From 2283bcda4cc8351dc271c424967841f1e6d09f2b Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Wed, 18 Apr 2018 10:31:33 +0100 Subject: [PATCH] Add text item property options when updating footprints. Fixes: lp:1753286 * https://bugs.launchpad.net/kicad/+bug/1753286 (cherry picked from commit b94dd87) --- pcbnew/CMakeLists.txt | 1 + pcbnew/dialogs/dialog_exchange_footprints.cpp | 362 ++++------ pcbnew/dialogs/dialog_exchange_footprints.h | 20 +- .../dialog_exchange_footprints_base.cpp | 73 +- .../dialog_exchange_footprints_base.fbp | 672 ++++++++---------- .../dialogs/dialog_exchange_footprints_base.h | 23 +- .../export_footprint_associations.cpp | 83 +++ pcbnew/pcb_edit_frame.h | 8 +- 8 files changed, 591 insertions(+), 651 deletions(-) create mode 100644 pcbnew/exporters/export_footprint_associations.cpp diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index 6ca7487f21..1084e82335 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -176,6 +176,7 @@ set( PCBNEW_IMPORT_DXF set( PCBNEW_EXPORTERS exporters/export_d356.cpp + exporters/export_footprint_associations.cpp exporters/export_gencad.cpp exporters/export_idf.cpp exporters/export_vrml.cpp diff --git a/pcbnew/dialogs/dialog_exchange_footprints.cpp b/pcbnew/dialogs/dialog_exchange_footprints.cpp index 4aee9e4108..349e032b17 100644 --- a/pcbnew/dialogs/dialog_exchange_footprints.cpp +++ b/pcbnew/dialogs/dialog_exchange_footprints.cpp @@ -26,26 +26,17 @@ #include #include -#include -#include -#include #include #include #include #include - #include #include #include #include - -#include -#include -#include #include - -static bool RecreateCmpFile( BOARD * aBrd, const wxString& aFullCmpFileName ); +#include #define ID_MATCH_FP_ALL 4200 @@ -59,59 +50,38 @@ int DIALOG_EXCHANGE_FOOTPRINTS::m_matchModeForUpdateSelected = ID_MATCH_FP_REF int DIALOG_EXCHANGE_FOOTPRINTS::m_matchModeForExchangeSelected = ID_MATCH_FP_REF; -DIALOG_EXCHANGE_FOOTPRINTS::DIALOG_EXCHANGE_FOOTPRINTS( PCB_EDIT_FRAME* parent, MODULE* Module, - bool updateMode ) : - DIALOG_EXCHANGE_FOOTPRINTS_BASE( parent ), m_commit( parent ) +DIALOG_EXCHANGE_FOOTPRINTS::DIALOG_EXCHANGE_FOOTPRINTS( PCB_EDIT_FRAME* aParent, MODULE* aModule, + bool updateMode ) : + DIALOG_EXCHANGE_FOOTPRINTS_BASE( aParent ), + m_commit( aParent ), + m_parent( aParent ), + m_currentModule( aModule ), + m_updateMode( updateMode ) { - m_parent = parent; - m_currentModule = Module; - m_updateMode = updateMode; - - init( m_updateMode ); - - // DIALOG_SHIM needs a unique hash_key because classname is not sufficient - // because the update and change versions of this dialog have different controls. - m_hash_key = TO_UTF8( GetTitle() ); - - // Ensure m_closeButton (with id = wxID_CANCEL) has the right label - // (to fix automatic renaming of button label ) - m_closeButton->SetLabel( _( "Close" ) ); - - // Now all widgets have the size fixed, call FinishDialogSettings - FinishDialogSettings(); -} - - -void DIALOG_EXCHANGE_FOOTPRINTS::OnQuit( wxCommandEvent& event ) -{ - Show( false ); - EndQuasiModal( wxID_CANCEL ); -} - - -void DIALOG_EXCHANGE_FOOTPRINTS::init( bool updateMode ) -{ - SetFocus(); - wxString title = updateMode ? _( "Update Footprints from Library" ) : _( "Change Footprints" ); wxString verb = updateMode ? _( "Update" ) : _( "Change" ); wxString label; SetTitle( title ); - if( updateMode ) + if( m_updateMode ) { label.Printf( m_matchAll->GetLabel(), verb ); m_matchAll->SetLabel( label ); - - m_middleSizer->Show( false ); + m_changeSizer->Show( false ); } else { m_upperSizer->FindItem( m_matchAll )->Show( false ); if( m_currentModule ) + { m_newID->AppendText( FROM_UTF8( m_currentModule->GetFPID().Format().c_str() ) ); + SetInitialFocus( m_newID ); + } + else + SetInitialFocus( m_specifiedRef ); + m_newIDBrowseButton->SetBitmap( KiBitmap( library_browse_xpm ) ); } @@ -171,6 +141,19 @@ void DIALOG_EXCHANGE_FOOTPRINTS::init( bool updateMode ) case ID_MATCH_FP_ID: OnMatchIDClicked( event ); } + + // DIALOG_SHIM needs a unique hash_key because classname is not sufficient + // because the update and change versions of this dialog have different controls. + m_hash_key = TO_UTF8( GetTitle() ); + + // Ensure m_closeButton (with id = wxID_CANCEL) has the right label + // (to fix automatic renaming of button label ) + m_sdbSizer1Cancel->SetLabel( _( "Close" ) ); + + m_sdbSizer1Apply->SetDefault(); + + // Now all widgets have the size fixed, call FinishDialogSettings + FinishDialogSettings(); } @@ -209,15 +192,14 @@ bool DIALOG_EXCHANGE_FOOTPRINTS::isMatch( MODULE* aModule ) case ID_MATCH_FP_ALL: return true; case ID_MATCH_FP_REF: - // currentModule case goes through changeCurrentFootprint, so we only have + // currentModule case goes through processCurrentModule, so we only have // to handle specifiedRef case return aModule->GetReference() == m_specifiedRef->GetValue(); case ID_MATCH_FP_VAL: // currentValue must also check FPID so we don't get accidental matches that // the user didn't intend if( m_currentModule ) - return aModule->GetValue() == m_currentModule->GetValue() - && aModule->GetFPID() == m_currentModule->GetFPID(); + return aModule->GetValue() == m_currentModule->GetValue() && aModule->GetFPID() == m_currentModule->GetFPID(); else return aModule->GetValue() == m_specifiedValue->GetValue(); case ID_MATCH_FP_ID: @@ -305,17 +287,18 @@ void DIALOG_EXCHANGE_FOOTPRINTS::OnMatchIDClicked( wxCommandEvent& event ) } -void DIALOG_EXCHANGE_FOOTPRINTS::OnApplyClick( wxCommandEvent& event ) +void DIALOG_EXCHANGE_FOOTPRINTS::OnApplyClicked( wxCommandEvent& event ) { - bool result = false; + bool result = false; + wxBusyCursor dummy; m_MessageWindow->Clear(); m_MessageWindow->Flush( true ); if( getMatchMode() == ID_MATCH_FP_REF && m_currentModule ) - result = changeCurrentFootprint(); + result = processCurrentModule(); else - result = changeSameFootprints(); + result = processMatchingModules(); if( result ) { @@ -329,126 +312,100 @@ void DIALOG_EXCHANGE_FOOTPRINTS::OnApplyClick( wxCommandEvent& event ) } -void DIALOG_EXCHANGE_FOOTPRINTS::RebuildCmpList( wxCommandEvent& event ) +bool DIALOG_EXCHANGE_FOOTPRINTS::processCurrentModule() { - wxString msg; - REPORTER& reporter = m_MessageWindow->Reporter(); - m_MessageWindow->Clear(); - m_MessageWindow->Flush( true ); + LIB_ID newFPID; - // Build the .cmp file name from the board name - wxFileName fn = m_parent->GetBoard()->GetFileName(); - fn.SetExt( ComponentFileExtension ); - - if( RecreateCmpFile( m_parent->GetBoard(), fn.GetFullPath() ) ) - { - msg.Printf( _( "File \"%s\" created\n" ), GetChars( fn.GetFullPath() ) ); - reporter.Report( msg, REPORTER::RPT_INFO ); - } + if( m_updateMode ) + newFPID = m_currentModule->GetFPID(); else { - msg.Printf( _( "** Could not create file \"%s\" ***\n" ), - GetChars( fn.GetFullPath() ) ); - reporter.Report( msg, REPORTER::RPT_ERROR ); + wxString newFPIDStr = m_newID->GetValue(); + + if( newFPIDStr.IsEmpty() ) + return false; + + newFPID = LIB_ID( newFPIDStr ); } + + return processModule( m_currentModule, newFPID ); } -bool DIALOG_EXCHANGE_FOOTPRINTS::changeCurrentFootprint() -{ - if( m_updateMode ) - return change_1_Module( m_currentModule, m_currentModule->GetFPID(), true ); - - wxString newFPID = m_newID->GetValue(); - - if( newFPID == wxEmptyString ) - return false; - - return change_1_Module( m_currentModule, newFPID, true ); -} - - -bool DIALOG_EXCHANGE_FOOTPRINTS::changeSameFootprints() +bool DIALOG_EXCHANGE_FOOTPRINTS::processMatchingModules() { MODULE* Module; MODULE* PtBack; bool change = false; wxString newFPID = m_newID->GetValue(); wxString value; - int ShowErr = 3; // Post 3 error messages max. - if( m_parent->GetBoard()->m_Modules == NULL ) + if( !m_parent->GetBoard()->m_Modules ) return false; if( !m_updateMode && newFPID == wxEmptyString ) return false; - /* The change is done from the last module because - * change_1_Module () modifies the last item in the list. - * - * note: for the first module in chain (the last here), Module->Back() - * points the board or is NULL + /* The change is done from the last module because processModule() modifies the last item + * in the list. + * Note: for the first module in chain (the last here), Module->Back() points to the board + * or is NULL. */ Module = m_parent->GetBoard()->m_Modules.GetLast(); - for( ; Module && ( Module->Type() == PCB_MODULE_T ); Module = PtBack ) + for( ; Module && Module->Type() == PCB_MODULE_T; Module = PtBack ) { PtBack = Module->Back(); if( !isMatch( Module ) ) continue; - bool result; if( m_updateMode ) - result = change_1_Module( Module, Module->GetFPID(), ShowErr ); + { + if( processModule( Module, Module->GetFPID()) ) + change = true; + } else - result = change_1_Module( Module, newFPID, ShowErr ); - - if( result ) - change = true; - else if( ShowErr ) - ShowErr--; + { + if( processModule( Module, newFPID ) ) + change = true; + } } return change; } -bool DIALOG_EXCHANGE_FOOTPRINTS::change_1_Module( MODULE* aModule, - const LIB_ID& aNewFootprintFPID, - bool aShowError ) +bool DIALOG_EXCHANGE_FOOTPRINTS::processModule( MODULE* aModule, const LIB_ID& aNewFPID ) { - MODULE* newModule; - wxString msg; - - if( aModule == NULL ) - return false; - - wxBusyCursor dummy; + LIB_ID oldFPID = aModule->GetFPID(); REPORTER& reporter = m_MessageWindow->Reporter(); + wxString msg; - // Copy parameters from the old footprint. - LIB_ID oldFootprintFPID = aModule->GetFPID(); + // Load new module. + msg.Printf( _( "%s footprint \"%s\" (from \"%s\") to \"%s\"" ), + m_updateMode ? _( "Update" ) : _( "Change" ), + aModule->GetReference(), + oldFPID.Format().c_str(), + aNewFPID.Format().c_str() ); - // Load module. - msg.Printf( _( "Change footprint \"%s\" (from \"%s\") to \"%s\"" ), - GetChars( aModule->GetReference() ), - oldFootprintFPID.Format().c_str(), - aNewFootprintFPID.Format().c_str() ); + MODULE* newModule = m_parent->LoadFootprint( aNewFPID ); - newModule = m_parent->LoadFootprint( aNewFootprintFPID ); - - if( newModule == NULL ) // New module not found. + if( !newModule ) { - msg << ": " << _( "footprint not found" ); + msg << ": " << _( "*** footprint not found ***" ); reporter.Report( msg, REPORTER::RPT_ERROR ); return false; } - m_parent->Exchange_Module( aModule, newModule, m_commit ); + m_parent->Exchange_Module( aModule, newModule, m_commit, + m_removeExtraBox->GetValue(), + m_resetTextItemLayers->GetValue(), + m_resetTextItemEffects->GetValue() ); if( aModule == m_currentModule ) m_currentModule = newModule; + if( aModule == m_parent->GetCurItem() ) m_parent->SetCurItem( newModule ); @@ -459,48 +416,89 @@ bool DIALOG_EXCHANGE_FOOTPRINTS::change_1_Module( MODULE* aModule, } -void PCB_EDIT_FRAME::Exchange_Module( MODULE* aOldModule, - MODULE* aNewModule, - BOARD_COMMIT& aCommit ) +void processTextItem( const TEXTE_MODULE& aSrc, TEXTE_MODULE& aDest, + bool resetText, bool resetTextLayers, bool resetTextEffects ) { - aNewModule->SetParent( GetBoard() ); + if( !resetText ) + aDest.SetText( aSrc.GetText() ); + + if( !resetTextLayers ) + { + aDest.SetLayer( aSrc.GetLayer() ); + aDest.SetVisible( aSrc.IsVisible() ); + } + + if( !resetTextEffects ) + aDest.SetEffects( aSrc ); +} + + +TEXTE_MODULE* getMatchingTextItem( TEXTE_MODULE* aRefItem, MODULE* aModule ) +{ + for( auto iItem = aModule->GraphicalItemsList().GetFirst(); iItem; iItem = iItem->Next() ) + { + TEXTE_MODULE* candidate = dyn_cast( iItem ); + if( candidate && candidate->GetText() == aRefItem->GetText() ) + return candidate; + } + + return nullptr; +} + + +void PCB_EDIT_FRAME::Exchange_Module( MODULE* aSrc, MODULE* aDest, BOARD_COMMIT& aCommit, + bool deleteExtraTexts, + bool resetTextLayers, bool resetTextEffects ) +{ + aDest->SetParent( GetBoard() ); /* place module without ratsnest refresh: this will be made later * when all modules are on board */ - PlaceModule( aNewModule, NULL, false ); + PlaceModule( aDest, nullptr, false ); // Copy full placement and pad net names (when possible) // but not local settings like clearances (use library values) - aOldModule->CopyNetlistSettings( aNewModule, false ); + aSrc->CopyNetlistSettings( aDest, false ); // Copy reference - aNewModule->SetReference( aOldModule->GetReference() ); + processTextItem( aSrc->Reference(), aDest->Reference(), + // never reset reference text + false, + resetTextLayers, resetTextEffects ); - // Copy value unless it is a proxy for the footprint ID (a good example is replacing a - // footprint with value "MoutingHole-2.5mm" with one of value "MountingHole-4mm"). - if( aOldModule->GetValue() != aOldModule->GetFPID().GetLibItemName() ) - aNewModule->SetValue( aOldModule->GetValue() ); + // Copy value + processTextItem( aSrc->Value(), aDest->Value(), + // reset value text only when it is a proxy for the footprint ID + // (cf replacing value "MountingHole-2.5mm" with "MountingHole-4.0mm") + aSrc->GetValue() == aSrc->GetFPID().GetLibItemName(), + resetTextLayers, resetTextEffects ); - // Compare the footprint name only, in case the nickname is empty or in case - // user moved the footprint to a new library. Chances are if footprint name is - // same then the footprint is very nearly the same and the two texts should - // be kept at same size, position, and rotation. - if( aNewModule->GetFPID().GetLibItemName() == aOldModule->GetFPID().GetLibItemName() ) + // Copy fields in accordance with the reset* flags + for( BOARD_ITEM* item = aSrc->GraphicalItemsList().GetFirst(); item; item = item->Next() ) { - aNewModule->Reference().SetEffects( aOldModule->Reference() ); - aNewModule->Value().SetEffects( aOldModule->Value() ); + TEXTE_MODULE* srcItem = dyn_cast( item ); + + if( srcItem ) + { + TEXTE_MODULE* destItem = getMatchingTextItem( srcItem, aDest ); + + if( destItem ) + processTextItem( *srcItem, *destItem, false, resetTextLayers, resetTextEffects ); + else if( !deleteExtraTexts ) + aDest->GraphicalItemsList().Append( new TEXTE_MODULE( *srcItem ) ); + } } - // Updating other parameters - aNewModule->SetTimeStamp( aOldModule->GetTimeStamp() ); - aNewModule->SetPath( aOldModule->GetPath() ); + // Updating other parameters + aDest->SetTimeStamp( aSrc->GetTimeStamp() ); + aDest->SetPath( aSrc->GetPath() ); - aCommit.Remove( aOldModule ); - aCommit.Add( aNewModule ); + aCommit.Remove( aSrc ); + aCommit.Add( aDest ); // @todo LEGACY should be unnecessary GetBoard()->m_Status_Pcb = 0; - aNewModule->ClearFlags(); + aDest->ClearFlags(); } @@ -522,73 +520,3 @@ void DIALOG_EXCHANGE_FOOTPRINTS::ViewAndSelectFootprint( wxCommandEvent& event ) } -void PCB_EDIT_FRAME::RecreateCmpFileFromBoard( wxCommandEvent& aEvent ) -{ - wxFileName fn; - MODULE* module = GetBoard()->m_Modules; - wxString msg; - wxString wildcard; - - if( module == NULL ) - { - DisplayError( this, _( "No footprints!" ) ); - return; - } - - // Build the .cmp file name from the board name - fn = GetBoard()->GetFileName(); - fn.SetExt( ComponentFileExtension ); - wildcard = ComponentFileWildcard(); - - wxString pro_dir = wxPathOnly( Prj().GetProjectFullName() ); - - wxFileDialog dlg( this, _( "Save Footprint Association File" ), pro_dir, - fn.GetFullName(), wildcard, - wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); - - if( dlg.ShowModal() == wxID_CANCEL ) - return; - - fn = dlg.GetPath(); - - if( ! RecreateCmpFile( GetBoard(), fn.GetFullPath() ) ) - { - msg.Printf( _( "Could not create file \"%s\"" ), GetChars(fn.GetFullPath() ) ); - DisplayError( this, msg ); - return; - } -} - - -bool RecreateCmpFile( BOARD * aBrd, const wxString& aFullCmpFileName ) -{ - FILE* cmpFile; - - cmpFile = wxFopen( aFullCmpFileName, wxT( "wt" ) ); - - if( cmpFile == NULL ) - return false; - - fprintf( cmpFile, "Cmp-Mod V01 Created by PcbNew date = %s\n", TO_UTF8( DateAndTime() ) ); - - MODULE* module = aBrd->m_Modules; - for( ; module != NULL; module = module->Next() ) - { - fprintf( cmpFile, "\nBeginCmp\n" ); - fprintf( cmpFile, "TimeStamp = %8.8lX\n", (unsigned long)module->GetTimeStamp() ); - fprintf( cmpFile, "Path = %s\n", TO_UTF8( module->GetPath() ) ); - fprintf( cmpFile, "Reference = %s;\n", - !module->GetReference().IsEmpty() ? - TO_UTF8( module->GetReference() ) : "[NoRef]" ); - fprintf( cmpFile, "ValeurCmp = %s;\n", - !module->GetValue().IsEmpty() ? - TO_UTF8( module->GetValue() ) : "[NoVal]" ); - fprintf( cmpFile, "IdModule = %s;\n", module->GetFPID().Format().c_str() ); - fprintf( cmpFile, "EndCmp\n" ); - } - - fprintf( cmpFile, "\nEndListe\n" ); - fclose( cmpFile ); - - return true; -} diff --git a/pcbnew/dialogs/dialog_exchange_footprints.h b/pcbnew/dialogs/dialog_exchange_footprints.h index 2c3283bb1f..dbb2d6a562 100644 --- a/pcbnew/dialogs/dialog_exchange_footprints.h +++ b/pcbnew/dialogs/dialog_exchange_footprints.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2010-2014 Jean-Pierre Charras, jean-pierre.charras at wanadoo.fr - * Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2018 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 @@ -35,6 +35,7 @@ class MODULE; class DIALOG_EXCHANGE_FOOTPRINTS : public DIALOG_EXCHANGE_FOOTPRINTS_BASE { private: + BOARD_COMMIT m_commit; PCB_EDIT_FRAME* m_parent; MODULE* m_currentModule; bool m_updateMode; @@ -45,7 +46,6 @@ private: public: DIALOG_EXCHANGE_FOOTPRINTS( PCB_EDIT_FRAME* aParent, MODULE* aModule, bool updateMode ); - ~DIALOG_EXCHANGE_FOOTPRINTS() { }; private: void updateMatchModeRadioButtons( wxUpdateUIEvent& event ) override; @@ -53,12 +53,8 @@ private: void OnMatchRefClicked( wxCommandEvent& event ) override; void OnMatchValueClicked( wxCommandEvent& event ) override; void OnMatchIDClicked( wxCommandEvent& event ) override; - void OnApplyClick( wxCommandEvent& event ) override; - void OnQuit( wxCommandEvent& event ) override; + void OnApplyClicked( wxCommandEvent& event ) override; void ViewAndSelectFootprint( wxCommandEvent& event ) override; - void RebuildCmpList( wxCommandEvent& event ) override; - - void init( bool updateMode ); int getMatchMode(); void setMatchMode( int aMatchMode ); @@ -66,13 +62,9 @@ private: wxRadioButton* getRadioButtonForMode(); bool isMatch( MODULE* ); - bool changeCurrentFootprint(); - bool changeSameFootprints(); - bool change_1_Module( MODULE* aModule, - const LIB_ID& aNewFootprintFPID, - bool eShowError ); - - BOARD_COMMIT m_commit; + bool processCurrentModule(); + bool processMatchingModules(); + bool processModule( MODULE* aModule, const LIB_ID& aNewFPID ); }; #endif // DIALOG_EXCHANGE_FOOTPRINTS_H_ diff --git a/pcbnew/dialogs/dialog_exchange_footprints_base.cpp b/pcbnew/dialogs/dialog_exchange_footprints_base.cpp index ff2a928b08..41cb721838 100644 --- a/pcbnew/dialogs/dialog_exchange_footprints_base.cpp +++ b/pcbnew/dialogs/dialog_exchange_footprints_base.cpp @@ -1,8 +1,8 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Aug 4 2017) +// C++ code generated with wxFormBuilder (version Dec 30 2017) // http://www.wxformbuilder.org/ // -// PLEASE DO "NOT" EDIT THIS FILE! +// PLEASE DO *NOT* EDIT THIS FILE! /////////////////////////////////////////////////////////////////////////// #include "wx_html_report_panel.h" @@ -67,16 +67,16 @@ DIALOG_EXCHANGE_FOOTPRINTS_BASE::DIALOG_EXCHANGE_FOOTPRINTS_BASE( wxWindow* pare m_mainSizer->Add( m_upperSizer, 0, wxALL|wxEXPAND, 5 ); - m_middleSizer = new wxBoxSizer( wxVERTICAL ); + m_changeSizer = new wxBoxSizer( wxVERTICAL ); wxStaticLine* staticline1; staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - m_middleSizer->Add( staticline1, 0, wxBOTTOM|wxEXPAND, 2 ); + m_changeSizer->Add( staticline1, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 2 ); wxStaticText* newIdLabel; newIdLabel = new wxStaticText( this, wxID_ANY, _("New footprint identifier:"), wxDefaultPosition, wxDefaultSize, 0 ); newIdLabel->Wrap( -1 ); - m_middleSizer->Add( newIdLabel, 0, wxLEFT|wxRIGHT|wxTOP|wxEXPAND, 5 ); + m_changeSizer->Add( newIdLabel, 0, wxLEFT|wxRIGHT|wxTOP|wxEXPAND, 5 ); wxFlexGridSizer* fgSizer2; fgSizer2 = new wxFlexGridSizer( 0, 2, 0, 0 ); @@ -93,45 +93,44 @@ DIALOG_EXCHANGE_FOOTPRINTS_BASE::DIALOG_EXCHANGE_FOOTPRINTS_BASE( wxWindow* pare fgSizer2->Add( m_newIDBrowseButton, 0, wxALL|wxALIGN_CENTER_VERTICAL, 0 ); - m_middleSizer->Add( fgSizer2, 0, wxEXPAND, 0 ); + m_changeSizer->Add( fgSizer2, 0, wxEXPAND, 0 ); - m_mainSizer->Add( m_middleSizer, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); + m_mainSizer->Add( m_changeSizer, 0, wxEXPAND|wxALL, 5 ); + + m_updateOptionsSizer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Update Options") ), wxVERTICAL ); + + m_removeExtraBox = new wxCheckBox( m_updateOptionsSizer->GetStaticBox(), wxID_ANY, _("Remove text items which are not in library footprint"), wxDefaultPosition, wxDefaultSize, 0 ); + m_removeExtraBox->SetToolTip( _("Removes fields that do not occur in the original library symbols") ); + + m_updateOptionsSizer->Add( m_removeExtraBox, 0, wxBOTTOM|wxRIGHT, 5 ); + + m_resetTextItemLayers = new wxCheckBox( m_updateOptionsSizer->GetStaticBox(), wxID_ANY, _("Reset text layers and visibilities"), wxDefaultPosition, wxDefaultSize, 0 ); + m_updateOptionsSizer->Add( m_resetTextItemLayers, 0, wxBOTTOM|wxRIGHT, 5 ); + + m_resetTextItemEffects = new wxCheckBox( m_updateOptionsSizer->GetStaticBox(), wxID_ANY, _("Reset text sizes, styles and positions"), wxDefaultPosition, wxDefaultSize, 0 ); + m_updateOptionsSizer->Add( m_resetTextItemEffects, 0, wxBOTTOM|wxRIGHT, 5 ); + + + m_mainSizer->Add( m_updateOptionsSizer, 0, wxEXPAND|wxALL, 5 ); m_MessageWindow = new WX_HTML_REPORT_PANEL( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_MessageWindow->SetMinSize( wxSize( -1,300 ) ); + m_MessageWindow->SetMinSize( wxSize( -1,240 ) ); m_mainSizer->Add( m_MessageWindow, 5, wxALL|wxEXPAND, 5 ); wxStaticLine* staticline2; staticline2 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - m_mainSizer->Add( staticline2, 0, wxEXPAND | wxALL, 5 ); + m_mainSizer->Add( staticline2, 0, wxEXPAND|wxALL, 5 ); - wxBoxSizer* bottomSizer; - bottomSizer = new wxBoxSizer( wxHORIZONTAL ); + m_sdbSizer1 = new wxStdDialogButtonSizer(); + m_sdbSizer1Apply = new wxButton( this, wxID_APPLY ); + m_sdbSizer1->AddButton( m_sdbSizer1Apply ); + m_sdbSizer1Cancel = new wxButton( this, wxID_CANCEL ); + m_sdbSizer1->AddButton( m_sdbSizer1Cancel ); + m_sdbSizer1->Realize(); - m_exportButton = new wxButton( this, wxID_ANY, _("Export Footprint Associations"), wxDefaultPosition, wxDefaultSize, 0 ); - bottomSizer->Add( m_exportButton, 0, wxALL, 5 ); - - wxBoxSizer* paddingSizer; - paddingSizer = new wxBoxSizer( wxHORIZONTAL ); - - wxStaticText* padding1; - padding1 = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - padding1->Wrap( -1 ); - paddingSizer->Add( padding1, 1, wxALL, 5 ); - - - bottomSizer->Add( paddingSizer, 1, 0, 5 ); - - m_applyButton = new wxButton( this, wxID_ANY, _("Apply"), wxDefaultPosition, wxDefaultSize, 0 ); - bottomSizer->Add( m_applyButton, 0, wxALL, 5 ); - - m_closeButton = new wxButton( this, wxID_CANCEL, _("Close"), wxDefaultPosition, wxDefaultSize, 0 ); - bottomSizer->Add( m_closeButton, 0, wxALL, 5 ); - - - m_mainSizer->Add( bottomSizer, 0, wxALL|wxEXPAND, 5 ); + m_mainSizer->Add( m_sdbSizer1, 0, wxEXPAND, 5 ); this->SetSizer( m_mainSizer ); @@ -152,9 +151,7 @@ DIALOG_EXCHANGE_FOOTPRINTS_BASE::DIALOG_EXCHANGE_FOOTPRINTS_BASE( wxWindow* pare m_matchSpecifiedID->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_EXCHANGE_FOOTPRINTS_BASE::OnMatchIDClicked ), NULL, this ); m_specifiedIDBrowseButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXCHANGE_FOOTPRINTS_BASE::ViewAndSelectFootprint ), NULL, this ); m_newIDBrowseButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXCHANGE_FOOTPRINTS_BASE::ViewAndSelectFootprint ), NULL, this ); - m_exportButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXCHANGE_FOOTPRINTS_BASE::RebuildCmpList ), NULL, this ); - m_applyButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXCHANGE_FOOTPRINTS_BASE::OnApplyClick ), NULL, this ); - m_closeButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXCHANGE_FOOTPRINTS_BASE::OnQuit ), NULL, this ); + m_sdbSizer1Apply->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXCHANGE_FOOTPRINTS_BASE::OnApplyClicked ), NULL, this ); } DIALOG_EXCHANGE_FOOTPRINTS_BASE::~DIALOG_EXCHANGE_FOOTPRINTS_BASE() @@ -173,8 +170,6 @@ DIALOG_EXCHANGE_FOOTPRINTS_BASE::~DIALOG_EXCHANGE_FOOTPRINTS_BASE() m_matchSpecifiedID->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_EXCHANGE_FOOTPRINTS_BASE::OnMatchIDClicked ), NULL, this ); m_specifiedIDBrowseButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXCHANGE_FOOTPRINTS_BASE::ViewAndSelectFootprint ), NULL, this ); m_newIDBrowseButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXCHANGE_FOOTPRINTS_BASE::ViewAndSelectFootprint ), NULL, this ); - m_exportButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXCHANGE_FOOTPRINTS_BASE::RebuildCmpList ), NULL, this ); - m_applyButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXCHANGE_FOOTPRINTS_BASE::OnApplyClick ), NULL, this ); - m_closeButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXCHANGE_FOOTPRINTS_BASE::OnQuit ), NULL, this ); + m_sdbSizer1Apply->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXCHANGE_FOOTPRINTS_BASE::OnApplyClicked ), NULL, this ); } diff --git a/pcbnew/dialogs/dialog_exchange_footprints_base.fbp b/pcbnew/dialogs/dialog_exchange_footprints_base.fbp index 5f749916d1..d063ef0a62 100644 --- a/pcbnew/dialogs/dialog_exchange_footprints_base.fbp +++ b/pcbnew/dialogs/dialog_exchange_footprints_base.fbp @@ -1051,16 +1051,16 @@ 5 - wxEXPAND|wxTOP|wxRIGHT|wxLEFT + wxEXPAND|wxALL 0 - m_middleSizer + m_changeSizer wxVERTICAL protected 2 - wxBOTTOM|wxEXPAND + wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT 0 1 @@ -1426,6 +1426,285 @@ + + 5 + wxEXPAND|wxALL + 0 + + wxID_ANY + Update Options + + m_updateOptionsSizer + wxVERTICAL + 1 + protected + + + 5 + wxBOTTOM|wxRIGHT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Remove text items which are not in library footprint + + 0 + + + 0 + + 1 + m_removeExtraBox + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + Removes fields that do not occur in the original library symbols + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxBOTTOM|wxRIGHT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Reset text layers and visibilities + + 0 + + + 0 + + 1 + m_resetTextItemLayers + 1 + + + protected + 1 + + Resizable + 1 + + + ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxBOTTOM|wxRIGHT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Reset text sizes, styles and positions + + 0 + + + 0 + + 1 + m_resetTextItemEffects + 1 + + + protected + 1 + + Resizable + 1 + + + ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 wxALL|wxEXPAND @@ -1463,7 +1742,7 @@ 0 - -1,300 + -1,240 1 m_MessageWindow 1 @@ -1508,7 +1787,7 @@ 5 - wxEXPAND | wxALL + wxEXPAND|wxALL 0 1 @@ -1589,371 +1868,28 @@ 5 - wxALL|wxEXPAND + wxEXPAND 0 - + + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 - bottomSizer - wxHORIZONTAL - none - - 5 - wxALL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Export Footprint Associations - - 0 - - - 0 - - 1 - m_exportButton - 1 - - - protected - 1 - - Resizable - 1 - - - ; - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - RebuildCmpList - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - - 1 - - - paddingSizer - wxHORIZONTAL - none - - 5 - wxALL - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - - 0 - - - 0 - - 1 - padding1 - 1 - - - none - 1 - - Resizable - 1 - - - ; - 0 - - - - - -1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxALL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Apply - - 0 - - - 0 - - 1 - m_applyButton - 1 - - - protected - 1 - - Resizable - 1 - - - ; - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - OnApplyClick - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxALL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_CANCEL - Close - - 0 - - - 0 - - 1 - m_closeButton - 1 - - - protected - 1 - - Resizable - 1 - - - ; - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - OnQuit - - - - - - - - - - - - - - - - - - - - - - - - - + m_sdbSizer1 + protected + OnApplyClicked + + + + + + + diff --git a/pcbnew/dialogs/dialog_exchange_footprints_base.h b/pcbnew/dialogs/dialog_exchange_footprints_base.h index 1d7f9a6606..a058fbaccb 100644 --- a/pcbnew/dialogs/dialog_exchange_footprints_base.h +++ b/pcbnew/dialogs/dialog_exchange_footprints_base.h @@ -1,8 +1,8 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Aug 4 2017) +// C++ code generated with wxFormBuilder (version Dec 30 2017) // http://www.wxformbuilder.org/ // -// PLEASE DO "NOT" EDIT THIS FILE! +// PLEASE DO *NOT* EDIT THIS FILE! /////////////////////////////////////////////////////////////////////////// #ifndef __DIALOG_EXCHANGE_FOOTPRINTS_BASE_H__ @@ -11,7 +11,6 @@ #include #include #include -class DIALOG_SHIM; class WX_HTML_REPORT_PANEL; #include "dialog_shim.h" @@ -31,6 +30,8 @@ class WX_HTML_REPORT_PANEL; #include #include #include +#include +#include #include #include @@ -57,13 +58,17 @@ class DIALOG_EXCHANGE_FOOTPRINTS_BASE : public DIALOG_SHIM wxRadioButton* m_matchSpecifiedID; wxTextCtrl* m_specifiedID; wxBitmapButton* m_specifiedIDBrowseButton; - wxBoxSizer* m_middleSizer; + wxBoxSizer* m_changeSizer; wxTextCtrl* m_newID; wxBitmapButton* m_newIDBrowseButton; + wxStaticBoxSizer* m_updateOptionsSizer; + wxCheckBox* m_removeExtraBox; + wxCheckBox* m_resetTextItemLayers; + wxCheckBox* m_resetTextItemEffects; WX_HTML_REPORT_PANEL* m_MessageWindow; - wxButton* m_exportButton; - wxButton* m_applyButton; - wxButton* m_closeButton; + wxStdDialogButtonSizer* m_sdbSizer1; + wxButton* m_sdbSizer1Apply; + wxButton* m_sdbSizer1Cancel; // Virtual event handlers, overide them in your derived class virtual void updateMatchModeRadioButtons( wxUpdateUIEvent& event ) { event.Skip(); } @@ -72,9 +77,7 @@ class DIALOG_EXCHANGE_FOOTPRINTS_BASE : public DIALOG_SHIM virtual void OnMatchValueClicked( wxCommandEvent& event ) { event.Skip(); } virtual void OnMatchIDClicked( wxCommandEvent& event ) { event.Skip(); } virtual void ViewAndSelectFootprint( wxCommandEvent& event ) { event.Skip(); } - virtual void RebuildCmpList( wxCommandEvent& event ) { event.Skip(); } - virtual void OnApplyClick( wxCommandEvent& event ) { event.Skip(); } - virtual void OnQuit( wxCommandEvent& event ) { event.Skip(); } + virtual void OnApplyClicked( wxCommandEvent& event ) { event.Skip(); } public: diff --git a/pcbnew/exporters/export_footprint_associations.cpp b/pcbnew/exporters/export_footprint_associations.cpp new file mode 100644 index 0000000000..576e7cae61 --- /dev/null +++ b/pcbnew/exporters/export_footprint_associations.cpp @@ -0,0 +1,83 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2018 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 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +bool RecreateCmpFile( BOARD * aBrd, const wxString& aFullCmpFileName ) +{ + FILE* cmpFile = wxFopen( aFullCmpFileName, wxT( "wt" ) ); + + if( cmpFile == NULL ) + return false; + + fprintf( cmpFile, "Cmp-Mod V01 Created by PcbNew date = %s\n", TO_UTF8( DateAndTime() ) ); + + for( MODULE* module = aBrd->m_Modules; module != NULL; module = module->Next() ) + { + fprintf( cmpFile, "\nBeginCmp\n" ); + fprintf( cmpFile, "TimeStamp = %8.8lX\n", (unsigned long)module->GetTimeStamp() ); + fprintf( cmpFile, "Path = %s\n", TO_UTF8( module->GetPath() ) ); + fprintf( cmpFile, "Reference = %s;\n", + !module->GetReference().IsEmpty() ? TO_UTF8( module->GetReference() ) : "[NoRef]" ); + fprintf( cmpFile, "ValeurCmp = %s;\n", + !module->GetValue().IsEmpty() ? TO_UTF8( module->GetValue() ) : "[NoVal]" ); + fprintf( cmpFile, "IdModule = %s;\n", module->GetFPID().Format().c_str() ); + fprintf( cmpFile, "EndCmp\n" ); + } + + fprintf( cmpFile, "\nEndListe\n" ); + fclose( cmpFile ); + + return true; +} + + +void PCB_EDIT_FRAME::RecreateCmpFileFromBoard( wxCommandEvent& aEvent ) +{ + // Build the .cmp file name from the board name + wxString projectDir = wxPathOnly( Prj().GetProjectFullName() ); + wxFileName fn = GetBoard()->GetFileName(); + + fn.SetExt( ComponentFileExtension ); + + wxFileDialog dlg( this, _( "Save Footprint Association File" ), + projectDir, fn.GetFullName(), ComponentFileWildcard(), + wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); + + if( dlg.ShowModal() == wxID_CANCEL ) + return; + + wxString path = dlg.GetPath(); + + if( !RecreateCmpFile( GetBoard(), path ) ) + DisplayError( this, wxString::Format( _( "Could not create file \"%s\"." ), path ) ); +} + diff --git a/pcbnew/pcb_edit_frame.h b/pcbnew/pcb_edit_frame.h index 0e1fa87860..d52834790a 100644 --- a/pcbnew/pcb_edit_frame.h +++ b/pcbnew/pcb_edit_frame.h @@ -1152,11 +1152,13 @@ public: * Replaces OldModule by NewModule, using OldModule settings: * position, orientation, pad netnames ...) * OldModule is deleted or put in undo list. - * @param aOldModule = footprint to replace - * @param aNewModule = footprint to put + * @param aSrc = footprint to replace + * @param aDest = footprint to put * @param aCommit = commit that should store the changes */ - void Exchange_Module( MODULE* aOldModule, MODULE* aNewModule, BOARD_COMMIT& aCommit ); + void Exchange_Module( MODULE* aSrc, MODULE* aDest, BOARD_COMMIT& aCommit, + bool deleteExtraTexts = true, + bool resetTextLayers = true, bool resetTextEffects = true ); // loading modules: see PCB_BASE_FRAME