diff --git a/common/project.cpp b/common/project.cpp index 27f91a8bad..ff3d853ebc 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -93,12 +93,19 @@ const wxString PROJECT::GetProjectFullName() const return m_project_name.GetFullPath(); } + const wxString PROJECT::GetProjectPath() const { return m_project_name.GetPathWithSep(); } +const wxString PROJECT::GetProjectName() const +{ + return m_project_name.GetName(); +} + + const wxString PROJECT::FootprintLibTblName() const { wxFileName fn = GetProjectFullName(); diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt index 700007faff..995bb7d6fc 100644 --- a/eeschema/CMakeLists.txt +++ b/eeschema/CMakeLists.txt @@ -63,6 +63,10 @@ set( EESCHEMA_DLGS dialogs/dialog_plot_schematic.cpp dialogs/dialog_print_using_printer_base.cpp dialogs/dialog_print_using_printer.cpp + dialogs/dialog_rescue_each.cpp + dialogs/dialog_rescue_each_base.cpp + dialogs/dialog_rescue_summary.cpp + dialogs/dialog_rescue_summary_base.cpp dialogs/dialog_sch_edit_sheet_pin.cpp dialogs/dialog_sch_edit_sheet_pin_base.cpp dialogs/dialog_sch_sheet_props.cpp @@ -111,6 +115,7 @@ set( EESCHEMA_SRCS libedit_undo_redo.cpp lib_arc.cpp lib_bezier.cpp + lib_cache_rescue.cpp lib_circle.cpp lib_collectors.cpp lib_draw_item.cpp diff --git a/eeschema/class_libentry.cpp b/eeschema/class_libentry.cpp index 698e54e5aa..654dc74baa 100644 --- a/eeschema/class_libentry.cpp +++ b/eeschema/class_libentry.cpp @@ -628,6 +628,65 @@ LIB_PIN* LIB_PART::GetPin( const wxString& aNumber, int aUnit, int aConvert ) } +bool LIB_PART::PinsConflictWith( LIB_PART& aOtherPart, bool aTestNums, bool aTestNames, + bool aTestType, bool aTestOrientation, bool aTestLength ) +{ + LIB_PINS thisPinList; + GetPins( thisPinList, /* aUnit */ 0, /* aConvert */ 0 ); + + BOOST_FOREACH( LIB_PIN* eachThisPin, thisPinList ) + { + wxASSERT( eachThisPin ); + LIB_PINS otherPinList; + aOtherPart.GetPins( otherPinList, /* aUnit */ 0, /* aConvert */ 0 ); + bool foundMatch = false; + + BOOST_FOREACH( LIB_PIN* eachOtherPin, otherPinList ) + { + wxASSERT( eachOtherPin ); + // Same position? + if( eachThisPin->GetPosition() != eachOtherPin->GetPosition() ) + continue; + + // Same number? + wxString eachThisPinNumber, eachOtherPinNumber; + eachThisPin->PinStringNum( eachThisPinNumber ); + eachOtherPin->PinStringNum( eachOtherPinNumber ); + if( aTestNums && ( eachThisPinNumber != eachOtherPinNumber )) + continue; + + // Same name? + if( aTestNames && ( eachThisPin->GetName() != eachOtherPin->GetName() )) + continue; + + // Same electrical type? + if( aTestType && ( eachThisPin->GetType() != eachOtherPin->GetType() )) + continue; + + // Same orientation? + if( aTestOrientation && ( eachThisPin->GetOrientation() != eachOtherPin->GetOrientation() )) + continue; + + // Same length? + if( aTestLength && ( eachThisPin->GetLength() != eachOtherPin->GetLength() )) + continue; + + foundMatch = true; + } + + if( !foundMatch ) + { + // This means there was not an identical (according to the arguments) + // pin at the same position in the other component. + return true; + } + } + + // The loop never gave up, so no conflicts were found. + return false; +} + + bool LIB_PART::Save( OUTPUTFORMATTER& aFormatter ) { LIB_FIELD& value = GetValueField(); diff --git a/eeschema/class_libentry.h b/eeschema/class_libentry.h index f781122222..3d6381c8d7 100644 --- a/eeschema/class_libentry.h +++ b/eeschema/class_libentry.h @@ -522,6 +522,22 @@ public: */ LIB_PIN* GetPin( const wxString& aNumber, int aUnit = 0, int aConvert = 0 ); + /** + * Function PinsConflictWith + * returns true if this part's pins do not match another part's pins. This + * is used to detect whether the project cache is out of sync with the + * system libs. + * + * @param aOtherPart - The other library part to test + * @param aTestNums - Whether two pins at the same point must have the same number. + * @param aTestNames - Whether two pins at the same point must have the same name. + * @param aTestType - Whether two pins at the same point must have the same electrical type. + * @param aTestOrientation - Whether two pins at the same point must have the same orientation. + * @param aTestLength - Whether two pins at the same point must have the same length. + */ + bool PinsConflictWith( LIB_PART& aOtherPart, bool aTestNums, bool aTestNames, + bool aTestType, bool aTestOrientation, bool aTestLength ); + /** * Move the part \a aOffset. * diff --git a/eeschema/class_library.cpp b/eeschema/class_library.cpp index 3116d1fb4c..4fac061ba5 100644 --- a/eeschema/class_library.cpp +++ b/eeschema/class_library.cpp @@ -38,6 +38,7 @@ #include #include #include +#include //#include #include @@ -924,7 +925,7 @@ wxArrayString PART_LIBS::GetLibraryNames( bool aSorted ) } -LIB_PART* PART_LIBS::FindLibPart( const wxString& aName, const wxString& aLibraryName ) +LIB_PART* PART_LIBS::FindLibPart( const wxString& aPartName, const wxString& aLibraryName ) { LIB_PART* part = NULL; @@ -933,7 +934,7 @@ LIB_PART* PART_LIBS::FindLibPart( const wxString& aName, const wxString& aLibrar if( !aLibraryName.IsEmpty() && lib.GetName() != aLibraryName ) continue; - part = lib.FindPart( aName ); + part = lib.FindPart( aPartName ); if( part ) break; @@ -943,7 +944,7 @@ LIB_PART* PART_LIBS::FindLibPart( const wxString& aName, const wxString& aLibrar } -LIB_ALIAS* PART_LIBS::FindLibraryEntry( const wxString& aName, const wxString& aLibraryName ) +LIB_ALIAS* PART_LIBS::FindLibraryEntry( const wxString& aEntryName, const wxString& aLibraryName ) { LIB_ALIAS* entry = NULL; @@ -952,7 +953,7 @@ LIB_ALIAS* PART_LIBS::FindLibraryEntry( const wxString& aName, const wxString& a if( !!aLibraryName && lib.GetName() != aLibraryName ) continue; - entry = lib.FindEntry( aName ); + entry = lib.FindEntry( aEntryName ); if( entry ) break; @@ -961,6 +962,17 @@ LIB_ALIAS* PART_LIBS::FindLibraryEntry( const wxString& aName, const wxString& a return entry; } +void PART_LIBS::FindLibraryEntries( const wxString& aEntryName, std::vector& aEntries ) +{ + BOOST_FOREACH( PART_LIB& lib, *this ) + { + LIB_ALIAS* entry = lib.FindEntry( aEntryName ); + + if( entry ) + aEntries.push_back( entry ); + } +} + /* searches all libraries in the list for an entry, using a case insensitive comparison. * Used to find an entry, when the normal (case sensitive) search fails. */ @@ -1162,12 +1174,15 @@ void PART_LIBS::LoadAllLibraries( PROJECT* aProject ) throw( IO_ERROR, boost::ba // add the special cache library. wxString cache_name = CacheName( aProject->GetProjectFullName() ); + PART_LIB* cache_lib; + if( !!cache_name ) { try { - if( PART_LIB* lib = AddLibrary( cache_name ) ) - lib->SetCache(); + cache_lib = AddLibrary( cache_name ); + if( cache_lib ) + cache_lib->SetCache(); } catch( const IO_ERROR& ioe ) { diff --git a/eeschema/class_library.h b/eeschema/class_library.h index 8823a538c3..37bf0ddd41 100644 --- a/eeschema/class_library.h +++ b/eeschema/class_library.h @@ -301,6 +301,15 @@ public: LIB_ALIAS* FindLibraryEntry( const wxString& aEntryName, const wxString& aLibraryName = wxEmptyString ); + /** + * Function FindLibraryEntries + * searches all libraries in the list for an entry, returns all matches. + * + * @param aEntryName - Name of entry to search for (case sensitive). + * @param aEntries - a std::vector to store entries + */ + void FindLibraryEntries( const wxString& aEntryName, std::vector& aEntries ); + /** * Function FindLibraryNearEntries * Searches all libraries in the list for an entry, using a case insensitive comparison. diff --git a/eeschema/dialogs/dialog_annotate_base.fbp b/eeschema/dialogs/dialog_annotate_base.fbp index b836390bd8..cfceed14de 100644 --- a/eeschema/dialogs/dialog_annotate_base.fbp +++ b/eeschema/dialogs/dialog_annotate_base.fbp @@ -44,7 +44,7 @@ DIALOG_ANNOTATE_BASE - 432,550 + -1,-1 wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER DIALOG_SHIM; dialog_shim.h Annotate Schematic diff --git a/eeschema/dialogs/dialog_eeschema_config.cpp b/eeschema/dialogs/dialog_eeschema_config.cpp index 3293118ca7..2bf2d719a2 100644 --- a/eeschema/dialogs/dialog_eeschema_config.cpp +++ b/eeschema/dialogs/dialog_eeschema_config.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -54,6 +55,7 @@ public: wxString* aCallersProjectSpecificLibPaths, wxArrayString* aCallersLibNames ); private: + wxConfigBase* m_config; wxString* m_callers_project_specific_lib_paths; wxArrayString* m_callers_lib_names; @@ -124,6 +126,12 @@ DIALOG_EESCHEMA_CONFIG::DIALOG_EESCHEMA_CONFIG( wxWindow* aParent, if( libpaths->GetCount() > 1 ) m_DefaultLibraryPathslistBox->Select( 1 ); + // Load setting for cache rescue + m_config = Kiface().KifaceSettings(); + bool rescueNeverShow = false; + m_config->Read( wxT("RescueNeverShow"), &rescueNeverShow, false ); + m_cbRescue->SetValue( !rescueNeverShow ); + wxString msg = wxString::Format( _( "Project '%s'" ), GetChars( Prj().GetProjectFullName() ) @@ -241,6 +249,8 @@ void DIALOG_EESCHEMA_CONFIG::OnOkClick( wxCommandEvent& event ) *m_callers_lib_names = list; } + m_config->Write( wxT("RescueNeverShow"), ! m_cbRescue->GetValue() ); + EndModal( wxID_OK ); } diff --git a/eeschema/dialogs/dialog_eeschema_config_fbp.cpp b/eeschema/dialogs/dialog_eeschema_config_fbp.cpp index 99297fb844..636b554f20 100644 --- a/eeschema/dialogs/dialog_eeschema_config_fbp.cpp +++ b/eeschema/dialogs/dialog_eeschema_config_fbp.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Nov 5 2013) +// C++ code generated with wxFormBuilder (version Mar 13 2015) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! @@ -120,6 +120,9 @@ DIALOG_EESCHEMA_CONFIG_FBP::DIALOG_EESCHEMA_CONFIG_FBP( wxWindow* parent, wxWind m_staticline3 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); bMainSizer->Add( m_staticline3, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); + m_cbRescue = new wxCheckBox( this, wxID_ANY, _("Check for cache/library conflicts at schematic load"), wxDefaultPosition, wxDefaultSize, 0 ); + bMainSizer->Add( m_cbRescue, 0, wxALL, 5 ); + m_sdbSizer1 = new wxStdDialogButtonSizer(); m_sdbSizer1OK = new wxButton( this, wxID_OK ); m_sdbSizer1->AddButton( m_sdbSizer1OK ); diff --git a/eeschema/dialogs/dialog_eeschema_config_fbp.fbp b/eeschema/dialogs/dialog_eeschema_config_fbp.fbp index 5fe277f65c..760a489b14 100644 --- a/eeschema/dialogs/dialog_eeschema_config_fbp.fbp +++ b/eeschema/dialogs/dialog_eeschema_config_fbp.fbp @@ -2,7 +2,7 @@ - + C++ 1 source_name @@ -16,9 +16,9 @@ none 1 dialog_eeschema_config - + . - + 1 1 1 @@ -29,67 +29,67 @@ 0 wxAUI_MGR_DEFAULT - + wxBOTH - + 1 1 impl_virtual - - - + + + 0 wxID_ANY - - + + DIALOG_EESCHEMA_CONFIG_FBP - + -1,-1 wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER DIALOG_SHIM; dialog_shim.h - - - - - - - - - - - - - - + + + + + + + + + + + + + + OnCloseWindow - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - + bMainSizer wxVERTICAL none @@ -98,7 +98,7 @@ wxEXPAND 2 - + bSizerUpper wxVERTICAL none @@ -111,78 +111,78 @@ 1 1 1 - - - - - - - + + + + + + + 1 0 1 - + 1 0 Dock 0 Left 1 - + 1 - + 0 0 wxID_ANY Component library files - + 0 - - + + 0 - + 1 m_staticTextLibsList 1 - - + + protected 1 - + Resizable 1 - - - + + + 0 - - - - + + + + -1 - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -190,7 +190,7 @@ wxEXPAND 1 - + bSizerLibsChoice wxHORIZONTAL none @@ -203,83 +203,83 @@ 1 1 1 - - - - - - - + + + + + + + 1 0 - + 1 - + 1 0 Dock 0 Left 1 - + 1 - + 0 0 wxID_ANY - + 0 - - + + 0 400,250 1 m_ListLibr 1 - - + + protected 1 - + Resizable 1 - + wxLB_EXTENDED|wxLB_HSCROLL|wxLB_NEEDED_SB|wxLB_SINGLE - + 0 List of active library files. Only library files in this list are loaded by Eeschema. The order of this list is important: Eeschema searchs for a given component using this list order priority. - + wxFILTER_NONE wxDefaultValidator - - - - - - - - - - - - - - + + + + + + + + + + + + + + OnFilesListClick OnFilesListClick - - - - - - - - - - - - - + + + + + + + + + + + + + @@ -287,7 +287,7 @@ wxALIGN_CENTER_VERTICAL|wxALL 0 - + bRightSizer wxVERTICAL none @@ -300,17 +300,17 @@ 1 1 1 - - - - - - - + + + + + + + 1 0 1 - + 1 0 0 @@ -318,65 +318,65 @@ 0 Left 1 - + 1 - + 0 0 ID_ADD_LIB Add - + 0 - - + + 0 - + 1 m_buttonAddLib 1 - - + + protected 1 - + Resizable 1 - - - + + + 0 Add a new library after the selected library, and load it - + wxFILTER_NONE wxDefaultValidator - - - - + + + + OnAddOrInsertLibClick - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -388,17 +388,17 @@ 1 1 1 - - - - - - - + + + + + + + 1 0 1 - + 1 0 0 @@ -406,65 +406,65 @@ 0 Left 1 - + 1 - + 0 0 wxID_ANY Insert - + 0 - - + + 0 - + 1 m_buttonIns 1 - - + + protected 1 - + Resizable 1 - - - + + + 0 Add a new library before the selected library, and load it - + wxFILTER_NONE wxDefaultValidator - - - - + + + + OnAddOrInsertLibClick - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -476,17 +476,17 @@ 1 1 1 - - - - - - - + + + + + + + 1 0 1 - + 1 0 0 @@ -494,65 +494,65 @@ 0 Left 1 - + 1 - + 0 0 ID_REMOVE_LIB Remove - + 0 - - + + 0 - + 1 m_buttonRemoveLib 1 - - + + protected 1 - + Resizable 1 - - - + + + 0 Unload the selected library - + wxFILTER_NONE wxDefaultValidator - - - - + + + + OnRemoveLibClick - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -564,17 +564,17 @@ 1 1 1 - - - - - - - + + + + + + + 1 0 1 - + 1 0 0 @@ -582,65 +582,65 @@ 0 Left 1 - + 1 - + 0 0 wxID_ANY Up - + 0 - - + + 0 - + 1 m_buttonUp 1 - - + + protected 1 - + Resizable 1 - - - + + + 0 - - + + wxFILTER_NONE wxDefaultValidator - - - - + + + + OnButtonUpClick - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -652,17 +652,17 @@ 1 1 1 - - - - - - - + + + + + + + 1 0 1 - + 1 0 0 @@ -670,65 +670,65 @@ 0 Left 1 - + 1 - + 0 0 wxID_ANY Down - + 0 - - + + 0 - + 1 m_buttonDown 1 - - + + protected 1 - + Resizable 1 - - - + + + 0 - - + + wxFILTER_NONE wxDefaultValidator - - - - + + + + OnButtonDownClick - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -742,7 +742,7 @@ wxEXPAND 1 - + bSizerMiddle wxVERTICAL none @@ -755,78 +755,78 @@ 1 1 1 - - - - - - - + + + + + + + 1 0 1 - + 1 0 Dock 0 Left 1 - + 1 - + 0 0 wxID_ANY User defined search path - + 0 - - + + 0 - + 1 m_staticTextPaths 1 - - + + protected 1 - + Resizable 1 - - - + + + 0 - - - - + + + + -1 - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -834,7 +834,7 @@ wxEXPAND 1 - + bSizerPathsChoice wxHORIZONTAL none @@ -847,83 +847,83 @@ 1 1 1 - - - - - - - + + + + + + + 1 0 - + 1 - + 1 0 Dock 0 Left 1 - + 1 - + 0 0 wxID_ANY - + 0 - - + + 0 400,90 1 m_listUserPaths 1 - - + + protected 1 - + Resizable 1 - + wxLB_HSCROLL|wxLB_NEEDED_SB|wxLB_SINGLE - + 0 Additional paths used in this project. The priority is higher than default KiCad paths. - + wxFILTER_NONE wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -931,7 +931,7 @@ wxALIGN_CENTER_VERTICAL|wxALL 0 - + bUserPathsButtonsSizer wxVERTICAL none @@ -944,17 +944,17 @@ 1 1 1 - - - - - - - + + + + + + + 1 0 1 - + 1 0 0 @@ -962,65 +962,65 @@ 0 Left 1 - + 1 - + 0 0 ID_LIB_PATH_SEL Add - + 0 - - + + 0 - + 1 m_buttonAddPath 1 - - + + protected 1 - + Resizable 1 - - - + + + 0 - - + + wxFILTER_NONE wxDefaultValidator - - - - + + + + OnAddOrInsertPath - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -1032,17 +1032,17 @@ 1 1 1 - - - - - - - + + + + + + + 1 0 1 - + 1 0 0 @@ -1050,65 +1050,65 @@ 0 Left 1 - + 1 - + 0 0 wxID_INSERT_PATH Insert - + 0 - - + + 0 - + 1 m_buttonInsPath 1 - - + + protected 1 - + Resizable 1 - - - + + + 0 - - + + wxFILTER_NONE wxDefaultValidator - - - - + + + + OnAddOrInsertPath - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -1120,17 +1120,17 @@ 1 1 1 - - - - - - - + + + + + + + 1 0 1 - + 1 0 0 @@ -1138,65 +1138,65 @@ 0 Left 1 - + 1 - + 0 0 wxID_REMOVE_PATH Remove - + 0 - - + + 0 - + 1 m_buttonRemovePath 1 - - + + protected 1 - + Resizable 1 - - - + + + 0 - - + + wxFILTER_NONE wxDefaultValidator - - - - + + + + OnRemoveUserPath - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -1210,7 +1210,7 @@ wxEXPAND 1 - + bSizerLower wxVERTICAL none @@ -1223,78 +1223,78 @@ 1 1 1 - - - - - - - + + + + + + + 1 0 1 - + 1 0 Dock 0 Left 1 - + 1 - + 0 0 wxID_ANY Current search path list - + 0 - - + + 0 - + 1 m_staticTextPathlist 1 - - + + protected 1 - + Resizable 1 - - - + + + 0 - - - - + + + + -1 - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -1306,83 +1306,83 @@ 1 1 1 - - - - - - - + + + + + + + 1 0 - + 1 - + 1 0 Dock 0 Left 1 - + 1 - + 0 0 wxID_ANY - + 0 - - + + 0 -1,-1 1 m_DefaultLibraryPathslistBox 1 - - + + protected 1 - + Resizable 1 - + wxLB_NEEDED_SB - + 0 System and user paths used to search and load library files and component doc files. Sorted by decreasing priority order. - + wxFILTER_NONE wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1396,76 +1396,164 @@ 1 1 1 - - - - - - - + + + + + + + 1 0 1 - + 1 0 Dock 0 Left 1 - + 1 - + 0 0 wxID_ANY - + 0 - - + + 0 - + 1 m_staticline3 1 - - + + protected 1 - + Resizable 1 - + wxLI_HORIZONTAL - + 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Check for cache/library conflicts at schematic load + + 0 + + + 0 + + 1 + m_cbRescue + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1481,17 +1569,17 @@ 1 0 0 - + m_sdbSizer1 public - + OnCancelClick - - - + + + OnOkClick - - + + diff --git a/eeschema/dialogs/dialog_eeschema_config_fbp.h b/eeschema/dialogs/dialog_eeschema_config_fbp.h index 84b86341c4..31f46390ee 100644 --- a/eeschema/dialogs/dialog_eeschema_config_fbp.h +++ b/eeschema/dialogs/dialog_eeschema_config_fbp.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Nov 5 2013) +// C++ code generated with wxFormBuilder (version Mar 13 2015) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! @@ -24,6 +24,7 @@ class DIALOG_SHIM; #include #include #include +#include #include /////////////////////////////////////////////////////////////////////////// @@ -60,6 +61,7 @@ class DIALOG_EESCHEMA_CONFIG_FBP : public DIALOG_SHIM wxStaticText* m_staticTextPathlist; wxListBox* m_DefaultLibraryPathslistBox; wxStaticLine* m_staticline3; + wxCheckBox* m_cbRescue; // Virtual event handlers, overide them in your derived class virtual void OnCloseWindow( wxCloseEvent& event ) { event.Skip(); } diff --git a/eeschema/dialogs/dialog_rescue_each.cpp b/eeschema/dialogs/dialog_rescue_each.cpp new file mode 100644 index 0000000000..649895fd4e --- /dev/null +++ b/eeschema/dialogs/dialog_rescue_each.cpp @@ -0,0 +1,305 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Chris Pavlina + * Copyright (C) 2015 Kicad Developers, see change_log.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 +#include +#include +#include + +class DIALOG_RESCUE_EACH: public DIALOG_RESCUE_EACH_BASE +{ +public: + /** + * Constructor + * This dialog asks the user which rescuable, cached parts he wants to rescue. + * Any rejects will be pruned from aCandidates. + * @param aCaller - the SCH_EDIT_FRAME calling this + * @param aCandidates - the list of RESCUE_CANDIDATES + * @param aComponents - a vector of all the components in the schematic + * @param aAskShowAgain - if true, a "Never Show Again" button will be included + */ + DIALOG_RESCUE_EACH( SCH_EDIT_FRAME* aParent, std::vector& aCandidates, + std::vector& aComponents, bool aAskShowAgain ); + + ~DIALOG_RESCUE_EACH(); + +private: + SCH_EDIT_FRAME* m_Parent; + wxConfigBase* m_Config; + std::vector* m_Candidates; + std::vector* m_Components; + bool m_AskShowAgain; + + bool m_insideUpdateEvent; + + bool TransferDataToWindow(); + bool TransferDataFromWindow(); + void PopulateConflictList(); + void PopulateInstanceList(); + void OnConflictSelect( wxDataViewEvent& event ); + void OnNeverShowClick( wxCommandEvent& event ); + void OnCancelClick( wxCommandEvent& event ); + void OnHandleCachePreviewRepaint( wxPaintEvent& aRepaintEvent ); + void OnHandleLibraryPreviewRepaint( wxPaintEvent& aRepaintEvent ); + void OnDialogResize( wxSizeEvent& aSizeEvent ); + void renderPreview( LIB_PART* aComponent, int aUnit, wxPanel* panel ); +}; + + +DIALOG_RESCUE_EACH::DIALOG_RESCUE_EACH( SCH_EDIT_FRAME* aParent, std::vector& aCandidates, + std::vector& aComponents, bool aAskShowAgain ) + + : DIALOG_RESCUE_EACH_BASE( aParent ), + m_Parent( aParent ), + m_Candidates( &aCandidates ), + m_Components( &aComponents ), + m_AskShowAgain( aAskShowAgain ), + m_insideUpdateEvent( false ) +{ +} + + +DIALOG_RESCUE_EACH::~DIALOG_RESCUE_EACH() +{ +} + + +bool DIALOG_RESCUE_EACH::TransferDataToWindow() +{ + if( !wxDialog::TransferDataToWindow() ) + return false; + + m_Config = Kiface().KifaceSettings(); + m_ListOfConflicts->AppendToggleColumn( wxT("Rescue") ); + m_ListOfConflicts->AppendTextColumn( wxT("Symbol Name") ); + m_ListOfInstances->AppendTextColumn( wxT("Reference") ); + m_ListOfInstances->AppendTextColumn( wxT("Value") ); + PopulateConflictList(); + PopulateInstanceList(); + + if( !m_AskShowAgain ) + m_btnNeverShowAgain->Hide(); + + GetSizer()->Layout(); + GetSizer()->Fit( this ); + GetSizer()->SetSizeHints( this ); + Centre(); + + return true; +} + + +void DIALOG_RESCUE_EACH::PopulateConflictList() +{ + wxVector data; + BOOST_FOREACH( RESCUE_CANDIDATE& each_candidate, *m_Candidates ) + { + data.clear(); + data.push_back( wxVariant( true ) ); + data.push_back( each_candidate.requested_name ); + m_ListOfConflicts->AppendItem( data ); + } +} + + +void DIALOG_RESCUE_EACH::PopulateInstanceList() +{ + m_ListOfInstances->DeleteAllItems(); + + int row = m_ListOfConflicts->GetSelectedRow(); + if( row == wxNOT_FOUND ) + row = 0; + + RESCUE_CANDIDATE& selected_part = (*m_Candidates)[row]; + + wxVector data; + BOOST_FOREACH( SCH_COMPONENT* each_component, *m_Components ) + { + if( each_component->GetPartName() != selected_part.requested_name ) + continue; + + SCH_FIELD* valueField = each_component->GetField( 1 ); + + data.clear(); + data.push_back( each_component->GetRef( & m_Parent->GetCurrentSheet() ) ); + data.push_back( valueField ? valueField->GetText() : wxT("") ); + m_ListOfInstances->AppendItem( data ); + + } +} + + +void DIALOG_RESCUE_EACH::OnHandleCachePreviewRepaint( wxPaintEvent& aRepaintEvent ) +{ + int row = m_ListOfConflicts->GetSelectedRow(); + if( row == wxNOT_FOUND ) + row = 0; + + RESCUE_CANDIDATE& selected_part = (*m_Candidates)[row]; + + renderPreview( selected_part.cache_candidate, 0, m_componentViewOld ); +} + + +void DIALOG_RESCUE_EACH::OnHandleLibraryPreviewRepaint( wxPaintEvent& aRepaintEvent ) +{ + int row = m_ListOfConflicts->GetSelectedRow(); + if( row == wxNOT_FOUND ) + row = 0; + + RESCUE_CANDIDATE& selected_part = (*m_Candidates)[row]; + + renderPreview( selected_part.lib_candidate, 0, m_componentViewNew ); +} + + +void DIALOG_RESCUE_EACH::OnDialogResize( wxSizeEvent& aSizeEvent ) +{ + // Placeholer - I was previously doing some extra reflow here. + DIALOG_RESCUE_EACH_BASE::OnDialogResize( aSizeEvent ); +} + + +// Render the preview in our m_componentView. If this gets more complicated, we should +// probably have a derived class from wxPanel; but this keeps things local. +void DIALOG_RESCUE_EACH::renderPreview( LIB_PART* aComponent, int aUnit, wxPanel* aPanel ) +{ + wxPaintDC dc( aPanel ); + EDA_COLOR_T bgcolor = m_Parent->GetDrawBgColor(); + + dc.SetBackground( bgcolor == BLACK ? *wxBLACK_BRUSH : *wxWHITE_BRUSH ); + dc.Clear(); + + if( aComponent == NULL ) + return; + + if( aUnit <= 0 ) + aUnit = 1; + + const wxSize dc_size = dc.GetSize(); + dc.SetDeviceOrigin( dc_size.x / 2, dc_size.y / 2 ); + + // Find joint bounding box for everything we are about to draw. + EDA_RECT bBox = aComponent->GetBoundingBox( aUnit, /* deMorganConvert */ 0 ); + const double xscale = (double) dc_size.x / bBox.GetWidth(); + const double yscale = (double) dc_size.y / bBox.GetHeight(); + const double scale = std::min( xscale, yscale ) * 0.85; + + dc.SetUserScale( scale, scale ); + + wxPoint offset = bBox.Centre(); + NEGATE( offset.x ); + NEGATE( offset.y ); + + // Avoid rendering when either dimension is zero + int width, height; + + dc.GetSize( &width, &height ); + if( !width || !height ) + return; + + aComponent->Draw( NULL, &dc, offset, aUnit, /* deMorganConvert */ 0, GR_COPY, + UNSPECIFIED_COLOR, DefaultTransform, true, true, false ); +} + + +void DIALOG_RESCUE_EACH::OnConflictSelect( wxDataViewEvent& aEvent ) +{ + // wxformbuilder connects this event to the _dialog_, not the data view. + // Make sure the correct item triggered it, otherwise we trigger recursively + // and get a stack overflow. + if( aEvent.GetEventObject() != m_ListOfConflicts ) return; + + PopulateInstanceList(); + + int row = m_ListOfConflicts->GetSelectedRow(); + if( row == wxNOT_FOUND ) + row = 0; + + RESCUE_CANDIDATE& selected_part = (*m_Candidates)[row]; + + renderPreview( selected_part.cache_candidate, 0, m_componentViewOld ); + renderPreview( selected_part.lib_candidate, 0, m_componentViewNew ); +} + + +bool DIALOG_RESCUE_EACH::TransferDataFromWindow() +{ + if( !wxDialog::TransferDataFromWindow() ) + return false; + + std::vector::iterator it = m_Candidates->begin(); + for( size_t index = 0; it != m_Candidates->end(); ++index ) + { + wxVariant val; + m_ListOfConflicts->GetValue( val, index, 0 ); + bool rescue_part = val.GetBool(); + + if( !rescue_part ) + m_Candidates->erase( it ); + else + ++it; + } + + return true; +} + + +void DIALOG_RESCUE_EACH::OnNeverShowClick( wxCommandEvent& aEvent ) +{ + wxMessageDialog dlg( m_Parent, wxT( "Stop showing this tool? No changes will be made.\n\n" + "This setting can be changed from the Component Libraries settings, and the " + "tool can be activated manually from the Tools menu." ), + wxT( "Rescue Components" ), wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION ); + int resp = dlg.ShowModal (); + + if( resp == wxID_YES ) + { + m_Config->Write( wxT("RescueNeverShow"), true ); + m_Candidates->clear(); + Close(); + } +} + + +void DIALOG_RESCUE_EACH::OnCancelClick( wxCommandEvent& aEvent ) +{ + m_Candidates->clear(); + DIALOG_RESCUE_EACH_BASE::OnCancelClick( aEvent ); +} + + +int InvokeDialogRescueEach( SCH_EDIT_FRAME* aCaller, std::vector& aCandidates, + std::vector& aComponents, bool aAskShowAgain ) +{ + DIALOG_RESCUE_EACH dlg( aCaller, aCandidates, aComponents, aAskShowAgain ); + return dlg.ShowModal(); +} diff --git a/eeschema/dialogs/dialog_rescue_each_base.cpp b/eeschema/dialogs/dialog_rescue_each_base.cpp new file mode 100644 index 0000000000..a716bdb217 --- /dev/null +++ b/eeschema/dialogs/dialog_rescue_each_base.cpp @@ -0,0 +1,127 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Mar 13 2015) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "dialog_rescue_each_base.h" + +/////////////////////////////////////////////////////////////////////////// + +DIALOG_RESCUE_EACH_BASE::DIALOG_RESCUE_EACH_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( wxSize( 450,100 ), wxDefaultSize ); + + wxBoxSizer* bSizerMain; + bSizerMain = new wxBoxSizer( wxVERTICAL ); + + m_lblInfo = new wxStaticText( this, wxID_ANY, _("This project uses symbols that no longer match the symbols in the system libraries. Using this tool, you can rescue these cached symbols into a new library.\n\nChoose \"Rescue\" for any parts you would like to save from this project's cache, or press Cancel to allow the symbols to be updated to the new versions."), wxDefaultPosition, wxDefaultSize, 0 ); + m_lblInfo->Wrap( 500 ); + bSizerMain->Add( m_lblInfo, 0, wxALL|wxEXPAND, 5 ); + + m_staticText5 = new wxStaticText( this, wxID_ANY, _("Symbols with cache/library conflicts:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText5->Wrap( -1 ); + m_staticText5->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); + + bSizerMain->Add( m_staticText5, 0, wxALL, 5 ); + + m_ListOfConflicts = new wxDataViewListCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + bSizerMain->Add( m_ListOfConflicts, 2, wxALL|wxEXPAND, 5 ); + + m_staticText4 = new wxStaticText( this, wxID_ANY, _("Instances of this symbol:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText4->Wrap( -1 ); + m_staticText4->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); + + bSizerMain->Add( m_staticText4, 0, wxALL, 5 ); + + m_ListOfInstances = new wxDataViewListCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + bSizerMain->Add( m_ListOfInstances, 1, wxALL|wxEXPAND, 5 ); + + wxBoxSizer* bSizerView; + bSizerView = new wxBoxSizer( wxHORIZONTAL ); + + wxBoxSizer* bSizer6; + bSizer6 = new wxBoxSizer( wxVERTICAL ); + + m_staticText2 = new wxStaticText( this, wxID_ANY, _("Cached Part:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText2->Wrap( -1 ); + m_staticText2->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); + + bSizer6->Add( m_staticText2, 0, wxALL, 5 ); + + m_componentViewOld = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE|wxSUNKEN_BORDER ); + m_componentViewOld->SetMinSize( wxSize( 150,150 ) ); + + bSizer6->Add( m_componentViewOld, 1, wxEXPAND | wxALL, 5 ); + + + bSizerView->Add( bSizer6, 1, wxEXPAND, 5 ); + + wxBoxSizer* bSizer7; + bSizer7 = new wxBoxSizer( wxVERTICAL ); + + m_staticText3 = new wxStaticText( this, wxID_ANY, _("Library Part:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText3->Wrap( -1 ); + m_staticText3->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); + + bSizer7->Add( m_staticText3, 0, wxALL, 5 ); + + m_componentViewNew = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE|wxSUNKEN_BORDER ); + m_componentViewNew->SetMinSize( wxSize( 150,150 ) ); + + bSizer7->Add( m_componentViewNew, 1, wxEXPAND | wxALL, 5 ); + + + bSizerView->Add( bSizer7, 1, wxEXPAND, 5 ); + + + bSizerMain->Add( bSizerView, 2, wxEXPAND, 5 ); + + wxBoxSizer* bSizer5; + bSizer5 = new wxBoxSizer( wxHORIZONTAL ); + + m_btnNeverShowAgain = new wxButton( this, wxID_ANY, _("Never Show Again"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer5->Add( m_btnNeverShowAgain, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + + bSizer5->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_stdButtons = new wxStdDialogButtonSizer(); + m_stdButtonsOK = new wxButton( this, wxID_OK ); + m_stdButtons->AddButton( m_stdButtonsOK ); + m_stdButtonsCancel = new wxButton( this, wxID_CANCEL ); + m_stdButtons->AddButton( m_stdButtonsCancel ); + m_stdButtons->Realize(); + + bSizer5->Add( m_stdButtons, 0, wxALL|wxEXPAND, 5 ); + + + bSizerMain->Add( bSizer5, 0, wxEXPAND, 5 ); + + + this->SetSizer( bSizerMain ); + this->Layout(); + + this->Centre( wxBOTH ); + + // Connect Events + this->Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_RESCUE_EACH_BASE::OnDialogResize ) ); + this->Connect( wxID_ANY, wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, wxDataViewEventHandler( DIALOG_RESCUE_EACH_BASE::OnConflictSelect ) ); + m_componentViewOld->Connect( wxEVT_PAINT, wxPaintEventHandler( DIALOG_RESCUE_EACH_BASE::OnHandleCachePreviewRepaint ), NULL, this ); + m_componentViewNew->Connect( wxEVT_PAINT, wxPaintEventHandler( DIALOG_RESCUE_EACH_BASE::OnHandleLibraryPreviewRepaint ), NULL, this ); + m_btnNeverShowAgain->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_RESCUE_EACH_BASE::OnNeverShowClick ), NULL, this ); + m_stdButtonsCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_RESCUE_EACH_BASE::OnCancelClick ), NULL, this ); +} + +DIALOG_RESCUE_EACH_BASE::~DIALOG_RESCUE_EACH_BASE() +{ + // Disconnect Events + this->Disconnect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_RESCUE_EACH_BASE::OnDialogResize ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, wxDataViewEventHandler( DIALOG_RESCUE_EACH_BASE::OnConflictSelect ) ); + m_componentViewOld->Disconnect( wxEVT_PAINT, wxPaintEventHandler( DIALOG_RESCUE_EACH_BASE::OnHandleCachePreviewRepaint ), NULL, this ); + m_componentViewNew->Disconnect( wxEVT_PAINT, wxPaintEventHandler( DIALOG_RESCUE_EACH_BASE::OnHandleLibraryPreviewRepaint ), NULL, this ); + m_btnNeverShowAgain->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_RESCUE_EACH_BASE::OnNeverShowClick ), NULL, this ); + m_stdButtonsCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_RESCUE_EACH_BASE::OnCancelClick ), NULL, this ); + +} diff --git a/eeschema/dialogs/dialog_rescue_each_base.fbp b/eeschema/dialogs/dialog_rescue_each_base.fbp new file mode 100644 index 0000000000..d5209853ff --- /dev/null +++ b/eeschema/dialogs/dialog_rescue_each_base.fbp @@ -0,0 +1,978 @@ + + + + + + C++ + 1 + source_name + 0 + 0 + res + UTF-8 + connect + dialog_rescue_each_base + 1000 + none + 1 + dialog_rescue_each_base + + . + + 1 + 1 + 1 + 1 + UI + 0 + 0 + + 0 + wxAUI_MGR_DEFAULT + + wxBOTH + + 1 + 1 + impl_virtual + + + + 0 + wxID_ANY + + 450,100 + DIALOG_RESCUE_EACH_BASE + + 529,593 + wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER + DIALOG_SHIM; dialog_shim.h + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OnDialogResize + + + + bSizerMain + wxVERTICAL + none + + 5 + wxALL|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + This project uses symbols that no longer match the symbols in the system libraries. Using this tool, you can rescue these cached symbols into a new library. Choose "Rescue" for any parts you would like to save from this project's cache, or press Cancel to allow the symbols to be updated to the new versions. + + 0 + + + 0 + + 1 + m_lblInfo + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + 500 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + ,90,92,-1,70,0 + 0 + 0 + wxID_ANY + Symbols with cache/library conflicts: + + 0 + + + 0 + + 1 + m_staticText5 + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL|wxEXPAND + 2 + + + + 1 + 1 + + + 0 + wxID_ANY + + + m_ListOfConflicts + protected + + + + + + + + + + + + + + + + + + + + + + + + + + + OnConflictSelect + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + ,90,92,-1,70,0 + 0 + 0 + wxID_ANY + Instances of this symbol: + + 0 + + + 0 + + 1 + m_staticText4 + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL|wxEXPAND + 1 + + + + 1 + 1 + + + 0 + wxID_ANY + + + m_ListOfInstances + protected + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND + 2 + + + bSizerView + wxHORIZONTAL + none + + 5 + wxEXPAND + 1 + + + bSizer6 + wxVERTICAL + none + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + ,90,92,-1,70,0 + 0 + 0 + wxID_ANY + Cached Part: + + 0 + + + 0 + + 1 + m_staticText2 + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND | wxALL + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + 150,150 + 1 + m_componentViewOld + 1 + + + protected + 1 + + Resizable + 1 + + + 0 + + + + wxFULL_REPAINT_ON_RESIZE|wxSUNKEN_BORDER + + + + + + + + + + + + + + + + + OnHandleCachePreviewRepaint + + + + + + + + + + + + 5 + wxEXPAND + 1 + + + bSizer7 + wxVERTICAL + none + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + ,90,92,-1,70,0 + 0 + 0 + wxID_ANY + Library Part: + + 0 + + + 0 + + 1 + m_staticText3 + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND | wxALL + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + 150,150 + 1 + m_componentViewNew + 1 + + + protected + 1 + + Resizable + 1 + + + 0 + + + + wxFULL_REPAINT_ON_RESIZE|wxSUNKEN_BORDER + + + + + + + + + + + + + + + + + OnHandleLibraryPreviewRepaint + + + + + + + + + + + + + + 5 + wxEXPAND + 0 + + + bSizer5 + wxHORIZONTAL + none + + 5 + wxALIGN_CENTER_VERTICAL|wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Never Show Again + + 0 + + + 0 + + 1 + m_btnNeverShowAgain + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnNeverShowClick + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND + 1 + + 0 + protected + 0 + + + + 5 + wxALL|wxEXPAND + 0 + + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + + m_stdButtons + protected + + OnCancelClick + + + + + + + + + + + + + + diff --git a/eeschema/dialogs/dialog_rescue_each_base.h b/eeschema/dialogs/dialog_rescue_each_base.h new file mode 100644 index 0000000000..d543edaadd --- /dev/null +++ b/eeschema/dialogs/dialog_rescue_each_base.h @@ -0,0 +1,70 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Mar 13 2015) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#ifndef __DIALOG_RESCUE_EACH_BASE_H__ +#define __DIALOG_RESCUE_EACH_BASE_H__ + +#include +#include +#include +class DIALOG_SHIM; + +#include "dialog_shim.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +/// Class DIALOG_RESCUE_EACH_BASE +/////////////////////////////////////////////////////////////////////////////// +class DIALOG_RESCUE_EACH_BASE : public DIALOG_SHIM +{ + private: + + protected: + wxStaticText* m_lblInfo; + wxStaticText* m_staticText5; + wxDataViewListCtrl* m_ListOfConflicts; + wxStaticText* m_staticText4; + wxDataViewListCtrl* m_ListOfInstances; + wxStaticText* m_staticText2; + wxPanel* m_componentViewOld; + wxStaticText* m_staticText3; + wxPanel* m_componentViewNew; + wxButton* m_btnNeverShowAgain; + wxStdDialogButtonSizer* m_stdButtons; + wxButton* m_stdButtonsOK; + wxButton* m_stdButtonsCancel; + + // Virtual event handlers, overide them in your derived class + virtual void OnDialogResize( wxSizeEvent& event ) { event.Skip(); } + virtual void OnConflictSelect( wxDataViewEvent& event ) { event.Skip(); } + virtual void OnHandleCachePreviewRepaint( wxPaintEvent& event ) { event.Skip(); } + virtual void OnHandleLibraryPreviewRepaint( wxPaintEvent& event ) { event.Skip(); } + virtual void OnNeverShowClick( wxCommandEvent& event ) { event.Skip(); } + virtual void OnCancelClick( wxCommandEvent& event ) { event.Skip(); } + + + public: + + DIALOG_RESCUE_EACH_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 529,593 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + ~DIALOG_RESCUE_EACH_BASE(); + +}; + +#endif //__DIALOG_RESCUE_EACH_BASE_H__ diff --git a/eeschema/dialogs/dialog_rescue_summary.cpp b/eeschema/dialogs/dialog_rescue_summary.cpp new file mode 100644 index 0000000000..5b0ae13064 --- /dev/null +++ b/eeschema/dialogs/dialog_rescue_summary.cpp @@ -0,0 +1,87 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Chris Pavlina + * Copyright (C) 2015 Kicad Developers, see change_log.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 + +class DIALOG_RESCUE_SUMMARY: public DIALOG_RESCUE_SUMMARY_BASE +{ +public: + DIALOG_RESCUE_SUMMARY( SCH_EDIT_FRAME* aParent, std::vector& aRescueLog ); + +private: + SCH_EDIT_FRAME* m_Parent; + wxConfigBase* m_Config; + std::vector* m_RescueLog; + + bool TransferDataToWindow(); + void OnOkClick( wxCommandEvent& event ); +}; + + +DIALOG_RESCUE_SUMMARY::DIALOG_RESCUE_SUMMARY( SCH_EDIT_FRAME* aParent, std::vector& aRescueLog ) + : DIALOG_RESCUE_SUMMARY_BASE( aParent ), m_Parent( aParent), m_RescueLog( &aRescueLog ) +{ } + + +bool DIALOG_RESCUE_SUMMARY::TransferDataToWindow() +{ + if( !wxDialog::TransferDataToWindow() ) + return false; + + m_Config = Kiface().KifaceSettings(); + m_ListOfChanges->AppendTextColumn( wxT( "Reference" ) ); + m_ListOfChanges->AppendTextColumn( wxT( "Old Symbol" ), wxDATAVIEW_CELL_INERT, /*width*/ 100); + m_ListOfChanges->AppendTextColumn( wxT( "New Symbol" ), wxDATAVIEW_CELL_INERT, /*width*/ 100); + + wxVector data; + BOOST_FOREACH( RESCUE_LOG& each_log_item, *m_RescueLog ) + { + data.clear(); + data.push_back( each_log_item.component->GetRef( & m_Parent->GetCurrentSheet() ) ); + data.push_back( each_log_item.old_name ); + data.push_back( each_log_item.new_name ); + m_ListOfChanges->AppendItem( data ); + } + + GetSizer()->Layout(); + GetSizer()->Fit( this ); + GetSizer()->SetSizeHints( this ); + Centre(); + + return true; +} + + +int InvokeDialogRescueSummary( SCH_EDIT_FRAME* aCaller, std::vector& aRescueLog ) +{ + DIALOG_RESCUE_SUMMARY dlg( aCaller, aRescueLog ); + return dlg.ShowModal(); +} diff --git a/eeschema/dialogs/dialog_rescue_summary_base.cpp b/eeschema/dialogs/dialog_rescue_summary_base.cpp new file mode 100644 index 0000000000..15aec6d6b2 --- /dev/null +++ b/eeschema/dialogs/dialog_rescue_summary_base.cpp @@ -0,0 +1,46 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Mar 13 2015) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "dialog_rescue_summary_base.h" + +/////////////////////////////////////////////////////////////////////////// + +DIALOG_RESCUE_SUMMARY_BASE::DIALOG_RESCUE_SUMMARY_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* bmainSizer; + bmainSizer = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bupperSizer; + bupperSizer = new wxBoxSizer( wxVERTICAL ); + + m_staticText5 = new wxStaticText( this, wxID_ANY, _("The symbols of the following components were changed:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText5->Wrap( -1 ); + bupperSizer->Add( m_staticText5, 0, wxALL, 5 ); + + m_ListOfChanges = new wxDataViewListCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + bupperSizer->Add( m_ListOfChanges, 1, wxALL|wxEXPAND, 5 ); + + m_sdbSizer1 = new wxStdDialogButtonSizer(); + m_sdbSizer1OK = new wxButton( this, wxID_OK ); + m_sdbSizer1->AddButton( m_sdbSizer1OK ); + m_sdbSizer1->Realize(); + + bupperSizer->Add( m_sdbSizer1, 0, wxEXPAND, 5 ); + + + bmainSizer->Add( bupperSizer, 1, wxALL|wxEXPAND, 6 ); + + + this->SetSizer( bmainSizer ); + this->Layout(); +} + +DIALOG_RESCUE_SUMMARY_BASE::~DIALOG_RESCUE_SUMMARY_BASE() +{ +} diff --git a/eeschema/dialogs/dialog_rescue_summary_base.fbp b/eeschema/dialogs/dialog_rescue_summary_base.fbp new file mode 100644 index 0000000000..bf528fbbfa --- /dev/null +++ b/eeschema/dialogs/dialog_rescue_summary_base.fbp @@ -0,0 +1,287 @@ + + + + + + C++ + 1 + source_name + 0 + 0 + res + UTF-8 + connect + dialog_rescue_summary_base + 1000 + none + 1 + dialog_rescue_summary_base + + . + + 1 + 1 + 1 + 1 + UI + 0 + 0 + + 0 + wxAUI_MGR_DEFAULT + + + + 1 + 1 + impl_virtual + + + + 0 + wxID_ANY + + + DIALOG_RESCUE_SUMMARY_BASE + + 536,385 + wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER + DIALOG_SHIM; dialog_shim.h + Summary of Library Rescue + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + bmainSizer + wxVERTICAL + none + + 6 + wxALL|wxEXPAND + 1 + + + bupperSizer + wxVERTICAL + none + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + The symbols of the following components were changed: + + 0 + + + 0 + + 1 + m_staticText5 + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL|wxEXPAND + 1 + + + + 1 + 1 + + + 0 + wxID_ANY + + + m_ListOfChanges + protected + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND + 0 + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + + m_sdbSizer1 + protected + + + + + + + + + + + + + + + + diff --git a/eeschema/dialogs/dialog_rescue_summary_base.h b/eeschema/dialogs/dialog_rescue_summary_base.h new file mode 100644 index 0000000000..68dcdf6fc5 --- /dev/null +++ b/eeschema/dialogs/dialog_rescue_summary_base.h @@ -0,0 +1,51 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Mar 13 2015) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#ifndef __DIALOG_RESCUE_SUMMARY_BASE_H__ +#define __DIALOG_RESCUE_SUMMARY_BASE_H__ + +#include +#include +#include +class DIALOG_SHIM; + +#include "dialog_shim.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +/// Class DIALOG_RESCUE_SUMMARY_BASE +/////////////////////////////////////////////////////////////////////////////// +class DIALOG_RESCUE_SUMMARY_BASE : public DIALOG_SHIM +{ + private: + + protected: + wxStaticText* m_staticText5; + wxDataViewListCtrl* m_ListOfChanges; + wxStdDialogButtonSizer* m_sdbSizer1; + wxButton* m_sdbSizer1OK; + + public: + + DIALOG_RESCUE_SUMMARY_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Summary of Library Rescue"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 536,385 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + ~DIALOG_RESCUE_SUMMARY_BASE(); + +}; + +#endif //__DIALOG_RESCUE_SUMMARY_BASE_H__ diff --git a/eeschema/eeschema_id.h b/eeschema/eeschema_id.h index 899c300c25..98c3282e7a 100644 --- a/eeschema/eeschema_id.h +++ b/eeschema/eeschema_id.h @@ -61,6 +61,9 @@ enum id_eeschema_frm ID_UPDATE_ONE_SHEET = ID_END_LIST, ID_SAVE_ONE_SHEET_UNDER_NEW_NAME, + /* Schematic editor main menubar IDs. */ + ID_RESCUE_CACHED, + /* Schematic editor horizontal toolbar IDs */ ID_HIERARCHY, ID_TO_LIBVIEW, diff --git a/eeschema/files-io.cpp b/eeschema/files-io.cpp index 821e6dd72f..23ebcdb479 100644 --- a/eeschema/files-io.cpp +++ b/eeschema/files-io.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -42,6 +43,7 @@ #include #include #include +#include bool SCH_EDIT_FRAME::SaveEEFile( SCH_SCREEN* aScreen, bool aSaveUnderNewName, bool aCreateBackupFile ) @@ -303,6 +305,20 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector& aFileSet, in GetScreen()->ClrModify(); UpdateFileHistory( fullFileName ); + + // Check to see whether some old, cached library parts need to be rescued + // Only do this if RescueNeverShow was not set. + wxConfigBase *config = Kiface().KifaceSettings(); + bool rescueNeverShow = false; + config->Read( wxT("RescueNeverShow"), &rescueNeverShow, false ); + if( !rescueNeverShow ) + { + if( RescueCacheConflicts( false ) ) + { + GetScreen()->CheckComponentsToPartsLinks(); + GetScreen()->TestDanglingEnds(); + } + } } GetScreen()->SetGrid( ID_POPUP_GRID_LEVEL_1000 + m_LastGridSizeId ); diff --git a/eeschema/invoke_sch_dialog.h b/eeschema/invoke_sch_dialog.h index a6d95147e0..959619fa67 100644 --- a/eeschema/invoke_sch_dialog.h +++ b/eeschema/invoke_sch_dialog.h @@ -40,14 +40,40 @@ #ifndef INVOKE_SCH_DIALOG_H_ #define INVOKE_SCH_DIALOG_H_ +#include +#include class wxFrame; class wxDialog; +class LIB_PART; +class PART_LIBS; +class SCH_COMPONENT; +class RESCUE_CANDIDATE; +class RESCUE_LOG; // Often this is not used in the prototypes, since wxFrame is good enough and would // represent maximum information hiding. class SCH_EDIT_FRAME; +/** + * Function InvokeDialogRescueSummary + * This dialog displays a summary of component rescues. + * @param aCaller - the SCH_EDIT_FRAME calling this + * @param aRescueLog - a list of RESCUE_LOG items to show + */ +int InvokeDialogRescueSummary( SCH_EDIT_FRAME* aCaller, std::vector& aRescueLog ); + +/** + * Function InvokeDialogRescueEach + * This dialog asks the user which rescuable, cached parts he wants to rescue. + * Any rejects will be pruned from aCandidates. + * @param aCaller - the SCH_EDIT_FRAME calling this + * @param aCandidates - the list of RESCUE_CANDIDATES + * @param aComponents - a vector of all the components in the schematic + * @param aAskShowAgain - if true, a "Never Show Again" button will be included + */ +int InvokeDialogRescueEach( SCH_EDIT_FRAME* aCaller, std::vector& aCandidates, + std::vector& aComponents, bool aAskShowAgain ); /// Create and show DIALOG_ANNOTATE and return whatever /// DIALOG_ANNOTATE::ShowModal() returns. diff --git a/eeschema/lib_cache_rescue.cpp b/eeschema/lib_cache_rescue.cpp new file mode 100644 index 0000000000..e8f9680dde --- /dev/null +++ b/eeschema/lib_cache_rescue.cpp @@ -0,0 +1,383 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Chris Pavlina + * Copyright (C) 2015 KiCad Developers, see change_log.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 +#include +#include + +#include +#include + + +typedef std::pair COMPONENT_NAME_PAIR; + + +/** + * Function save_library + * writes the library out to disk. Returns true on success. + * + * @param aFileName - Filename to receive the library + * @param aLibrary - Library to write + * @param aEditFrame - the calling SCH_EDIT_FRAME + */ +static bool save_library( const wxString& aFileName, PART_LIB* aLibrary, SCH_EDIT_FRAME* aEditFrame ) +{ + try + { + FILE_OUTPUTFORMATTER formatter( aFileName ); + + if( !aLibrary->Save( formatter ) ) + { + wxString msg = wxString::Format( _( + "An error occurred attempting to save component library '%s'." ), + GetChars( aFileName ) + ); + DisplayError( aEditFrame, msg ); + return false; + } + } + catch( ... /* IO_ERROR ioe */ ) + { + wxString msg = wxString::Format( _( + "Failed to create component library file '%s'" ), + GetChars( aFileName ) + ); + DisplayError( aEditFrame, msg ); + return false; + } + + return true; +} + + +/** + * Function insert_library + * inserts a library into the project and refreshes libraries. + * + * @param aProject - project that will be modified + * @param aLibrary - PART_LIB to add + * @param aIndex - index in the list at which the library is to be inserted + * + * @return true on success, false on failure + */ +static bool insert_library( PROJECT *aProject, PART_LIB *aLibrary, size_t aIndex ) throw( boost::bad_pointer ) +{ + wxArrayString libNames; + wxString libPaths; + + wxString libName = aLibrary->GetName(); + PART_LIBS *libs = dynamic_cast( aProject->GetElem( PROJECT::ELEM_SCH_PART_LIBS ) ); + if( !libs ) + { + libs = new PART_LIBS(); + aProject->SetElem( PROJECT::ELEM_SCH_PART_LIBS, libs ); + } + + PART_LIBS::LibNamesAndPaths( aProject, false, &libPaths, &libNames ); + + // Make sure the library is not already in the list + while( libNames.Index( libName ) != wxNOT_FOUND ) + libNames.Remove( libName ); + + // Add the library to the list and save + libNames.Insert( libName, aIndex ); + PART_LIBS::LibNamesAndPaths( aProject, true, &libPaths, &libNames ); + + // Save the old libraries in case there is a problem after clear(). We'll + // put them back in. + boost::ptr_vector libsSave; + libsSave.transfer( libsSave.end(), libs->begin(), libs->end(), *libs ); + + aProject->SetElem( PROJECT::ELEM_SCH_PART_LIBS, NULL ); + + libs = new PART_LIBS(); + try + { + libs->LoadAllLibraries( aProject ); + } + catch( const PARSE_ERROR& e ) + { + // Some libraries were not found. There's no point in showing the error, + // because it was already shown. Just don't do anything. + } + catch( const IO_ERROR& e ) + { + // Restore the old list + libs->clear(); + libs->transfer( libs->end(), libsSave.begin(), libsSave.end(), libsSave ); + return false; + } + aProject->SetElem( PROJECT::ELEM_SCH_PART_LIBS, libs ); + + return true; +} + + +/** + * Function get_components + * Fills a vector with all of the project's components, to ease iterating over them. + * + * @param aComponents - a vector that will take the components + */ +static void get_components( std::vector& aComponents ) +{ + 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 ) continue; + SCH_COMPONENT* component = dynamic_cast( item ); + aComponents.push_back( component ); + } + } +} + + +/** + * Function find_component + * Search the libraries for the first component with a given name. + * + * @param aName - name to search for + * @param aLibs - the loaded PART_LIBS + * @param aCached - whether we are looking for the cached part + */ +static LIB_PART* find_component( wxString aName, PART_LIBS* aLibs, bool aCached ) +{ + LIB_PART *part = NULL; + + BOOST_FOREACH( PART_LIB& each_lib, *aLibs ) + { + if( aCached && !each_lib.IsCache() ) + continue; + + if( !aCached && each_lib.IsCache() ) + continue; + + part = each_lib.FindPart( aName ); + if( part ) + break; + } + + return part; +} + + +/** + * Function find_rescues + * Search components for any that request a part that conflicts with the + * library parts. + * + * This is done from the component side to track requested aliases. + * + * @param aComponents - a vector of components to scan + * @param aLibs - the loaded PART_LIBS + * @param aCandidates - a vector to hold rescue candidates + */ +static void find_rescues( std::vector& aComponents, PART_LIBS* aLibs, + std::vector& aCandidates ) +{ + // We need to narrow down the list and avoid having multiple copies of the + // same name. Therefore, we'll assemble in a map first, before pushing to + // the vector. + typedef std::map candidate_map_t; + candidate_map_t candidate_map; + BOOST_FOREACH( SCH_COMPONENT* each_component, aComponents ) + { + wxString part_name( each_component->GetPartName() ); + LIB_PART* cache_match = find_component( part_name, aLibs, /* aCached */ true ); + LIB_PART* lib_match = find_component( part_name, aLibs, /* aCached */ false ); + + // Test whether there is a conflict + if( !cache_match || !lib_match ) + continue; + if( !cache_match->PinsConflictWith( *lib_match, /* aTestNums */ true, /* aTestNames */ false, + /* aTestType */ true, /* aTestOrientation */ true, /* aTestLength */ false )) + continue; + + RESCUE_CANDIDATE candidate; + candidate.requested_name = part_name; + candidate.cache_candidate = cache_match; + candidate.lib_candidate = lib_match; + + candidate_map[part_name] = candidate; + } + + // Now, dump the map into aCandidates + BOOST_FOREACH( const candidate_map_t::value_type& each_pair, candidate_map ) + { + aCandidates.push_back( each_pair.second ); + } +} + + +/** + * Function create_rescue_library + * Creates and returns a PART_LIB object for storing rescued components. + * @param aFileName - wxFileName to receive the library's file name + */ +static PART_LIB* create_rescue_library( wxFileName& aFileName ) +{ + wxFileName fn( g_RootSheet->GetScreen()->GetFileName() ); + fn.SetName( fn.GetName() + wxT("-rescue") ); + fn.SetExt( SchematicLibraryFileExtension ); + aFileName.SetPath( fn.GetPath() ); + aFileName.SetName( fn.GetName() ); + aFileName.SetExt( wxT( "lib" ) ); + return new PART_LIB( LIBRARY_TYPE_EESCHEMA, fn.GetFullPath() ); +} + + +/** + * Function rescue_components + * Rescues components from aCandidates into aLibrary + * @param aCandidates - list of final rescue candidates to be rescued + * @param aLibrary - library for them to be rescued into + * @param aSuffix - part name suffix to apply to them + */ +static void rescue_components( std::vector& aCandidates, PART_LIB* aLibrary, const wxString &aSuffix ) +{ + BOOST_FOREACH( RESCUE_CANDIDATE& each_candidate, aCandidates ) + { + LIB_PART new_part( *each_candidate.cache_candidate, aLibrary ); + new_part.SetName( each_candidate.requested_name + aSuffix ); + new_part.RemoveAllAliases(); + aLibrary->AddPart( &new_part ); + } +} + + +/** + * Function update_components + * Update components to reflect changed names of rescued parts. + * Saves components with the original names to aRescueLog to allow recovering from errors and + * displaying summary. + * + * @param aComponents - a populated list of all components + * @param aCandidates - list of rescue candidates + * @param aSuffix - part name suffix + * @param aRescueLog - rescue log + */ +static void update_components( std::vector& aComponents, std::vector& aCandidates, + const wxString& aSuffix, std::vector& aRescueLog ) +{ + BOOST_FOREACH( RESCUE_CANDIDATE& each_candidate, aCandidates ) + { + BOOST_FOREACH( SCH_COMPONENT* each_component, aComponents ) + { + if( each_component->GetPartName() != each_candidate.requested_name ) continue; + + wxString new_name = each_candidate.requested_name + aSuffix; + each_component->SetPartName( new_name ); + + RESCUE_LOG log_item; + log_item.component = each_component; + log_item.old_name = each_candidate.requested_name; + log_item.new_name = new_name; + aRescueLog.push_back( log_item ); + } + } +} + + +bool SCH_EDIT_FRAME::RescueCacheConflicts( bool aRunningOnDemand ) +{ + // Data that will be used throughout the operation + std::vector candidates; + std::vector components; + PART_LIBS* libs; + wxString part_name_suffix; + PROJECT* prj; + + // Prepare data + get_components( components ); + prj = &Prj(); + libs = prj->SchLibs(); + part_name_suffix = wxT("-RESCUE-") + prj->GetProjectName(); + + // Start! + find_rescues( components, libs, candidates ); + if( candidates.empty() ) + { + if( aRunningOnDemand ) + { + wxMessageDialog dlg( this, _( "There are no conflicting symbols to rescue from the cache." ) ); + dlg.ShowModal(); + } + return true; + } + InvokeDialogRescueEach( this, candidates, components, /* aAskShowAgain */ !aRunningOnDemand ); + wxFileName library_fn; + std::auto_ptr rescue_lib( create_rescue_library( library_fn ) ); + rescue_components( candidates, rescue_lib.get(), part_name_suffix ); + if( !save_library( library_fn.GetFullPath(), rescue_lib.get(), this ) ) + { + // Save failed. Do not update the components. + return false; + } + + // Update components to reflect changed names + std::vector rescue_log; + update_components( components, candidates, part_name_suffix, rescue_log ); + + if( rescue_log.empty() ) + { + wxMessageDialog dlg( this, _( "No cached symbols were rescued." ) ); + dlg.ShowModal(); + return true; + } + else + { + // Try inserting the library into the project + if( insert_library( prj, rescue_lib.get(), 0 ) ) + { + InvokeDialogRescueSummary( this, rescue_log ); + + // Clean up wire ends + INSTALL_UNBUFFERED_DC( dc, m_canvas ); + GetScreen()->SchematicCleanUp( NULL, &dc ); + m_canvas->Refresh( true ); + OnModify(); + + return true; + } + else + { + // Unsuccessful! Restore all the components + BOOST_FOREACH( RESCUE_LOG& rescue_log_item, rescue_log ) + { + rescue_log_item.component->SetPartName( rescue_log_item.old_name ); + } + wxMessageDialog dlg( this, _( "An error occurred while attempting to rescue components. No changes have been made." ) ); + return false; + } + } +} diff --git a/eeschema/lib_cache_rescue.h b/eeschema/lib_cache_rescue.h new file mode 100644 index 0000000000..b84138f4bb --- /dev/null +++ b/eeschema/lib_cache_rescue.h @@ -0,0 +1,69 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Chris Pavlina + * Copyright (C) 2015 KiCad Developers, see change_log.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 + */ + +#ifndef _LIB_CACHE_RESCUE_H_ +#define _LIB_CACHE_RESCUE_H_ + +/* This code handles the case where an old schematic has parts that have + * changed in the system libraries, such that their pins no longer line up. + * The function of note is a member of SCH_EDIT_FRAME, defined thus: + * + * bool SCH_EDIT_FRAME::RescueCacheConflicts( bool aSilentIfNone ); + * + * When this is called, a list of component names referring to conflicting + * symbols is compiled. If this list is empty, then the function displays + * a notification and returns (if aSilentIfNone is true, the notification is + * silenced). + * + * The user is then prompted to select which parts he would like to rescue. + * Any remaining after he's through are rescued: they are renamed to avoid + * further conflicts, and then they are copied into a new library. The + * schematic components are updated to link to these new names, the library + * is saved, and the library is added to the project at the top of the + * search path. + */ + +#include +#include + +class LIB_PART; +class SCH_COMPONENT; + +class RESCUE_CANDIDATE +{ +public: + wxString requested_name; + LIB_PART* cache_candidate; + LIB_PART* lib_candidate; +}; + +class RESCUE_LOG +{ +public: + SCH_COMPONENT* component; + wxString old_name; + wxString new_name; +}; + +#endif // _LIB_CACHE_RESCUE_H_ diff --git a/eeschema/lib_collectors.h b/eeschema/lib_collectors.h index 293c33fd2a..e1b02a4aac 100644 --- a/eeschema/lib_collectors.h +++ b/eeschema/lib_collectors.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 20011 KiCad Developers, see change_log.txt for contributors. + * Copyright (C) 2011 KiCad Developers, see change_log.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 diff --git a/eeschema/menubar.cpp b/eeschema/menubar.cpp index 19800cae60..6027f876e7 100644 --- a/eeschema/menubar.cpp +++ b/eeschema/menubar.cpp @@ -436,6 +436,12 @@ void SCH_EDIT_FRAME::ReCreateMenuBar() _( "Library &Browser" ), HELP_RUN_LIB_VIEWER, KiBitmap( library_browse_xpm ) ); + AddMenuItem( toolsMenu, + ID_RESCUE_CACHED, + _( "&Rescue Cached Components" ), + _( "Find old components in the project cache and rescue them to a new library" ), + KiBitmap( copycomponent_xpm ) ); + toolsMenu->AppendSeparator(); AddMenuItem( toolsMenu, diff --git a/eeschema/schframe.cpp b/eeschema/schframe.cpp index edae214e3a..e3927e5808 100644 --- a/eeschema/schframe.cpp +++ b/eeschema/schframe.cpp @@ -227,6 +227,7 @@ BEGIN_EVENT_TABLE( SCH_EDIT_FRAME, EDA_DRAW_FRAME ) EVT_TOOL( ID_RUN_LIBRARY, SCH_EDIT_FRAME::OnOpenLibraryEditor ) EVT_TOOL( ID_POPUP_SCH_CALL_LIBEDIT_AND_LOAD_CMP, SCH_EDIT_FRAME::OnOpenLibraryEditor ) EVT_TOOL( ID_TO_LIBVIEW, SCH_EDIT_FRAME::OnOpenLibraryViewer ) + EVT_TOOL( ID_RESCUE_CACHED, SCH_EDIT_FRAME::OnRescueCached ) EVT_TOOL( ID_RUN_PCB, SCH_EDIT_FRAME::OnOpenPcbnew ) EVT_TOOL( ID_RUN_PCB_MODULE_EDITOR, SCH_EDIT_FRAME::OnOpenPcbModuleEditor ) @@ -1058,6 +1059,10 @@ void SCH_EDIT_FRAME::OnOpenLibraryEditor( wxCommandEvent& event ) } } +void SCH_EDIT_FRAME::OnRescueCached( wxCommandEvent& event ) +{ + RescueCacheConflicts( true ); +} void SCH_EDIT_FRAME::OnExit( wxCommandEvent& event ) { diff --git a/eeschema/schframe.h b/eeschema/schframe.h index 8b2ba0b6b0..587d69e367 100644 --- a/eeschema/schframe.h +++ b/eeschema/schframe.h @@ -808,6 +808,7 @@ private: void OnOpenPcbModuleEditor( wxCommandEvent& event ); void OnOpenCvpcb( wxCommandEvent& event ); void OnOpenLibraryEditor( wxCommandEvent& event ); + void OnRescueCached( wxCommandEvent& event ); void OnPreferencesOptions( wxCommandEvent& event ); void OnCancelCurrentCommand( wxCommandEvent& aEvent ); @@ -1259,6 +1260,20 @@ public: */ bool CreateArchiveLibrary( const wxString& aFileName ); + /** + * Function RescueCacheConflicts + * exports components from the '-cache' library that conflict with parts + * in the project libraries to a new library, renaming them to add a suffix + * of the root document's name to avoid conflicts. + * + * @param aRunningOnDemand - indicates whether the tool has been called up by the user + * (as opposed to being run automatically). If true, an information dialog is + * displayed if there are no components to rescue. If false, the tool is silent + * if there are no components to rescue, and a "Never Show Again" button is + * displayed. + */ + bool RescueCacheConflicts( bool aRunningOnDemand ); + /** * Function PrintPage * plots or prints the current sheet to the clipboard. diff --git a/include/project.h b/include/project.h index c7b2a123b3..5e5898f489 100644 --- a/include/project.h +++ b/include/project.h @@ -93,6 +93,13 @@ public: */ VTBL_ENTRY const wxString GetProjectPath() const; + /** + * Function GetProjectName + * returns the short name of the project. This is the file name without + * extension or path. + */ + VTBL_ENTRY const wxString GetProjectName() const; + /** * Function FootprintLibTblName * returns the path and filename of this project's fp-lib-table,