diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt index 50e13f67f0..1a52e7b0d3 100644 --- a/eeschema/CMakeLists.txt +++ b/eeschema/CMakeLists.txt @@ -42,6 +42,8 @@ set( EESCHEMA_DLGS dialogs/dialog_edit_line_style.cpp dialogs/dialog_edit_line_style_base.cpp dialogs/dialog_edit_one_field.cpp + dialogs/dialog_edit_components_libid.cpp + dialogs/dialog_edit_components_libid_base.cpp dialogs/dialog_eeschema_options_base.cpp dialogs/dialog_eeschema_options.cpp dialogs/dialog_erc.cpp diff --git a/eeschema/dialogs/dialog_edit_components_libid.cpp b/eeschema/dialogs/dialog_edit_components_libid.cpp new file mode 100644 index 0000000000..c8a3c9b054 --- /dev/null +++ b/eeschema/dialogs/dialog_edit_components_libid.cpp @@ -0,0 +1,416 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright 2017 Jean-Pierre Charras, jp.charras@wanadoo.fr + * Copyright 1992-2017 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 2 + * 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 + */ + +/** + * @file eeschema/dialogs/dialog_edit_components_libid.cpp + * @brief Dialog to remap library id of components to an other library id + */ + + +#include <fctsys.h> +#include <dialog_edit_components_libid_base.h> +#include <schframe.h> +#include <class_drawpanel.h> +#include <sch_component.h> +#include <sch_reference_list.h> + +#define COL_REFS 0 +#define COL_CURR_LIBID 1 +#define COL_NEW_LIBID 2 + +// a helper class to handle components to edit +class CMP_CANDIDATE +{ +public: + SCH_COMPONENT* m_Component; // the schematic component + int m_Row; // the row index in m_grid + SCH_SCREEN* m_Screen; // the screen where m_Component lives + wxString m_Reference; // the schematic reference, only to display it in list + wxString m_InitialLibId; // the Lib Id of the component before any change + + CMP_CANDIDATE( SCH_COMPONENT* aComponent ) + { + m_Component = aComponent; + m_InitialLibId = m_Component->GetLibId().Format(); + m_Row = -1; + } + + // Returns a string like mylib:symbol_name from the LIB_ID of the component + wxString GetStringLibId() + { + return wxString( m_Component->GetLibId().Format().c_str() ); + } + + // Returns a string containing the reference of the component + wxString GetSchematicReference() + { + return m_Reference; + } +}; + + +/** + * DIALOG_EDIT_COMPONENTS_LIBID is a dialog to globally edit the LIB_ID of groups if components + * having the same initial LIB_ID. + * this is useful when you want: + * to move a symbol from a symbol library to an other symbol library + * to change the nickname of a library + * globally replace the symbol used by a group of components by an other symbol. + */ +class DIALOG_EDIT_COMPONENTS_LIBID : public DIALOG_EDIT_COMPONENTS_LIBID_BASE +{ +public: + DIALOG_EDIT_COMPONENTS_LIBID( SCH_EDIT_FRAME* aParent ); + + bool IsSchelaticModified() { return m_isModified; } + +private: + SCH_EDIT_FRAME* m_parent; + bool m_isModified; // set to true is the schemaic is modified + + std::vector<CMP_CANDIDATE> m_components; + + void initDlg(); + + // returns true if all new lib id are valid + bool validateLibIds(); + + // Reverts all changes already made + void revertChanges(); + + // Events handlers + // called on a right click or a left double click: + void onCellBrowseLib( wxGridEvent& event ) override; + void onApplyButton( wxCommandEvent& event ) override; + + void onCancel( wxCommandEvent& event ) override + { + if( m_isModified ) + revertChanges(); + event.Skip(); + } + + void onUndoChangesButton( wxCommandEvent& event ) override; + + bool TransferDataFromWindow() override; +}; + + +DIALOG_EDIT_COMPONENTS_LIBID::DIALOG_EDIT_COMPONENTS_LIBID( SCH_EDIT_FRAME* aParent ) + :DIALOG_EDIT_COMPONENTS_LIBID_BASE( aParent ) +{ + m_parent = aParent; + initDlg(); + + // Gives a min size to display m_grid, now it is populated: + int minwidth = 30 // a margin + + m_grid->GetRowLabelSize() + m_grid->GetColSize( COL_REFS ) + + m_grid->GetColSize( COL_CURR_LIBID ) + m_grid->GetColSize( COL_NEW_LIBID ); + m_panelGrid->SetMinSize( wxSize( minwidth, -1) ); + Layout(); + + // Now all widgets have the size fixed, call FinishDialogSettings + FinishDialogSettings(); +} + + +// A sort compare function to sort components list by LIB_ID +// inside the group of same LIB_ID, sort by reference +static bool sort_by_libid( const CMP_CANDIDATE& cmp1, const CMP_CANDIDATE& cmp2 ) +{ + if( cmp1.m_Component->GetLibId() == cmp2.m_Component->GetLibId() ) + return cmp1.m_Reference.Cmp( cmp2.m_Reference ) < 0; + + return cmp1.m_Component->GetLibId() < cmp2.m_Component->GetLibId(); +} + + +void DIALOG_EDIT_COMPONENTS_LIBID::initDlg() +{ + // Build the component list: +#if 0 + // This option build a component list that works fine to edit LIB_ID fields, but does not display + // all components in a complex hierarchy. + // the list is shorter, but can be look like there are missing components in list + SCH_SCREENS screens; + + for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() ) + { + for( SCH_ITEM* item = screen->GetDrawItems(); item; item = item->Next() ) + { + if( item->Type() == SCH_COMPONENT_T ) + { + CMP_CANDIDATE candidate( static_cast< SCH_COMPONENT* >( item ) ); + candidate.m_Screen = screen; + candidate.m_Reference = candidate.m_Component->GetField( REFERENCE )->GetFullyQualifiedText(); + m_components.push_back( candidate ); + } + } + } +#else + // This option build the full component list + // In complex hierarchies, the same component is in fact duplicated, but + // it is listed with different references (one by sheet instance) + // the list is larger and looks like it contains all components + SCH_SHEET_LIST sheets( g_RootSheet ); + SCH_REFERENCE_LIST references; + sheets.GetComponents( references ); + + for( unsigned ii = 0; ii < references.GetCount(); ii++ ) + { + SCH_REFERENCE& item = references[ii]; + CMP_CANDIDATE candidate( item.GetComp() ); + candidate.m_Screen = item.GetSheetPath().LastScreen(); + SCH_SHEET_PATH sheetpath = item.GetSheetPath(); + candidate.m_Reference = candidate.m_Component->GetRef( &sheetpath ); + // For multi units per package , add unit id. + // however, there is a problem: the unit id stored is always >= 1 + // and 1 for no multi units. + // so add unit id only if unit > 1 if the unit count is > 1 + // (can be 0 if the symbol is not found) + int unit = candidate.m_Component->GetUnitSelection( &sheetpath ); + int unitcount = candidate.m_Component->GetUnitCount(); + + if( unitcount > 1 || unit > 1 ) + { + candidate.m_Reference << wxChar( ('A' + unit -1) ); + } + + m_components.push_back( candidate ); + } +#endif + + if( m_components.size() == 0 ) + return; + + // now sort by lib id to create groups of items having the same lib id + std::sort( m_components.begin(), m_components.end(), sort_by_libid ); + + // Now, fill m_grid + wxString last_str_libid = m_components.front().GetStringLibId(); + int row = 0; + wxString refs; + + for( unsigned ii = 0; ii < m_components.size(); ii++ ) + { + CMP_CANDIDATE& cmp = m_components[ii]; + + wxString str_libid = cmp.GetStringLibId(); + + if( last_str_libid != str_libid || ii == m_components.size()-1 ) + { + if( ii == m_components.size()-1 ) + { + if( !refs.IsEmpty() ) + refs += " "; + + refs += cmp.GetSchematicReference(); + cmp.m_Row = row; + + last_str_libid = str_libid; + } + + if( m_grid->GetNumberRows() <= row ) + m_grid->AppendRows(); + + m_grid->SetCellValue( row, COL_REFS, refs ); + m_grid->SetReadOnly( row, COL_REFS ); + + m_grid->SetCellValue( row, COL_CURR_LIBID, last_str_libid ); + m_grid->SetReadOnly( row, COL_CURR_LIBID ); + + m_grid->SetCellRenderer( row, COL_REFS, new wxGridCellAutoWrapStringRenderer); + m_grid->AutoSizeRow( row, false ); + + // prepare next entry + last_str_libid = str_libid; + refs.Empty(); + row++; + } + + if( !refs.IsEmpty() ) + refs += " "; + + refs += cmp.GetSchematicReference(); + cmp.m_Row = row; + } + + m_grid->AutoSizeColumn( COL_CURR_LIBID ); + + // Gives a similar width to COL_NEW_LIBID because it can conatains similar strings + if( m_grid->GetColSize( COL_CURR_LIBID ) > m_grid->GetColSize( COL_NEW_LIBID ) ) + m_grid->SetColSize( COL_NEW_LIBID, m_grid->GetColSize( COL_CURR_LIBID ) ); +} + + +bool DIALOG_EDIT_COMPONENTS_LIBID::validateLibIds() +{ + int row_max = m_grid->GetNumberRows() - 1; + + for( int row = 0; row <= row_max; row++ ) + { + wxString new_libid = m_grid->GetCellValue( row, COL_NEW_LIBID ); + + if( new_libid.IsEmpty() ) + continue; + + // a new lib id is found. validate this new value + LIB_ID id; + id.Parse( new_libid ); + + if( !id.IsValid() ) + { + wxString msg; + msg.Printf( _( "Symbol library identifier '%s' is not valid at row %d!" ), new_libid, row+1 ); + wxMessageBox( msg ); + return false; + } + } + + return true; +} + + +void DIALOG_EDIT_COMPONENTS_LIBID::onApplyButton( wxCommandEvent& event ) +{ + if( TransferDataFromWindow() ) + m_parent->GetCanvas()->Refresh(); +} + + +void DIALOG_EDIT_COMPONENTS_LIBID::onUndoChangesButton( wxCommandEvent& event ) +{ + revertChanges(); + + int row_max = m_grid->GetNumberRows() - 1; + + for( int row = 0; row <= row_max; row++ ) + { + m_grid->SetCellValue( row, COL_NEW_LIBID, wxEmptyString ); + } + + m_isModified = false; +} + + +void DIALOG_EDIT_COMPONENTS_LIBID::onCellBrowseLib( wxGridEvent& event ) +{ + int row = event.GetRow(); + + SCH_BASE_FRAME::HISTORY_LIST dummy; + + auto sel = m_parent->SelectComponentFromLibrary( NULL, dummy, true, 0, 0 ); + + if( !sel.LibId.IsValid() ) + return; + + wxString new_libid; + new_libid = sel.LibId.Format(); + + m_grid->SetCellValue( row, COL_NEW_LIBID, new_libid ); + +} + + +bool DIALOG_EDIT_COMPONENTS_LIBID::TransferDataFromWindow() +{ + if( !validateLibIds() ) + return false; + + bool change = false; + int row_max = m_grid->GetNumberRows() - 1; + + for( int row = 0; row <= row_max; row++ ) + { + wxString new_libid = m_grid->GetCellValue( row, COL_NEW_LIBID ); + + if( new_libid.IsEmpty() || new_libid == m_grid->GetCellValue( row, COL_CURR_LIBID ) ) + continue; + + // a new lib id is found and was already validated. + // set this new value + LIB_ID id; + id.Parse( new_libid ); + + for( CMP_CANDIDATE& cmp : m_components ) + { + if( cmp.m_Row != row ) + continue; + + cmp.m_Component->SetLibId( id ); + change = true; + cmp.m_Screen->SetModify(); + } + } + + if( change ) + { + m_isModified = true; + SCH_SCREENS schematic; + schematic.UpdateSymbolLinks( true ); + } + + return true; +} + + +void DIALOG_EDIT_COMPONENTS_LIBID::revertChanges() +{ + bool change = false; + int row_max = m_grid->GetNumberRows() - 1; + + for( int row = 0; row <= row_max; row++ ) + { + for( CMP_CANDIDATE& cmp : m_components ) + { + if( cmp.m_Row != row ) + continue; + + LIB_ID id; + id.Parse( cmp.m_InitialLibId ); + + if( cmp.m_Component->GetLibId() != id ) + { + cmp.m_Component->SetLibId( id ); + change = true; + } + } + } + + if( change ) + { + SCH_SCREENS schematic; + schematic.UpdateSymbolLinks( true ); + m_parent->GetCanvas()->Refresh(); + } +} + + +bool InvokeDialogEditComponentsLibId( SCH_EDIT_FRAME* aCaller ) +{ + DIALOG_EDIT_COMPONENTS_LIBID dlg( aCaller ); + dlg.ShowModal(); + + return dlg.IsSchelaticModified(); +} \ No newline at end of file diff --git a/eeschema/dialogs/dialog_edit_components_libid_base.cpp b/eeschema/dialogs/dialog_edit_components_libid_base.cpp new file mode 100644 index 0000000000..c76ac1f477 --- /dev/null +++ b/eeschema/dialogs/dialog_edit_components_libid_base.cpp @@ -0,0 +1,109 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Aug 4 2017) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "dialog_edit_components_libid_base.h" + +/////////////////////////////////////////////////////////////////////////// + +DIALOG_EDIT_COMPONENTS_LIBID_BASE::DIALOG_EDIT_COMPONENTS_LIBID_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizerMain; + bSizerMain = new wxBoxSizer( wxVERTICAL ); + + m_panelGrid = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizerGrid; + bSizerGrid = new wxBoxSizer( wxVERTICAL ); + + m_grid = new wxGrid( m_panelGrid, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + + // Grid + m_grid->CreateGrid( 1, 3 ); + m_grid->EnableEditing( true ); + m_grid->EnableGridLines( true ); + m_grid->EnableDragGridSize( false ); + m_grid->SetMargins( 0, 0 ); + + // Columns + m_grid->SetColSize( 0, 500 ); + m_grid->SetColSize( 1, 150 ); + m_grid->SetColSize( 2, 150 ); + m_grid->EnableDragColMove( false ); + m_grid->EnableDragColSize( true ); + m_grid->SetColLabelSize( 30 ); + m_grid->SetColLabelValue( 0, _("Components") ); + m_grid->SetColLabelValue( 1, _("Current Symbol") ); + m_grid->SetColLabelValue( 2, _("New Symbol") ); + m_grid->SetColLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); + + // Rows + m_grid->EnableDragRowSize( true ); + m_grid->SetRowLabelSize( 30 ); + m_grid->SetRowLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); + + // Label Appearance + + // Cell Defaults + m_grid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP ); + m_grid->SetMinSize( wxSize( 700,-1 ) ); + + bSizerGrid->Add( m_grid, 1, wxALL|wxEXPAND, 5 ); + + + m_panelGrid->SetSizer( bSizerGrid ); + m_panelGrid->Layout(); + bSizerGrid->Fit( m_panelGrid ); + bSizerMain->Add( m_panelGrid, 1, wxEXPAND | wxALL, 5 ); + + m_staticline = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizerMain->Add( m_staticline, 0, wxEXPAND | wxALL, 5 ); + + wxBoxSizer* bSizerButtons; + bSizerButtons = new wxBoxSizer( wxHORIZONTAL ); + + m_sdbSizer = new wxStdDialogButtonSizer(); + m_sdbSizerOK = new wxButton( this, wxID_OK ); + m_sdbSizer->AddButton( m_sdbSizerOK ); + m_sdbSizerApply = new wxButton( this, wxID_APPLY ); + m_sdbSizer->AddButton( m_sdbSizerApply ); + m_sdbSizerCancel = new wxButton( this, wxID_CANCEL ); + m_sdbSizer->AddButton( m_sdbSizerCancel ); + m_sdbSizer->Realize(); + + bSizerButtons->Add( m_sdbSizer, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + m_buttonUndo = new wxButton( this, wxID_ANY, _("Undo Changes"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizerButtons->Add( m_buttonUndo, 0, wxTOP|wxBOTTOM|wxRIGHT, 5 ); + + + bSizerMain->Add( bSizerButtons, 0, wxALIGN_RIGHT, 5 ); + + + this->SetSizer( bSizerMain ); + this->Layout(); + + this->Centre( wxBOTH ); + + // Connect Events + m_grid->Connect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( DIALOG_EDIT_COMPONENTS_LIBID_BASE::onCellBrowseLib ), NULL, this ); + m_grid->Connect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( DIALOG_EDIT_COMPONENTS_LIBID_BASE::onCellBrowseLib ), NULL, this ); + m_sdbSizerApply->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EDIT_COMPONENTS_LIBID_BASE::onApplyButton ), NULL, this ); + m_sdbSizerCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EDIT_COMPONENTS_LIBID_BASE::onCancel ), NULL, this ); + m_buttonUndo->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EDIT_COMPONENTS_LIBID_BASE::onUndoChangesButton ), NULL, this ); +} + +DIALOG_EDIT_COMPONENTS_LIBID_BASE::~DIALOG_EDIT_COMPONENTS_LIBID_BASE() +{ + // Disconnect Events + m_grid->Disconnect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( DIALOG_EDIT_COMPONENTS_LIBID_BASE::onCellBrowseLib ), NULL, this ); + m_grid->Disconnect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( DIALOG_EDIT_COMPONENTS_LIBID_BASE::onCellBrowseLib ), NULL, this ); + m_sdbSizerApply->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EDIT_COMPONENTS_LIBID_BASE::onApplyButton ), NULL, this ); + m_sdbSizerCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EDIT_COMPONENTS_LIBID_BASE::onCancel ), NULL, this ); + m_buttonUndo->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EDIT_COMPONENTS_LIBID_BASE::onUndoChangesButton ), NULL, this ); + +} diff --git a/eeschema/dialogs/dialog_edit_components_libid_base.fbp b/eeschema/dialogs/dialog_edit_components_libid_base.fbp new file mode 100644 index 0000000000..a2420a242c --- /dev/null +++ b/eeschema/dialogs/dialog_edit_components_libid_base.fbp @@ -0,0 +1,534 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<wxFormBuilder_Project> + <FileVersion major="1" minor="13" /> + <object class="Project" expanded="1"> + <property name="class_decoration"></property> + <property name="code_generation">C++</property> + <property name="disconnect_events">1</property> + <property name="disconnect_mode">source_name</property> + <property name="disconnect_php_events">0</property> + <property name="disconnect_python_events">0</property> + <property name="embedded_files_path">res</property> + <property name="encoding">UTF-8</property> + <property name="event_generation">connect</property> + <property name="file">dialog_edit_components_libid_base</property> + <property name="first_id">1000</property> + <property name="help_provider">none</property> + <property name="internationalize">1</property> + <property name="name">dialog_edit_components_libid_base</property> + <property name="namespace"></property> + <property name="path">.</property> + <property name="precompiled_header"></property> + <property name="relative_path">1</property> + <property name="skip_lua_events">1</property> + <property name="skip_php_events">1</property> + <property name="skip_python_events">1</property> + <property name="ui_table">UI</property> + <property name="use_enum">0</property> + <property name="use_microsoft_bom">0</property> + <object class="Dialog" expanded="1"> + <property name="aui_managed">0</property> + <property name="aui_manager_style">wxAUI_MGR_DEFAULT</property> + <property name="bg"></property> + <property name="center">wxBOTH</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="enabled">1</property> + <property name="event_handler">impl_virtual</property> + <property name="extra_style"></property> + <property name="fg"></property> + <property name="font"></property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="maximum_size"></property> + <property name="minimum_size"></property> + <property name="name">DIALOG_EDIT_COMPONENTS_LIBID_BASE</property> + <property name="pos"></property> + <property name="size">797,311</property> + <property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property> + <property name="subclass">DIALOG_SHIM; dialog_shim.h</property> + <property name="title">Edit Components Links to Symbols in Libraries</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnActivate"></event> + <event name="OnActivateApp"></event> + <event name="OnAuiFindManager"></event> + <event name="OnAuiPaneButton"></event> + <event name="OnAuiPaneClose"></event> + <event name="OnAuiPaneMaximize"></event> + <event name="OnAuiPaneRestore"></event> + <event name="OnAuiRender"></event> + <event name="OnChar"></event> + <event name="OnClose"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnHibernate"></event> + <event name="OnIconize"></event> + <event name="OnIdle"></event> + <event name="OnInitDialog"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">bSizerMain</property> + <property name="orient">wxVERTICAL</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxEXPAND | wxALL</property> + <property name="proportion">1</property> + <object class="wxPanel" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size">-1,-1</property> + <property name="moveable">1</property> + <property name="name">m_panelGrid</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style">wxTAB_TRAVERSAL</property> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">bSizerGrid</property> + <property name="orient">wxVERTICAL</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL|wxEXPAND</property> + <property name="proportion">1</property> + <object class="wxGrid" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="autosize_cols">0</property> + <property name="autosize_rows">0</property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="cell_bg"></property> + <property name="cell_font"></property> + <property name="cell_horiz_alignment">wxALIGN_LEFT</property> + <property name="cell_text"></property> + <property name="cell_vert_alignment">wxALIGN_TOP</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="col_label_horiz_alignment">wxALIGN_CENTRE</property> + <property name="col_label_size">30</property> + <property name="col_label_values">"Components" "Current Symbol" "New Symbol"</property> + <property name="col_label_vert_alignment">wxALIGN_CENTRE</property> + <property name="cols">3</property> + <property name="column_sizes">500,150,150</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="drag_col_move">0</property> + <property name="drag_col_size">1</property> + <property name="drag_grid_size">0</property> + <property name="drag_row_size">1</property> + <property name="editing">1</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="grid_line_color"></property> + <property name="grid_lines">1</property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label_bg"></property> + <property name="label_font"></property> + <property name="label_text"></property> + <property name="margin_height">0</property> + <property name="margin_width">0</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size">700,-1</property> + <property name="moveable">1</property> + <property name="name">m_grid</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="row_label_horiz_alignment">wxALIGN_CENTRE</property> + <property name="row_label_size">30</property> + <property name="row_label_values"></property> + <property name="row_label_vert_alignment">wxALIGN_CENTRE</property> + <property name="row_sizes"></property> + <property name="rows">1</property> + <property name="show">1</property> + <property name="size"></property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnGridCellChange"></event> + <event name="OnGridCellLeftClick"></event> + <event name="OnGridCellLeftDClick">onCellBrowseLib</event> + <event name="OnGridCellRightClick">onCellBrowseLib</event> + <event name="OnGridCellRightDClick"></event> + <event name="OnGridCmdCellChange"></event> + <event name="OnGridCmdCellLeftClick"></event> + <event name="OnGridCmdCellLeftDClick"></event> + <event name="OnGridCmdCellRightClick"></event> + <event name="OnGridCmdCellRightDClick"></event> + <event name="OnGridCmdColSize"></event> + <event name="OnGridCmdEditorCreated"></event> + <event name="OnGridCmdEditorHidden"></event> + <event name="OnGridCmdEditorShown"></event> + <event name="OnGridCmdLabelLeftClick"></event> + <event name="OnGridCmdLabelLeftDClick"></event> + <event name="OnGridCmdLabelRightClick"></event> + <event name="OnGridCmdLabelRightDClick"></event> + <event name="OnGridCmdRangeSelect"></event> + <event name="OnGridCmdRowSize"></event> + <event name="OnGridCmdSelectCell"></event> + <event name="OnGridColSize"></event> + <event name="OnGridEditorCreated"></event> + <event name="OnGridEditorHidden"></event> + <event name="OnGridEditorShown"></event> + <event name="OnGridLabelLeftClick"></event> + <event name="OnGridLabelLeftDClick"></event> + <event name="OnGridLabelRightClick"></event> + <event name="OnGridLabelRightDClick"></event> + <event name="OnGridRangeSelect"></event> + <event name="OnGridRowSize"></event> + <event name="OnGridSelectCell"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + </object> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxEXPAND | wxALL</property> + <property name="proportion">0</property> + <object class="wxStaticLine" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_staticline</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style">wxLI_HORIZONTAL</property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALIGN_RIGHT</property> + <property name="proportion">0</property> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">bSizerButtons</property> + <property name="orient">wxHORIZONTAL</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL</property> + <property name="proportion">0</property> + <object class="wxStdDialogButtonSizer" expanded="1"> + <property name="Apply">1</property> + <property name="Cancel">1</property> + <property name="ContextHelp">0</property> + <property name="Help">0</property> + <property name="No">0</property> + <property name="OK">1</property> + <property name="Save">0</property> + <property name="Yes">0</property> + <property name="minimum_size"></property> + <property name="name">m_sdbSizer</property> + <property name="permission">protected</property> + <event name="OnApplyButtonClick">onApplyButton</event> + <event name="OnCancelButtonClick">onCancel</event> + <event name="OnContextHelpButtonClick"></event> + <event name="OnHelpButtonClick"></event> + <event name="OnNoButtonClick"></event> + <event name="OnOKButtonClick"></event> + <event name="OnSaveButtonClick"></event> + <event name="OnYesButtonClick"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxTOP|wxBOTTOM|wxRIGHT</property> + <property name="proportion">0</property> + <object class="wxButton" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default">0</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Undo Changes</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_buttonUndo</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnButtonClick">onUndoChangesButton</event> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + </object> + </object> + </object> + </object> + </object> +</wxFormBuilder_Project> diff --git a/eeschema/dialogs/dialog_edit_components_libid_base.h b/eeschema/dialogs/dialog_edit_components_libid_base.h new file mode 100644 index 0000000000..4d5b16a457 --- /dev/null +++ b/eeschema/dialogs/dialog_edit_components_libid_base.h @@ -0,0 +1,63 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Aug 4 2017) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#ifndef __DIALOG_EDIT_COMPONENTS_LIBID_BASE_H__ +#define __DIALOG_EDIT_COMPONENTS_LIBID_BASE_H__ + +#include <wx/artprov.h> +#include <wx/xrc/xmlres.h> +#include <wx/intl.h> +class DIALOG_SHIM; + +#include "dialog_shim.h" +#include <wx/colour.h> +#include <wx/settings.h> +#include <wx/string.h> +#include <wx/font.h> +#include <wx/grid.h> +#include <wx/gdicmn.h> +#include <wx/sizer.h> +#include <wx/panel.h> +#include <wx/statline.h> +#include <wx/button.h> +#include <wx/dialog.h> + +/////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +/// Class DIALOG_EDIT_COMPONENTS_LIBID_BASE +/////////////////////////////////////////////////////////////////////////////// +class DIALOG_EDIT_COMPONENTS_LIBID_BASE : public DIALOG_SHIM +{ + private: + + protected: + wxPanel* m_panelGrid; + wxGrid* m_grid; + wxStaticLine* m_staticline; + wxStdDialogButtonSizer* m_sdbSizer; + wxButton* m_sdbSizerOK; + wxButton* m_sdbSizerApply; + wxButton* m_sdbSizerCancel; + wxButton* m_buttonUndo; + + // Virtual event handlers, overide them in your derived class + virtual void onCellBrowseLib( wxGridEvent& event ) { event.Skip(); } + virtual void onApplyButton( wxCommandEvent& event ) { event.Skip(); } + virtual void onCancel( wxCommandEvent& event ) { event.Skip(); } + virtual void onUndoChangesButton( wxCommandEvent& event ) { event.Skip(); } + + + public: + + DIALOG_EDIT_COMPONENTS_LIBID_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Edit Components Links to Symbols in Libraries"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 797,311 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + ~DIALOG_EDIT_COMPONENTS_LIBID_BASE(); + +}; + +#endif //__DIALOG_EDIT_COMPONENTS_LIBID_BASE_H__ diff --git a/eeschema/eeschema_id.h b/eeschema/eeschema_id.h index 56f24bdd66..93ec30f06d 100644 --- a/eeschema/eeschema_id.h +++ b/eeschema/eeschema_id.h @@ -66,6 +66,7 @@ enum id_eeschema_frm ID_RESCUE_CACHED, ID_EDIT_SYM_LIB_TABLE, ID_REMAP_SYMBOLS, + ID_EDIT_COMPONENTS_TO_SYMBOLS_LIB_ID, /* Schematic editor horizontal toolbar IDs */ ID_HIERARCHY, diff --git a/eeschema/invoke_sch_dialog.h b/eeschema/invoke_sch_dialog.h index bc7f6cc50a..1691d2e03d 100644 --- a/eeschema/invoke_sch_dialog.h +++ b/eeschema/invoke_sch_dialog.h @@ -98,4 +98,11 @@ int InvokeDialogUpdateFields( SCH_EDIT_FRAME* aCaller, #define NET_PLUGIN_CHANGE 1 int InvokeDialogNetList( SCH_EDIT_FRAME* aCaller ); +/** + * Run a dialog to modify the LIB_ID of components for instance when a symbol has + * moved from a symbol library to an other symbol library + * @return true if changes are made, false if no change + */ +bool InvokeDialogEditComponentsLibId( SCH_EDIT_FRAME* aCaller ); + #endif // INVOKE_SCH_DIALOG_H_ diff --git a/eeschema/menubar.cpp b/eeschema/menubar.cpp index fde01bd057..3fc4aee833 100644 --- a/eeschema/menubar.cpp +++ b/eeschema/menubar.cpp @@ -454,6 +454,13 @@ void prepareEditMenu( wxMenu* aParentMenu ) _( "Update Field Values" ), _( "Sets component fields to original library values" ), KiBitmap( update_fields_xpm ) ); + + // Edit components to symbols library links (change LIB_ID values) + aParentMenu->AppendSeparator(); + AddMenuItem( aParentMenu, ID_EDIT_COMPONENTS_TO_SYMBOLS_LIB_ID, + _( "Edit Components to Symbol Library Links" ), + _( "Edit components to symbols library links to switch to an other library link (library IDs)" ), + KiBitmap( update_fields_xpm ) ); } diff --git a/eeschema/schframe.cpp b/eeschema/schframe.cpp index 9a6320ad68..9800551956 100644 --- a/eeschema/schframe.cpp +++ b/eeschema/schframe.cpp @@ -252,6 +252,7 @@ BEGIN_EVENT_TABLE( SCH_EDIT_FRAME, EDA_DRAW_FRAME ) EVT_TOOL( ID_TO_LIBVIEW, SCH_EDIT_FRAME::OnOpenLibraryViewer ) EVT_TOOL( ID_RESCUE_CACHED, SCH_EDIT_FRAME::OnRescueProject ) EVT_MENU( ID_REMAP_SYMBOLS, SCH_EDIT_FRAME::OnRemapSymbols ) + EVT_MENU( ID_EDIT_COMPONENTS_TO_SYMBOLS_LIB_ID, SCH_EDIT_FRAME::OnEditComponentSymbolsId ) EVT_TOOL( ID_RUN_PCB, SCH_EDIT_FRAME::OnOpenPcbnew ) EVT_TOOL( ID_RUN_PCB_MODULE_EDITOR, SCH_EDIT_FRAME::OnOpenPcbModuleEditor ) @@ -1278,6 +1279,18 @@ void SCH_EDIT_FRAME::OnRemapSymbols( wxCommandEvent& event ) } +// This method is not the same as OnRemapSymbols. +// It allows renaming the lib id of groups of components when a symbol +// has moved from a library to an other library. +// For instance to rename libname1::mysymbol to libname2::mysymbol +// or any other lib id name +void SCH_EDIT_FRAME::OnEditComponentSymbolsId( wxCommandEvent& event ) +{ + InvokeDialogEditComponentsLibId( this ); + m_canvas->Refresh( true ); +} + + void SCH_EDIT_FRAME::OnExit( wxCommandEvent& event ) { Close( false ); diff --git a/eeschema/schframe.h b/eeschema/schframe.h index d9655c88b9..86abc4a063 100644 --- a/eeschema/schframe.h +++ b/eeschema/schframe.h @@ -854,6 +854,10 @@ private: void OnOpenLibraryEditor( wxCommandEvent& event ); void OnRescueProject( wxCommandEvent& event ); void OnRemapSymbols( wxCommandEvent& aEvent ); + // a helper function to run the dialog that allows to rename the symbol library Id of + // groups of components, for instance after a symbol has moved from a library to + // an other library + void OnEditComponentSymbolsId( wxCommandEvent& aEvent ); void OnPreferencesOptions( wxCommandEvent& event ); void OnCancelCurrentCommand( wxCommandEvent& aEvent ); diff --git a/kicad/menubar.cpp b/kicad/menubar.cpp index 6611db00aa..5bbc603561 100644 --- a/kicad/menubar.cpp +++ b/kicad/menubar.cpp @@ -1,7 +1,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2009 Wayne Stambaugh <stambaughw@verizon.net> * Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors. * @@ -411,7 +411,7 @@ void KICAD_MANAGER_FRAME::ReCreateMenuBar() kicad_Manager_Hokeys_Descr, HK_RUN_PCBNEW ); AddMenuItem( toolsMenu, ID_TO_PCB, msg, KiBitmap( pcbnew_xpm ) ); - msg = AddHotkeyName( _( "Edit PCB Footprint" ), + msg = AddHotkeyName( _( "Edit PCB Footprints" ), kicad_Manager_Hokeys_Descr, HK_RUN_FPEDITOR ); AddMenuItem( toolsMenu, ID_TO_PCB_FP_EDITOR, msg, KiBitmap( module_editor_xpm ) );