Eeschema: component library rescue improvements.
* Fix case sensitive component library name searches * Factor out rescue code into a generic rescue project class.
This commit is contained in:
parent
c55e729117
commit
80eb5460f9
|
@ -114,7 +114,6 @@ set( EESCHEMA_SRCS
|
||||||
libedit_undo_redo.cpp
|
libedit_undo_redo.cpp
|
||||||
lib_arc.cpp
|
lib_arc.cpp
|
||||||
lib_bezier.cpp
|
lib_bezier.cpp
|
||||||
lib_cache_rescue.cpp
|
|
||||||
lib_circle.cpp
|
lib_circle.cpp
|
||||||
lib_collectors.cpp
|
lib_collectors.cpp
|
||||||
lib_draw_item.cpp
|
lib_draw_item.cpp
|
||||||
|
@ -139,6 +138,7 @@ set( EESCHEMA_SRCS
|
||||||
plot_schematic_PS.cpp
|
plot_schematic_PS.cpp
|
||||||
plot_schematic_PDF.cpp
|
plot_schematic_PDF.cpp
|
||||||
plot_schematic_SVG.cpp
|
plot_schematic_SVG.cpp
|
||||||
|
project_rescue.cpp
|
||||||
sch_base_frame.cpp
|
sch_base_frame.cpp
|
||||||
sch_bitmap.cpp
|
sch_bitmap.cpp
|
||||||
sch_bus_entry.cpp
|
sch_bus_entry.cpp
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
#include <richio.h>
|
#include <richio.h>
|
||||||
#include <config_params.h>
|
#include <config_params.h>
|
||||||
#include <wildcards_and_files_ext.h>
|
#include <wildcards_and_files_ext.h>
|
||||||
#include <lib_cache_rescue.h>
|
#include <project_rescue.h>
|
||||||
//#include <richio.h>
|
//#include <richio.h>
|
||||||
|
|
||||||
#include <general.h>
|
#include <general.h>
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
#include <lib_cache_rescue.h>
|
#include <project_rescue.h>
|
||||||
#include <eeschema_config.h>
|
#include <eeschema_config.h>
|
||||||
|
|
||||||
class DIALOG_RESCUE_EACH: public DIALOG_RESCUE_EACH_BASE
|
class DIALOG_RESCUE_EACH: public DIALOG_RESCUE_EACH_BASE
|
||||||
|
@ -43,24 +43,19 @@ public:
|
||||||
* This dialog asks the user which rescuable, cached parts he wants to rescue.
|
* This dialog asks the user which rescuable, cached parts he wants to rescue.
|
||||||
* Any rejects will be pruned from aCandidates.
|
* Any rejects will be pruned from aCandidates.
|
||||||
* @param aCaller - the SCH_EDIT_FRAME calling this
|
* @param aCaller - the SCH_EDIT_FRAME calling this
|
||||||
* @param aCandidates - the list of RESCUE_CANDIDATES
|
* @param aRescuer - the active RESCUER instance
|
||||||
* @param aComponents - a vector of all the components in the schematic
|
|
||||||
* @param aAskShowAgain - if true, a "Never Show Again" button will be included
|
* @param aAskShowAgain - if true, a "Never Show Again" button will be included
|
||||||
*/
|
*/
|
||||||
DIALOG_RESCUE_EACH( SCH_EDIT_FRAME* aParent, std::vector<RESCUE_CANDIDATE>& aCandidates,
|
DIALOG_RESCUE_EACH( SCH_EDIT_FRAME* aParent, RESCUER& aRescuer, bool aAskShowAgain );
|
||||||
std::vector<SCH_COMPONENT*>& aComponents, bool aAskShowAgain );
|
|
||||||
|
|
||||||
~DIALOG_RESCUE_EACH();
|
~DIALOG_RESCUE_EACH();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SCH_EDIT_FRAME* m_Parent;
|
SCH_EDIT_FRAME* m_Parent;
|
||||||
wxConfigBase* m_Config;
|
wxConfigBase* m_Config;
|
||||||
std::vector<RESCUE_CANDIDATE>* m_Candidates;
|
RESCUER* m_Rescuer;
|
||||||
std::vector<SCH_COMPONENT*>* m_Components;
|
|
||||||
bool m_AskShowAgain;
|
bool m_AskShowAgain;
|
||||||
|
|
||||||
bool m_insideUpdateEvent;
|
|
||||||
|
|
||||||
bool TransferDataToWindow();
|
bool TransferDataToWindow();
|
||||||
bool TransferDataFromWindow();
|
bool TransferDataFromWindow();
|
||||||
void PopulateConflictList();
|
void PopulateConflictList();
|
||||||
|
@ -75,31 +70,22 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
DIALOG_RESCUE_EACH::DIALOG_RESCUE_EACH( SCH_EDIT_FRAME* aParent, std::vector<RESCUE_CANDIDATE>& aCandidates,
|
DIALOG_RESCUE_EACH::DIALOG_RESCUE_EACH( SCH_EDIT_FRAME* aParent, RESCUER& aRescuer,
|
||||||
std::vector<SCH_COMPONENT*>& aComponents, bool aAskShowAgain )
|
bool aAskShowAgain )
|
||||||
|
|
||||||
: DIALOG_RESCUE_EACH_BASE( aParent ),
|
: DIALOG_RESCUE_EACH_BASE( aParent ),
|
||||||
m_Parent( aParent ),
|
m_Parent( aParent ),
|
||||||
m_Candidates( &aCandidates ),
|
m_Rescuer( &aRescuer ),
|
||||||
m_Components( &aComponents ),
|
m_AskShowAgain( aAskShowAgain )
|
||||||
m_AskShowAgain( aAskShowAgain ),
|
|
||||||
m_insideUpdateEvent( false )
|
|
||||||
{
|
{
|
||||||
m_Config = Kiface().KifaceSettings();
|
m_Config = Kiface().KifaceSettings();
|
||||||
m_stdButtonsOK->SetDefault();
|
m_stdButtonsOK->SetDefault();
|
||||||
|
|
||||||
// Set the info message, customized to include the proper suffix.
|
// Set the info message, customized to include the proper suffix.
|
||||||
wxString info_message;
|
wxString info_message =
|
||||||
info_message.Printf(
|
_( "It looks like this project was made using older schematic component libraries.\n"
|
||||||
_( "This project uses symbols that no longer match the ones in the system libraries.\n"
|
"Some parts may need to be relinked to a different symbol name, and some symbols\n"
|
||||||
"Using this tool, you can rescue these cached symbols into a new library.\n"
|
"may need to be \"rescued\" into a new library.\n"
|
||||||
"\n"
|
"The following changes are recommended to update the project.\n" );
|
||||||
"Choose \"Rescue\" for any parts you would like to save from this project's cache,\n"
|
|
||||||
"or press \"Cancel\" to allow the symbols to be updated to the new versions.\n"
|
|
||||||
"\n"
|
|
||||||
"All rescued components will be renamed with a new suffix of \"-RESCUE-%s\"\n"
|
|
||||||
"to avoid naming conflicts." ),
|
|
||||||
Prj().GetProjectName() );
|
|
||||||
m_lblInfo->SetLabel( info_message );
|
m_lblInfo->SetLabel( info_message );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,8 +100,9 @@ bool DIALOG_RESCUE_EACH::TransferDataToWindow()
|
||||||
if( !wxDialog::TransferDataToWindow() )
|
if( !wxDialog::TransferDataToWindow() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_ListOfConflicts->AppendToggleColumn( _( "Rescue symbol" ) );
|
m_ListOfConflicts->AppendToggleColumn( _( "Accept" ) );
|
||||||
m_ListOfConflicts->AppendTextColumn( _( "Symbol name" ) );
|
m_ListOfConflicts->AppendTextColumn( _( "Symbol" ) );
|
||||||
|
m_ListOfConflicts->AppendTextColumn( _( "Action" ) );
|
||||||
m_ListOfInstances->AppendTextColumn( _( "Reference" ) );
|
m_ListOfInstances->AppendTextColumn( _( "Reference" ) );
|
||||||
m_ListOfInstances->AppendTextColumn( _( "Value" ) );
|
m_ListOfInstances->AppendTextColumn( _( "Value" ) );
|
||||||
PopulateConflictList();
|
PopulateConflictList();
|
||||||
|
@ -136,11 +123,13 @@ bool DIALOG_RESCUE_EACH::TransferDataToWindow()
|
||||||
void DIALOG_RESCUE_EACH::PopulateConflictList()
|
void DIALOG_RESCUE_EACH::PopulateConflictList()
|
||||||
{
|
{
|
||||||
wxVector<wxVariant> data;
|
wxVector<wxVariant> data;
|
||||||
BOOST_FOREACH( RESCUE_CANDIDATE& each_candidate, *m_Candidates )
|
BOOST_FOREACH( RESCUE_CANDIDATE& each_candidate, m_Rescuer->m_all_candidates )
|
||||||
{
|
{
|
||||||
data.clear();
|
data.clear();
|
||||||
data.push_back( wxVariant( true ) );
|
data.push_back( wxVariant( true ) );
|
||||||
data.push_back( each_candidate.requested_name );
|
data.push_back( each_candidate.GetRequestedName() );
|
||||||
|
data.push_back( each_candidate.GetActionDescription() );
|
||||||
|
|
||||||
m_ListOfConflicts->AppendItem( data );
|
m_ListOfConflicts->AppendItem( data );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,12 +144,12 @@ void DIALOG_RESCUE_EACH::PopulateInstanceList()
|
||||||
if( row == wxNOT_FOUND )
|
if( row == wxNOT_FOUND )
|
||||||
row = 0;
|
row = 0;
|
||||||
|
|
||||||
RESCUE_CANDIDATE& selected_part = (*m_Candidates)[row];
|
RESCUE_CANDIDATE& selected_part = m_Rescuer->m_all_candidates[row];
|
||||||
|
|
||||||
wxVector<wxVariant> data;
|
wxVector<wxVariant> data;
|
||||||
BOOST_FOREACH( SCH_COMPONENT* each_component, *m_Components )
|
BOOST_FOREACH( SCH_COMPONENT* each_component, *m_Rescuer->GetComponents() )
|
||||||
{
|
{
|
||||||
if( each_component->GetPartName() != selected_part.requested_name )
|
if( each_component->GetPartName() != selected_part.GetRequestedName() )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
SCH_FIELD* valueField = each_component->GetField( 1 );
|
SCH_FIELD* valueField = each_component->GetField( 1 );
|
||||||
|
@ -181,9 +170,10 @@ void DIALOG_RESCUE_EACH::OnHandleCachePreviewRepaint( wxPaintEvent& aRepaintEven
|
||||||
if( row == wxNOT_FOUND )
|
if( row == wxNOT_FOUND )
|
||||||
row = 0;
|
row = 0;
|
||||||
|
|
||||||
RESCUE_CANDIDATE& selected_part = (*m_Candidates)[row];
|
RESCUE_CANDIDATE& selected_part = m_Rescuer->m_all_candidates[row];
|
||||||
|
|
||||||
renderPreview( selected_part.cache_candidate, 0, m_componentViewOld );
|
if( selected_part.GetCacheCandidate() )
|
||||||
|
renderPreview( selected_part.GetCacheCandidate(), 0, m_componentViewOld );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -194,9 +184,10 @@ void DIALOG_RESCUE_EACH::OnHandleLibraryPreviewRepaint( wxPaintEvent& aRepaintEv
|
||||||
if( row == wxNOT_FOUND )
|
if( row == wxNOT_FOUND )
|
||||||
row = 0;
|
row = 0;
|
||||||
|
|
||||||
RESCUE_CANDIDATE& selected_part = (*m_Candidates)[row];
|
RESCUE_CANDIDATE& selected_part = m_Rescuer->m_all_candidates[row];
|
||||||
|
|
||||||
renderPreview( selected_part.lib_candidate, 0, m_componentViewNew );
|
if( selected_part.GetLibCandidate() )
|
||||||
|
renderPreview( selected_part.GetLibCandidate(), 0, m_componentViewNew );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -269,19 +260,15 @@ bool DIALOG_RESCUE_EACH::TransferDataFromWindow()
|
||||||
if( !wxDialog::TransferDataFromWindow() )
|
if( !wxDialog::TransferDataFromWindow() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::vector<RESCUE_CANDIDATE>::iterator it = m_Candidates->begin();
|
for( size_t index = 0; index < m_Rescuer->GetCandidateCount(); ++index )
|
||||||
for( size_t index = 0; it != m_Candidates->end(); ++index )
|
|
||||||
{
|
{
|
||||||
wxVariant val;
|
wxVariant val;
|
||||||
m_ListOfConflicts->GetValue( val, index, 0 );
|
m_ListOfConflicts->GetValue( val, index, 0 );
|
||||||
bool rescue_part = val.GetBool();
|
bool rescue_part = val.GetBool();
|
||||||
|
|
||||||
if( !rescue_part )
|
if( rescue_part )
|
||||||
m_Candidates->erase( it );
|
m_Rescuer->m_chosen_candidates.push_back( &m_Rescuer->m_all_candidates[index] );
|
||||||
else
|
|
||||||
++it;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,7 +286,7 @@ void DIALOG_RESCUE_EACH::OnNeverShowClick( wxCommandEvent& aEvent )
|
||||||
if( resp == wxID_YES )
|
if( resp == wxID_YES )
|
||||||
{
|
{
|
||||||
m_Config->Write( RESCUE_NEVER_SHOW_KEY, true );
|
m_Config->Write( RESCUE_NEVER_SHOW_KEY, true );
|
||||||
m_Candidates->clear();
|
m_Rescuer->m_chosen_candidates.clear();
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -307,14 +294,13 @@ void DIALOG_RESCUE_EACH::OnNeverShowClick( wxCommandEvent& aEvent )
|
||||||
|
|
||||||
void DIALOG_RESCUE_EACH::OnCancelClick( wxCommandEvent& aEvent )
|
void DIALOG_RESCUE_EACH::OnCancelClick( wxCommandEvent& aEvent )
|
||||||
{
|
{
|
||||||
m_Candidates->clear();
|
m_Rescuer->m_chosen_candidates.clear();
|
||||||
DIALOG_RESCUE_EACH_BASE::OnCancelClick( aEvent );
|
DIALOG_RESCUE_EACH_BASE::OnCancelClick( aEvent );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int InvokeDialogRescueEach( SCH_EDIT_FRAME* aCaller, std::vector<RESCUE_CANDIDATE>& aCandidates,
|
int InvokeDialogRescueEach( SCH_EDIT_FRAME* aCaller, RESCUER& aRescuer, bool aAskShowAgain )
|
||||||
std::vector<SCH_COMPONENT*>& aComponents, bool aAskShowAgain )
|
|
||||||
{
|
{
|
||||||
DIALOG_RESCUE_EACH dlg( aCaller, aCandidates, aComponents, aAskShowAgain );
|
DIALOG_RESCUE_EACH dlg( aCaller, aRescuer, aAskShowAgain );
|
||||||
return dlg.ShowModal();
|
return dlg.ShowModal();
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ DIALOG_RESCUE_EACH_BASE::DIALOG_RESCUE_EACH_BASE( wxWindow* parent, wxWindowID i
|
||||||
m_lblInfo->Wrap( 500 );
|
m_lblInfo->Wrap( 500 );
|
||||||
bSizerMain->Add( m_lblInfo, 0, wxALL|wxEXPAND, 5 );
|
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 = new wxStaticText( this, wxID_ANY, _("Symbols to update:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
m_staticText5->Wrap( -1 );
|
m_staticText5->Wrap( -1 );
|
||||||
m_staticText5->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
|
m_staticText5->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
|
||||||
|
|
||||||
|
|
|
@ -208,7 +208,7 @@
|
||||||
<property name="gripper">0</property>
|
<property name="gripper">0</property>
|
||||||
<property name="hidden">0</property>
|
<property name="hidden">0</property>
|
||||||
<property name="id">wxID_ANY</property>
|
<property name="id">wxID_ANY</property>
|
||||||
<property name="label">Symbols with cache/library conflicts:</property>
|
<property name="label">Symbols to update:</property>
|
||||||
<property name="max_size"></property>
|
<property name="max_size"></property>
|
||||||
<property name="maximize_button">0</property>
|
<property name="maximize_button">0</property>
|
||||||
<property name="maximum_size"></property>
|
<property name="maximum_size"></property>
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
#include <sch_sheet_path.h>
|
#include <sch_sheet_path.h>
|
||||||
#include <sch_component.h>
|
#include <sch_component.h>
|
||||||
#include <wildcards_and_files_ext.h>
|
#include <wildcards_and_files_ext.h>
|
||||||
#include <lib_cache_rescue.h>
|
#include <project_rescue.h>
|
||||||
#include <eeschema_config.h>
|
#include <eeschema_config.h>
|
||||||
|
|
||||||
|
|
||||||
|
@ -307,7 +307,7 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
|
||||||
|
|
||||||
UpdateFileHistory( fullFileName );
|
UpdateFileHistory( fullFileName );
|
||||||
|
|
||||||
// Check to see whether some old, cached library parts need to be rescued
|
// Check to see whether some old library parts need to be rescued
|
||||||
// Only do this if RescueNeverShow was not set.
|
// Only do this if RescueNeverShow was not set.
|
||||||
wxConfigBase *config = Kiface().KifaceSettings();
|
wxConfigBase *config = Kiface().KifaceSettings();
|
||||||
bool rescueNeverShow = false;
|
bool rescueNeverShow = false;
|
||||||
|
@ -315,7 +315,7 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
|
||||||
|
|
||||||
if( !rescueNeverShow )
|
if( !rescueNeverShow )
|
||||||
{
|
{
|
||||||
if( RescueCacheConflicts( false ) )
|
if( RescueProject( false ) )
|
||||||
{
|
{
|
||||||
GetScreen()->CheckComponentsToPartsLinks();
|
GetScreen()->CheckComponentsToPartsLinks();
|
||||||
GetScreen()->TestDanglingEnds();
|
GetScreen()->TestDanglingEnds();
|
||||||
|
|
|
@ -48,8 +48,7 @@ class wxDialog;
|
||||||
class LIB_PART;
|
class LIB_PART;
|
||||||
class PART_LIBS;
|
class PART_LIBS;
|
||||||
class SCH_COMPONENT;
|
class SCH_COMPONENT;
|
||||||
class RESCUE_CANDIDATE;
|
class RESCUER;
|
||||||
class RESCUE_LOG;
|
|
||||||
|
|
||||||
// Often this is not used in the prototypes, since wxFrame is good enough and would
|
// Often this is not used in the prototypes, since wxFrame is good enough and would
|
||||||
// represent maximum information hiding.
|
// represent maximum information hiding.
|
||||||
|
@ -60,12 +59,10 @@ class SCH_EDIT_FRAME;
|
||||||
* This dialog asks the user which rescuable, cached parts he wants to rescue.
|
* This dialog asks the user which rescuable, cached parts he wants to rescue.
|
||||||
* Any rejects will be pruned from aCandidates.
|
* Any rejects will be pruned from aCandidates.
|
||||||
* @param aCaller - the SCH_EDIT_FRAME calling this
|
* @param aCaller - the SCH_EDIT_FRAME calling this
|
||||||
* @param aCandidates - the list of RESCUE_CANDIDATES
|
* @param aRescuer - the active RESCUER instance
|
||||||
* @param aComponents - a vector of all the components in the schematic
|
|
||||||
* @param aAskShowAgain - if true, a "Never Show Again" button will be included
|
* @param aAskShowAgain - if true, a "Never Show Again" button will be included
|
||||||
*/
|
*/
|
||||||
int InvokeDialogRescueEach( SCH_EDIT_FRAME* aCaller, std::vector<RESCUE_CANDIDATE>& aCandidates,
|
int InvokeDialogRescueEach( SCH_EDIT_FRAME* aCaller, RESCUER& aRescuer, bool aAskShowAgain );
|
||||||
std::vector<SCH_COMPONENT*>& aComponents, bool aAskShowAgain );
|
|
||||||
|
|
||||||
/// Create and show DIALOG_ANNOTATE and return whatever
|
/// Create and show DIALOG_ANNOTATE and return whatever
|
||||||
/// DIALOG_ANNOTATE::ShowModal() returns.
|
/// DIALOG_ANNOTATE::ShowModal() returns.
|
||||||
|
|
|
@ -1,385 +0,0 @@
|
||||||
/*
|
|
||||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2015 Chris Pavlina <pavlina.chris@gmail.com>
|
|
||||||
* 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 <class_drawpanel.h>
|
|
||||||
#include <class_library.h>
|
|
||||||
#include <confirm.h>
|
|
||||||
#include <invoke_sch_dialog.h>
|
|
||||||
#include <kicad_device_context.h>
|
|
||||||
#include <lib_cache_rescue.h>
|
|
||||||
#include <sch_component.h>
|
|
||||||
#include <sch_sheet.h>
|
|
||||||
#include <schframe.h>
|
|
||||||
#include <wildcards_and_files_ext.h>
|
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
|
|
||||||
typedef std::pair<SCH_COMPONENT*, wxString> 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<PART_LIBS*>( 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<PART_LIB> 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<SCH_COMPONENT*>& 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<SCH_COMPONENT*>( 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<SCH_COMPONENT*>& aComponents, PART_LIBS* aLibs,
|
|
||||||
std::vector<RESCUE_CANDIDATE>& 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<wxString, RESCUE_CANDIDATE> 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 */ true,
|
|
||||||
/* 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<RESCUE_CANDIDATE>& 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<SCH_COMPONENT*>& aComponents, std::vector<RESCUE_CANDIDATE>& aCandidates,
|
|
||||||
const wxString& aSuffix, std::vector<RESCUE_LOG>& 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<RESCUE_CANDIDATE> candidates;
|
|
||||||
std::vector<SCH_COMPONENT*> 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<PART_LIB> rescue_lib( create_rescue_library( library_fn ) );
|
|
||||||
rescue_components( candidates, rescue_lib.get(), part_name_suffix );
|
|
||||||
|
|
||||||
// If no components were rescued, let the user know what's going on. He might
|
|
||||||
// have clicked cancel by mistake, and should have some indication of that.
|
|
||||||
if( candidates.empty() )
|
|
||||||
{
|
|
||||||
wxMessageDialog dlg( this, _( "No cached symbols were rescued." ) );
|
|
||||||
dlg.ShowModal();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
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> rescue_log;
|
|
||||||
update_components( components, candidates, part_name_suffix, rescue_log );
|
|
||||||
|
|
||||||
wxASSERT( !rescue_log.empty() );
|
|
||||||
|
|
||||||
// Try inserting the library into the project
|
|
||||||
if( insert_library( prj, rescue_lib.get(), 0 ) )
|
|
||||||
{
|
|
||||||
// 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." ) );
|
|
||||||
dlg.ShowModal();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,69 +0,0 @@
|
||||||
/*
|
|
||||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2015 Chris Pavlina <pavlina.chris@gmail.com>
|
|
||||||
* 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 <vector>
|
|
||||||
#include <wx/string.h>
|
|
||||||
|
|
||||||
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_
|
|
|
@ -431,8 +431,8 @@ void SCH_EDIT_FRAME::ReCreateMenuBar()
|
||||||
|
|
||||||
AddMenuItem( toolsMenu,
|
AddMenuItem( toolsMenu,
|
||||||
ID_RESCUE_CACHED,
|
ID_RESCUE_CACHED,
|
||||||
_( "&Rescue Cached Components" ),
|
_( "&Rescue Old Components" ),
|
||||||
_( "Find old components in the project cache and rescue them to a new library" ),
|
_( "Find old components in the project and rename/rescue them" ),
|
||||||
KiBitmap( copycomponent_xpm ) );
|
KiBitmap( copycomponent_xpm ) );
|
||||||
|
|
||||||
toolsMenu->AppendSeparator();
|
toolsMenu->AppendSeparator();
|
||||||
|
|
|
@ -0,0 +1,540 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 Chris Pavlina <pavlina.chris@gmail.com>
|
||||||
|
* 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 <class_drawpanel.h>
|
||||||
|
#include <class_library.h>
|
||||||
|
#include <confirm.h>
|
||||||
|
#include <invoke_sch_dialog.h>
|
||||||
|
#include <kicad_device_context.h>
|
||||||
|
#include <project_rescue.h>
|
||||||
|
#include <sch_component.h>
|
||||||
|
#include <sch_sheet.h>
|
||||||
|
#include <schframe.h>
|
||||||
|
#include <wildcards_and_files_ext.h>
|
||||||
|
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
|
||||||
|
typedef std::pair<SCH_COMPONENT*, wxString> 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<PART_LIBS*>( 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<PART_LIB> 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<SCH_COMPONENT*>& 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<SCH_COMPONENT*>( 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RESCUER::RemoveDuplicates()
|
||||||
|
{
|
||||||
|
std::vector<wxString> names_seen;
|
||||||
|
|
||||||
|
for( boost::ptr_vector<RESCUE_CANDIDATE>::iterator it = m_all_candidates.begin();
|
||||||
|
it != m_all_candidates.end(); )
|
||||||
|
{
|
||||||
|
bool seen_already = false;
|
||||||
|
BOOST_FOREACH( wxString& name_seen, names_seen )
|
||||||
|
{
|
||||||
|
if( name_seen == it->GetRequestedName() )
|
||||||
|
{
|
||||||
|
seen_already = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( seen_already )
|
||||||
|
{
|
||||||
|
it = m_all_candidates.erase( it );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
names_seen.push_back( it->GetRequestedName() );
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class RESCUE_CASE_CANDIDATE: public RESCUE_CANDIDATE
|
||||||
|
{
|
||||||
|
wxString m_requested_name;
|
||||||
|
wxString m_new_name;
|
||||||
|
LIB_PART* m_lib_candidate;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Function FindRescues
|
||||||
|
* Grab all possible RESCUE_CASE_CANDIDATES into a vector.
|
||||||
|
* @param aRescuer - the working RESCUER instance.
|
||||||
|
* @param aCandidates - the vector the will hold the candidates.
|
||||||
|
*/
|
||||||
|
static void FindRescues( RESCUER& aRescuer, boost::ptr_vector<RESCUE_CANDIDATE>& aCandidates )
|
||||||
|
{
|
||||||
|
typedef std::map<wxString, RESCUE_CASE_CANDIDATE> candidate_map_t;
|
||||||
|
candidate_map_t candidate_map;
|
||||||
|
|
||||||
|
BOOST_FOREACH( SCH_COMPONENT* each_component, *( aRescuer.GetComponents() ) )
|
||||||
|
{
|
||||||
|
wxString part_name( each_component->GetPartName() );
|
||||||
|
|
||||||
|
LIB_PART* case_sensitive_match = find_component( part_name, aRescuer.GetLibs(), /* aCached */ true );
|
||||||
|
std::vector<LIB_ALIAS*> case_insensitive_matches;
|
||||||
|
aRescuer.GetLibs()->FindLibraryNearEntries( case_insensitive_matches, part_name );
|
||||||
|
|
||||||
|
if( case_sensitive_match || !( case_insensitive_matches.size() ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
RESCUE_CASE_CANDIDATE candidate(
|
||||||
|
part_name, case_insensitive_matches[0]->GetName(),
|
||||||
|
case_insensitive_matches[0]->GetPart() );
|
||||||
|
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( new RESCUE_CASE_CANDIDATE( each_pair.second ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor RESCUE_CANDIDATE
|
||||||
|
* @param aRequestedName - the name the schematic asks for
|
||||||
|
* @param aNewName - the name we want to change it to
|
||||||
|
* @param aLibCandidate - the part that will give us
|
||||||
|
*/
|
||||||
|
RESCUE_CASE_CANDIDATE( const wxString& aRequestedName, const wxString& aNewName,
|
||||||
|
LIB_PART* aLibCandidate )
|
||||||
|
: m_requested_name( aRequestedName ),
|
||||||
|
m_new_name( aNewName ),
|
||||||
|
m_lib_candidate( aLibCandidate ) { }
|
||||||
|
|
||||||
|
RESCUE_CASE_CANDIDATE() {}
|
||||||
|
|
||||||
|
virtual wxString GetRequestedName() const { return m_requested_name; }
|
||||||
|
virtual wxString GetNewName() const { return m_new_name; }
|
||||||
|
virtual LIB_PART* GetLibCandidate() const { return m_lib_candidate; }
|
||||||
|
virtual wxString GetActionDescription() const
|
||||||
|
{
|
||||||
|
wxString action;
|
||||||
|
action.Printf( _( "Rename to %s" ), m_new_name );
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool PerformAction( RESCUER* aRescuer )
|
||||||
|
{
|
||||||
|
BOOST_FOREACH( SCH_COMPONENT* each_component, *aRescuer->GetComponents() )
|
||||||
|
{
|
||||||
|
if( each_component->GetPartName() != m_requested_name ) continue;
|
||||||
|
each_component->SetPartName( m_new_name );
|
||||||
|
aRescuer->LogRescue( each_component, m_requested_name, m_new_name );
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class RESCUE_CACHE_CANDIDATE: public RESCUE_CANDIDATE
|
||||||
|
{
|
||||||
|
wxString m_requested_name;
|
||||||
|
wxString m_new_name;
|
||||||
|
LIB_PART* m_cache_candidate;
|
||||||
|
LIB_PART* m_lib_candidate;
|
||||||
|
|
||||||
|
static std::auto_ptr<PART_LIB> m_rescue_lib;
|
||||||
|
static wxFileName m_library_fn;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Function FindRescues
|
||||||
|
* Grab all possible RESCUE_CACHE_CANDIDATEs into a vector.
|
||||||
|
* @param aRescuer - the working RESCUER instance.
|
||||||
|
* @param aCandidates - the vector the will hold the candidates.
|
||||||
|
*/
|
||||||
|
static void FindRescues( RESCUER& aRescuer, boost::ptr_vector<RESCUE_CANDIDATE>& aCandidates )
|
||||||
|
{
|
||||||
|
typedef std::map<wxString, RESCUE_CACHE_CANDIDATE> candidate_map_t;
|
||||||
|
candidate_map_t candidate_map;
|
||||||
|
|
||||||
|
wxString part_name_suffix = wxT( "-RESCUE-" ) + aRescuer.GetPrj()->GetProjectName();
|
||||||
|
|
||||||
|
BOOST_FOREACH( SCH_COMPONENT* each_component, *( aRescuer.GetComponents() ) )
|
||||||
|
{
|
||||||
|
wxString part_name( each_component->GetPartName() );
|
||||||
|
|
||||||
|
LIB_PART* cache_match = find_component( part_name, aRescuer.GetLibs(), /* aCached */ true );
|
||||||
|
LIB_PART* lib_match = find_component( part_name, aRescuer.GetLibs(), /* aCached */ false );
|
||||||
|
|
||||||
|
// Test whether there is a conflict
|
||||||
|
if( !cache_match || !lib_match )
|
||||||
|
continue;
|
||||||
|
if( !cache_match->PinsConflictWith( *lib_match, /* aTestNums */ true,
|
||||||
|
/* aTestNames */ true, /* aTestType */ true, /* aTestOrientation */ true,
|
||||||
|
/* aTestLength */ false ))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
RESCUE_CACHE_CANDIDATE candidate(
|
||||||
|
part_name, part_name + part_name_suffix,
|
||||||
|
cache_match, 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( new RESCUE_CACHE_CANDIDATE( each_pair.second ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor RESCUE_CACHE_CANDIDATE
|
||||||
|
* @param aRequestedName - the name the schematic asks for
|
||||||
|
* @param aNewName - the name we want to change it to
|
||||||
|
* @param aCacheCandidate - the part from the cache
|
||||||
|
* @param aLibCandidate - the part that would be loaded from the library
|
||||||
|
*/
|
||||||
|
RESCUE_CACHE_CANDIDATE( const wxString& aRequestedName, const wxString& aNewName,
|
||||||
|
LIB_PART* aCacheCandidate, LIB_PART* aLibCandidate )
|
||||||
|
: m_requested_name( aRequestedName ),
|
||||||
|
m_new_name( aNewName ),
|
||||||
|
m_cache_candidate( aCacheCandidate ),
|
||||||
|
m_lib_candidate( aLibCandidate ) { }
|
||||||
|
|
||||||
|
RESCUE_CACHE_CANDIDATE() {}
|
||||||
|
|
||||||
|
virtual wxString GetRequestedName() const { return m_requested_name; }
|
||||||
|
virtual wxString GetNewName() const { return m_new_name; }
|
||||||
|
virtual LIB_PART* GetCacheCandidate() const { return m_cache_candidate; }
|
||||||
|
virtual LIB_PART* GetLibCandidate() const { return m_lib_candidate; }
|
||||||
|
virtual wxString GetActionDescription() const
|
||||||
|
{
|
||||||
|
wxString action;
|
||||||
|
action.Printf( _( "Rescue %s as %s" ), m_requested_name, m_new_name );
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function OpenRescueLibrary
|
||||||
|
* Creates the new rescue library. Must be called before calling any PerformAction()s.
|
||||||
|
*/
|
||||||
|
static void OpenRescueLibrary()
|
||||||
|
{
|
||||||
|
wxFileName fn( g_RootSheet->GetScreen()->GetFileName() );
|
||||||
|
fn.SetName( fn.GetName() + wxT( "-rescue" ) );
|
||||||
|
fn.SetExt( SchematicLibraryFileExtension );
|
||||||
|
m_library_fn.SetPath( fn.GetPath() );
|
||||||
|
m_library_fn.SetName( fn.GetName() );
|
||||||
|
m_library_fn.SetExt( wxT( "lib" ) );
|
||||||
|
|
||||||
|
std::auto_ptr<PART_LIB> rescue_lib( new PART_LIB( LIBRARY_TYPE_EESCHEMA,
|
||||||
|
fn.GetFullPath() ) );
|
||||||
|
|
||||||
|
m_rescue_lib = rescue_lib;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool PerformAction( RESCUER* aRescuer )
|
||||||
|
{
|
||||||
|
LIB_PART new_part( *m_cache_candidate, m_rescue_lib.get() );
|
||||||
|
new_part.SetName( m_new_name );
|
||||||
|
new_part.RemoveAllAliases();
|
||||||
|
RESCUE_CACHE_CANDIDATE::m_rescue_lib.get()->AddPart( &new_part );
|
||||||
|
|
||||||
|
BOOST_FOREACH( SCH_COMPONENT* each_component, *aRescuer->GetComponents() )
|
||||||
|
{
|
||||||
|
if( each_component->GetPartName() != m_requested_name ) continue;
|
||||||
|
each_component->SetPartName( m_new_name );
|
||||||
|
aRescuer->LogRescue( each_component, m_requested_name, m_new_name );
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function WriteRescueLibrary
|
||||||
|
* Writes out the rescue library. Called after successful PerformAction()s. If this fails,
|
||||||
|
* undo the actions.
|
||||||
|
* @return True on success.
|
||||||
|
*/
|
||||||
|
static bool WriteRescueLibrary( SCH_EDIT_FRAME *aEditFrame, PROJECT* aProject )
|
||||||
|
{
|
||||||
|
|
||||||
|
if( !save_library( m_library_fn.GetFullPath(), m_rescue_lib.get(), aEditFrame ) )
|
||||||
|
return false;
|
||||||
|
return insert_library( aProject, m_rescue_lib.get(), 0 );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::auto_ptr<PART_LIB> RESCUE_CACHE_CANDIDATE::m_rescue_lib;
|
||||||
|
wxFileName RESCUE_CACHE_CANDIDATE::m_library_fn;
|
||||||
|
|
||||||
|
RESCUER::RESCUER( SCH_EDIT_FRAME& aEditFrame, PROJECT& aProject )
|
||||||
|
{
|
||||||
|
get_components( m_components );
|
||||||
|
m_prj = &aProject;
|
||||||
|
m_libs = m_prj->SchLibs();
|
||||||
|
m_edit_frame = &aEditFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RESCUER::FindCandidates()
|
||||||
|
{
|
||||||
|
RESCUE_CASE_CANDIDATE::FindRescues( *this, m_all_candidates );
|
||||||
|
RESCUE_CACHE_CANDIDATE::FindRescues( *this, m_all_candidates );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RESCUER::InvokeDialog( bool aAskShowAgain )
|
||||||
|
{
|
||||||
|
InvokeDialogRescueEach( m_edit_frame, *this, aAskShowAgain );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RESCUER::LogRescue( SCH_COMPONENT *aComponent, const wxString &aOldName,
|
||||||
|
const wxString &aNewName )
|
||||||
|
{
|
||||||
|
RESCUE_LOG logitem;
|
||||||
|
logitem.component = aComponent;
|
||||||
|
logitem.old_name = aOldName;
|
||||||
|
logitem.new_name = aNewName;
|
||||||
|
m_rescue_log.push_back( logitem );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool RESCUER::DoRescues()
|
||||||
|
{
|
||||||
|
BOOST_FOREACH( RESCUE_CANDIDATE* each_candidate, m_chosen_candidates )
|
||||||
|
{
|
||||||
|
if( ! each_candidate->PerformAction( this ) )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RESCUER::UndoRescues()
|
||||||
|
{
|
||||||
|
BOOST_FOREACH( RESCUE_LOG& each_logitem, m_rescue_log )
|
||||||
|
{
|
||||||
|
each_logitem.component->SetPartName( each_logitem.old_name );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SCH_EDIT_FRAME::RescueProject( bool aRunningOnDemand )
|
||||||
|
{
|
||||||
|
// Data that will be used throughout the operation
|
||||||
|
std::vector<RESCUE_CANDIDATE> candidates;
|
||||||
|
wxString part_name_suffix;
|
||||||
|
|
||||||
|
RESCUER rescuer( *this, Prj() );
|
||||||
|
|
||||||
|
rescuer.FindCandidates();
|
||||||
|
|
||||||
|
if( ! rescuer.GetCandidateCount() )
|
||||||
|
{
|
||||||
|
if( aRunningOnDemand )
|
||||||
|
{
|
||||||
|
wxMessageDialog dlg( this, _( "This project has nothing to rescue." ) );
|
||||||
|
dlg.ShowModal();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
rescuer.RemoveDuplicates();
|
||||||
|
|
||||||
|
rescuer.InvokeDialog( !aRunningOnDemand );
|
||||||
|
|
||||||
|
// If no components were rescued, let the user know what's going on. He might
|
||||||
|
// have clicked cancel by mistake, and should have some indication of that.
|
||||||
|
if( !rescuer.GetChosenCandidateCount() )
|
||||||
|
{
|
||||||
|
wxMessageDialog dlg( this, _( "No symbols were rescued." ) );
|
||||||
|
dlg.ShowModal();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
RESCUE_CACHE_CANDIDATE::OpenRescueLibrary();
|
||||||
|
|
||||||
|
if( !rescuer.DoRescues() )
|
||||||
|
{
|
||||||
|
rescuer.UndoRescues();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
RESCUE_CACHE_CANDIDATE::WriteRescueLibrary( this, &Prj() );
|
||||||
|
|
||||||
|
Prj().SetElem( PROJECT::ELEM_SCH_PART_LIBS, NULL );
|
||||||
|
|
||||||
|
// Clean up wire ends
|
||||||
|
INSTALL_UNBUFFERED_DC( dc, m_canvas );
|
||||||
|
GetScreen()->SchematicCleanUp( NULL, &dc );
|
||||||
|
m_canvas->Refresh( true );
|
||||||
|
OnModify();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,190 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 Chris Pavlina <pavlina.chris@gmail.com>
|
||||||
|
* 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 was made before
|
||||||
|
* various changes were made, either to KiCad or to the libraries, and
|
||||||
|
* the project needs to be recovered. The function of note is a member
|
||||||
|
* of SCH_EDIT_FRAME, defined thus:
|
||||||
|
*
|
||||||
|
* bool SCH_EDIT_FRAME::RescueProject( bool aSilentIfNone );
|
||||||
|
*
|
||||||
|
* When this is called, a list of problematic components is compiled. If
|
||||||
|
* this list is empty, then the function displays a notification and returns
|
||||||
|
* (if aSilentIfNone is true, the notification is silenced).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <schframe.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <wx/string.h>
|
||||||
|
#include <boost/ptr_container/ptr_vector.hpp>
|
||||||
|
|
||||||
|
class LIB_PART;
|
||||||
|
class SCH_COMPONENT;
|
||||||
|
class RESCUER;
|
||||||
|
|
||||||
|
enum RESCUE_TYPE
|
||||||
|
{
|
||||||
|
RESCUE_CONFLICT,
|
||||||
|
RESCUE_CASE,
|
||||||
|
};
|
||||||
|
|
||||||
|
class RESCUE_CANDIDATE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Function GetRequestedName
|
||||||
|
* Get the name that was originally requested in the schematic
|
||||||
|
*/
|
||||||
|
virtual wxString GetRequestedName() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetNewName
|
||||||
|
* Get the name we're proposing changing it to
|
||||||
|
*/
|
||||||
|
virtual wxString GetNewName() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetCacheCandidate
|
||||||
|
* Get the part that can be loaded from the project cache, if possible, or
|
||||||
|
* else NULL.
|
||||||
|
*/
|
||||||
|
virtual LIB_PART* GetCacheCandidate() const { return NULL; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetLibCandidate
|
||||||
|
* Get the part the would be loaded from the libraries, if possible, or else
|
||||||
|
* NULL.
|
||||||
|
*/
|
||||||
|
virtual LIB_PART* GetLibCandidate() const { return NULL; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetActionDescription
|
||||||
|
* Get a description of the action proposed, for displaying in the UI.
|
||||||
|
*/
|
||||||
|
virtual wxString GetActionDescription() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function PerformAction
|
||||||
|
* Perform the actual rescue action. If successful, this must log the rescue using
|
||||||
|
* RESCUER::LogRescue to allow it to be reversed.
|
||||||
|
* @return True on success.
|
||||||
|
*/
|
||||||
|
virtual bool PerformAction( RESCUER* aRescuer ) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RESCUE_LOG
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SCH_COMPONENT* component;
|
||||||
|
wxString old_name;
|
||||||
|
wxString new_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RESCUER
|
||||||
|
{
|
||||||
|
friend class DIALOG_RESCUE_EACH;
|
||||||
|
|
||||||
|
std::vector<SCH_COMPONENT*> m_components;
|
||||||
|
PART_LIBS* m_libs;
|
||||||
|
PROJECT* m_prj;
|
||||||
|
SCH_EDIT_FRAME* m_edit_frame;
|
||||||
|
|
||||||
|
boost::ptr_vector<RESCUE_CANDIDATE> m_all_candidates;
|
||||||
|
std::vector<RESCUE_CANDIDATE*> m_chosen_candidates;
|
||||||
|
|
||||||
|
std::vector<RESCUE_LOG> m_rescue_log;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RESCUER( SCH_EDIT_FRAME& aEditFrame, PROJECT& aProject );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function FindCandidates
|
||||||
|
* Populate the RESCUER with all possible candidates.
|
||||||
|
*/
|
||||||
|
void FindCandidates();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function RemoveDuplicates
|
||||||
|
* Filter out duplicately named rescue candidates.
|
||||||
|
*/
|
||||||
|
void RemoveDuplicates();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetCandidateCount
|
||||||
|
*/
|
||||||
|
size_t GetCandidateCount() { return m_all_candidates.size(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetChosenCandidateCount
|
||||||
|
*/
|
||||||
|
size_t GetChosenCandidateCount() { return m_chosen_candidates.size(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetComponents
|
||||||
|
*/
|
||||||
|
std::vector<SCH_COMPONENT*>* GetComponents() { return &m_components; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetLibs
|
||||||
|
*/
|
||||||
|
PART_LIBS* GetLibs() { return m_libs; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetPrj
|
||||||
|
*/
|
||||||
|
PROJECT* GetPrj() { return m_prj; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function InvokeDialog
|
||||||
|
* Display a dialog to allow the user to select rescues.
|
||||||
|
* @param aAskShowAgain - whether the "Never Show Again" button should be visible
|
||||||
|
*/
|
||||||
|
void InvokeDialog( bool aAskShowAgain );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function LogRescue
|
||||||
|
* Used by individual RESCUE_CANDIDATEs to log a rescue for undoing.
|
||||||
|
*/
|
||||||
|
void LogRescue( SCH_COMPONENT *aComponent, const wxString& aOldName,
|
||||||
|
const wxString& aNewName );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function DoRescues
|
||||||
|
* Perform all chosen rescue actions, logging them to be undone if necessary.
|
||||||
|
* @return True on success
|
||||||
|
*/
|
||||||
|
bool DoRescues();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function UndoRescues
|
||||||
|
* Reverse the effects of all rescues on the project.
|
||||||
|
*/
|
||||||
|
void UndoRescues();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _LIB_CACHE_RESCUE_H_
|
|
@ -243,7 +243,7 @@ BEGIN_EVENT_TABLE( SCH_EDIT_FRAME, EDA_DRAW_FRAME )
|
||||||
EVT_TOOL( ID_RUN_LIBRARY, SCH_EDIT_FRAME::OnOpenLibraryEditor )
|
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_POPUP_SCH_CALL_LIBEDIT_AND_LOAD_CMP, SCH_EDIT_FRAME::OnOpenLibraryEditor )
|
||||||
EVT_TOOL( ID_TO_LIBVIEW, SCH_EDIT_FRAME::OnOpenLibraryViewer )
|
EVT_TOOL( ID_TO_LIBVIEW, SCH_EDIT_FRAME::OnOpenLibraryViewer )
|
||||||
EVT_TOOL( ID_RESCUE_CACHED, SCH_EDIT_FRAME::OnRescueCached )
|
EVT_TOOL( ID_RESCUE_CACHED, SCH_EDIT_FRAME::OnRescueProject )
|
||||||
|
|
||||||
EVT_TOOL( ID_RUN_PCB, SCH_EDIT_FRAME::OnOpenPcbnew )
|
EVT_TOOL( ID_RUN_PCB, SCH_EDIT_FRAME::OnOpenPcbnew )
|
||||||
EVT_TOOL( ID_RUN_PCB_MODULE_EDITOR, SCH_EDIT_FRAME::OnOpenPcbModuleEditor )
|
EVT_TOOL( ID_RUN_PCB_MODULE_EDITOR, SCH_EDIT_FRAME::OnOpenPcbModuleEditor )
|
||||||
|
@ -1120,9 +1120,9 @@ void SCH_EDIT_FRAME::OnOpenLibraryEditor( wxCommandEvent& event )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SCH_EDIT_FRAME::OnRescueCached( wxCommandEvent& event )
|
void SCH_EDIT_FRAME::OnRescueProject( wxCommandEvent& event )
|
||||||
{
|
{
|
||||||
RescueCacheConflicts( true );
|
RescueProject( true );
|
||||||
}
|
}
|
||||||
|
|
||||||
void SCH_EDIT_FRAME::OnExit( wxCommandEvent& event )
|
void SCH_EDIT_FRAME::OnExit( wxCommandEvent& event )
|
||||||
|
|
|
@ -832,7 +832,7 @@ private:
|
||||||
void OnOpenPcbModuleEditor( wxCommandEvent& event );
|
void OnOpenPcbModuleEditor( wxCommandEvent& event );
|
||||||
void OnOpenCvpcb( wxCommandEvent& event );
|
void OnOpenCvpcb( wxCommandEvent& event );
|
||||||
void OnOpenLibraryEditor( wxCommandEvent& event );
|
void OnOpenLibraryEditor( wxCommandEvent& event );
|
||||||
void OnRescueCached( wxCommandEvent& event );
|
void OnRescueProject( wxCommandEvent& event );
|
||||||
void OnPreferencesOptions( wxCommandEvent& event );
|
void OnPreferencesOptions( wxCommandEvent& event );
|
||||||
void OnCancelCurrentCommand( wxCommandEvent& aEvent );
|
void OnCancelCurrentCommand( wxCommandEvent& aEvent );
|
||||||
|
|
||||||
|
@ -1307,10 +1307,13 @@ public:
|
||||||
bool CreateArchiveLibrary( const wxString& aFileName );
|
bool CreateArchiveLibrary( const wxString& aFileName );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function RescueCacheConflicts
|
* Function RescueProject
|
||||||
* exports components from the '-cache' library that conflict with parts
|
* performs rescue operations to recover old projects from before certain
|
||||||
* in the project libraries to a new library, renaming them to add a suffix
|
* changes were made.
|
||||||
* of the root document's name to avoid conflicts.
|
*
|
||||||
|
* - Exports cached symbols that conflict with new symbols to a separate
|
||||||
|
* library
|
||||||
|
* - Renames symbols named before libraries were case sensitive
|
||||||
*
|
*
|
||||||
* @param aRunningOnDemand - indicates whether the tool has been called up by the user
|
* @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
|
* (as opposed to being run automatically). If true, an information dialog is
|
||||||
|
@ -1318,7 +1321,7 @@ public:
|
||||||
* if there are no components to rescue, and a "Never Show Again" button is
|
* if there are no components to rescue, and a "Never Show Again" button is
|
||||||
* displayed.
|
* displayed.
|
||||||
*/
|
*/
|
||||||
bool RescueCacheConflicts( bool aRunningOnDemand );
|
bool RescueProject( bool aRunningOnDemand );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function PrintPage
|
* Function PrintPage
|
||||||
|
|
Loading…
Reference in New Issue