KiCad PCB EDA Suite
dialog_symbol_remap.cpp
Go to the documentation of this file.
1 
5 /*
6  * This program source code file is part of KiCad, a free EDA CAD application.
7  *
8  * Copyright (C) 2017 Wayne Stambaugh <stambaughw@verizon.net>
9  * Copyright (C) 2017 KiCad Developers, see AUTHORS.txt for contributors.
10  *
11  * This program is free software: you can redistribute it and/or modify it
12  * under the terms of the GNU General Public License as published by the
13  * Free Software Foundation, either version 3 of the License, or (at your
14  * option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful, but
17  * WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License along
22  * with this program. If not, see <http://www.gnu.org/licenses/>.
23  */
24 
25 #include <macros.h>
26 #include <pgm_base.h>
27 #include <kiface_i.h>
28 #include <project.h>
29 #include <confirm.h>
30 #include <reporter.h>
32 #include <wx_html_report_panel.h>
33 
34 #include <class_library.h>
35 #include <sch_io_mgr.h>
36 #include <sch_sheet.h>
37 #include <sch_component.h>
38 #include <class_sch_screen.h>
39 #include <schframe.h>
40 #include <symbol_lib_table.h>
41 #include <env_paths.h>
42 
43 #include <dialog_symbol_remap.h>
44 
45 
47  DIALOG_SYMBOL_REMAP_BASE( aParent )
48 {
49  wxString text;
50 
51  text = _( "This schematic currently uses the symbol library list look up method for "
52  "loading schematic symbols. KiCad will attempt to map the existing symbols "
53  "to use the new symbol library table. Remapping will change project files "
54  "and schematics will not be compatible with previous versions of KiCad. "
55  "All files that are changed will be backed up with the .v4 extension should "
56  "you need to revert any changes. If you choose to skip this step, you will "
57  "be responsible for manually remapping the symbols." );
58 
59  m_htmlCtrl->AppendToPage( text );
60 }
61 
62 
63 void DIALOG_SYMBOL_REMAP::OnRemapSymbols( wxCommandEvent& aEvent )
64 {
65  wxBusyCursor busy;
66 
67  backupProject();
68 
69  // The schematic is fully loaded, any legacy library symbols have been rescued. Now
70  // check to see if the schematic has not been converted to the symbol library table
71  // method for looking up symbols.
72  wxFileName prjSymLibTableFileName( Prj().GetProjectPath(),
74 
75  if( !prjSymLibTableFileName.FileExists() )
76  {
79  Prj().SchSymbolLibTable();
80  }
81 
83 
84  // Remove all of the libraries from the legacy library list.
85  wxString paths;
86  wxArrayString libNames;
87 
88  PART_LIBS::LibNamesAndPaths( &Prj(), true, &paths, &libNames );
89 
90  // Reload the the cache symbol library.
92  Prj().SchLibs();
93 }
94 
95 
96 size_t DIALOG_SYMBOL_REMAP::getLibsNotInGlobalSymbolLibTable( std::vector< PART_LIB* >& aLibs )
97 {
98  PART_LIBS* libs = Prj().SchLibs();
99 
100  for( PART_LIBS_BASE::iterator it = libs->begin(); it != libs->end(); ++it )
101  {
102  // Ignore the cache library.
103  if( it->IsCache() )
104  continue;
105 
106  // Check for the obvious library name.
107  wxString libFileName = it->GetFullFileName();
108 
109  if( !SYMBOL_LIB_TABLE::GetGlobalLibTable().FindRowByURI( libFileName ) )
110  aLibs.push_back( &(*it) );
111  }
112 
113  return aLibs.size();
114 }
115 
116 
118 {
119  wxString msg;
120  std::vector< PART_LIB* > libs;
121 
123  {
124  SYMBOL_LIB_TABLE prjLibTable;
125  std::vector< wxString > libNames = SYMBOL_LIB_TABLE::GetGlobalLibTable().GetLogicalLibs();
126 
127  for( auto lib : libs )
128  {
129  wxString libName = lib->GetName();
130  int libNameInc = 1;
131  int libNameLen = libName.Length();
132 
133  // Don't create duplicate table entries.
134  while( std::find( libNames.begin(), libNames.end(), libName ) != libNames.end() )
135  {
136  libName = libName.Left( libNameLen );
137  libName << libNameInc;
138  libNameInc++;
139  }
140 
141  wxString pluginType = SCH_IO_MGR::ShowType( SCH_IO_MGR::SCH_LEGACY );
142  wxFileName fn = lib->GetFullFileName();
143 
144  // Use environment variable substitution where possible. This is based solely
145  // on the internal user environment variable list. Checking against all of the
146  // system wide environment variables is probably not a good idea.
147  wxString fullFileName = NormalizePath( fn, &Pgm().GetLocalEnvVariables(), &Prj() );
148 
149  // Fall back to the absolute library path.
150  if( fullFileName.IsEmpty() )
151  fullFileName = lib->GetFullFileName();
152 
153  wxFileName tmpFn = fullFileName;
154 
155  // Don't add symbol libraries that do not exist.
156  if( tmpFn.Normalize() && tmpFn.FileExists() )
157  {
158  msg.Printf( _( "Adding library '%s', file '%s' to project symbol library table." ),
159  libName, fullFileName );
160  aReporter.Report( msg, REPORTER::RPT_INFO );
161 
162  prjLibTable.InsertRow( new SYMBOL_LIB_TABLE_ROW( libName, fullFileName,
163  pluginType ) );
164  }
165  else
166  {
167  msg.Printf( _( "Library '%s' not found." ), fullFileName );
168  aReporter.Report( msg, REPORTER::RPT_WARNING );
169  }
170  }
171 
172  // Don't save empty project symbol library table.
173  if( !prjLibTable.IsEmpty() )
174  {
175  wxFileName fn( Prj().GetProjectPath(), SYMBOL_LIB_TABLE::GetSymbolLibTableFileName() );
176 
177  try
178  {
179  FILE_OUTPUTFORMATTER formatter( fn.GetFullPath() );
180  prjLibTable.Format( &formatter, 0 );
181  }
182  catch( const IO_ERROR& ioe )
183  {
184  msg.Printf( _( "Failed to write project symbol library table. Error:\n %s" ),
185  ioe.What() );
186  aReporter.Report( msg, REPORTER::RPT_ERROR );
187  }
188 
189  aReporter.Report( _( "Created project symbol library table.\n" ), REPORTER::RPT_INFO );
190  }
191  }
192 }
193 
194 
196 {
197  wxString msg;
198  SCH_SCREENS schematic;
199  SCH_COMPONENT* symbol;
200  SCH_ITEM* item;
201  SCH_ITEM* nextItem;
202  SCH_SCREEN* screen;
203 
204  for( screen = schematic.GetFirst(); screen; screen = schematic.GetNext() )
205  {
206  for( item = screen->GetDrawItems(); item; item = nextItem )
207  {
208  nextItem = item->Next();
209 
210  if( item->Type() != SCH_COMPONENT_T )
211  continue;
212 
213  symbol = dynamic_cast< SCH_COMPONENT* >( item );
214 
215  if( !remapSymbolToLibTable( symbol ) )
216  {
217  msg.Printf( _( "No symbol '%s' found in symbol library table." ),
218  symbol->GetLibId().GetLibItemName().wx_str() );
219  aReporter.Report( msg, REPORTER::RPT_WARNING );
220  }
221  else
222  {
223  msg.Printf( _( "Symbol '%s' mapped to symbol library '%s'." ),
224  symbol->GetLibId().GetLibItemName().wx_str(),
225  symbol->GetLibId().GetLibNickname().wx_str() );
226  aReporter.Report( msg, REPORTER::RPT_ACTION );
227  screen->SetModify();
228  }
229  }
230  }
231 
232  aReporter.Report( _( "Symbol library table mapping complete!" ), REPORTER::RPT_INFO );
233  schematic.UpdateSymbolLinks( true );
234 }
235 
236 
238 {
239  wxCHECK_MSG( aSymbol != NULL, false, "Null pointer passed to remapSymbolToLibTable." );
240  wxCHECK_MSG( aSymbol->GetLibId().GetLibNickname().empty(), false,
241  "Cannot remap symbol that is already mapped." );
242  wxCHECK_MSG( !aSymbol->GetLibId().GetLibItemName().empty(), false,
243  "The symbol LIB_ID name is empty." );
244 
245  PART_LIBS* libs = Prj().SchLibs();
246 
247  for( PART_LIBS_BASE::iterator it = libs->begin(); it != libs->end(); ++it )
248  {
249  // Ignore the cache library.
250  if( it->IsCache() )
251  continue;
252 
253  LIB_ALIAS* alias = it->FindAlias( aSymbol->GetLibId().GetLibItemName().wx_str() );
254 
255  // Found in the same library as the old look up method assuming the user didn't
256  // change the libraries or library ordering since the last time the schematic was
257  // loaded.
258  if( alias )
259  {
260  // Find the same library in the symbol library table using the full path and file name.
261  wxString libFileName = it->GetFullFileName();
262 
263  const LIB_TABLE_ROW* row = Prj().SchSymbolLibTable()->FindRowByURI( libFileName );
264 
265  if( row )
266  {
267  LIB_ID id = aSymbol->GetLibId();
268 
269  id.SetLibNickname( row->GetNickName() );
270 
271  // Don't resolve symbol library links now.
272  aSymbol->SetLibId( id, nullptr, nullptr );
273  return true;
274  }
275  }
276  }
277 
278  return false;
279 }
280 
281 
283 {
284  static wxString ext = "v4";
285 
286  wxString errorMsg;
287  wxFileName destFileName;
288  SCH_SCREENS schematic;
289 
290  // Back up the schematic files.
291  for( SCH_SCREEN* screen = schematic.GetFirst(); screen; screen = schematic.GetNext() )
292  {
293  destFileName = screen->GetFileName();
294  destFileName.SetName( destFileName.GetFullName() );
295  destFileName.SetExt( ext );
296 
297  wxLogTrace( "KICAD_TRACE_PATHS", "Backing up file '%s' to file '%s'.",
298  screen->GetFileName(), destFileName.GetFullPath() );
299 
300  if( wxFileName::Exists( screen->GetFileName() )
301  && !wxCopyFile( screen->GetFileName(), destFileName.GetFullPath() ) )
302  {
303  errorMsg += wxPrintf( _( "Failed to back up file '%s'.\n" ), screen->GetFileName() );
304  }
305  }
306 
307  // Back up the project file.
308  destFileName = Prj().GetProjectFullName();
309  destFileName.SetName( destFileName.GetFullName() );
310  destFileName.SetExt( ext );
311 
312  wxLogTrace( "KICAD_TRACE_PATHS", "Backing up file '%s' to file '%s'.",
313  Prj().GetProjectFullName(), destFileName.GetFullPath() );
314 
315  if( wxFileName::Exists( Prj().GetProjectFullName() )
316  && !wxCopyFile( Prj().GetProjectFullName(), destFileName.GetFullPath() ) )
317  {
318  errorMsg += wxPrintf( _( "Failed to back up file '%s'.\n" ), Prj().GetProjectFullName() );
319  }
320 
321  wxFileName srcFileName;
322 
323  // Back up the cache library.
324  srcFileName.SetPath( Prj().GetProjectPath() );
325  srcFileName.SetName( Prj().GetProjectName() + "-cache" );
326  srcFileName.SetExt( SchematicLibraryFileExtension );
327 
328  destFileName = srcFileName;
329  destFileName.SetName( destFileName.GetFullName() );
330  destFileName.SetExt( ext );
331 
332  wxLogTrace( "KICAD_TRACE_PATHS", "Backing up file '%s' to file '%s'.",
333  srcFileName.GetFullPath(), destFileName.GetFullPath() );
334 
335  if( srcFileName.Exists()
336  && !wxCopyFile( srcFileName.GetFullPath(), destFileName.GetFullPath() ) )
337  {
338  errorMsg += wxPrintf( _( "Failed to back up file '%s'.\n" ), srcFileName.GetFullPath() );
339  }
340 
341  // Back up the rescue library if it exists.
342  srcFileName.SetName( Prj().GetProjectName() + "-rescue" );
343  destFileName.SetName( srcFileName.GetFullName() );
344 
345  wxLogTrace( "KICAD_TRACE_PATHS", "Backing up file '%s' to file '%s'.",
346  srcFileName.GetFullPath(), destFileName.GetFullPath() );
347 
348  if( srcFileName.Exists()
349  && !wxCopyFile( srcFileName.GetFullPath(), destFileName.GetFullPath() ) )
350  {
351  errorMsg += wxPrintf( _( "Failed to back up file '%s'.\n" ), srcFileName.GetFullPath() );
352  }
353 
354  // Back up the rescue library document file if it exists.
355  srcFileName.SetName( Prj().GetProjectName() + "-rescue" );
356  srcFileName.SetExt( "dcm" );
357  destFileName.SetName( srcFileName.GetFullName() );
358 
359  wxLogTrace( "KICAD_TRACE_PATHS", "Backing up file '%s' to file '%s'.",
360  srcFileName.GetFullPath(), destFileName.GetFullPath() );
361 
362  if( srcFileName.Exists()
363  && !wxCopyFile( srcFileName.GetFullPath(), destFileName.GetFullPath() ) )
364  {
365  errorMsg += wxPrintf( _( "Failed to back up file '%s'.\n" ), srcFileName.GetFullPath() );
366  }
367 
368  if( !errorMsg.IsEmpty() )
369  {
370  errorMsg.Trim();
371  DisplayErrorMessage( this, _( "Some of the project files could not be backed up." ),
372  errorMsg );
373  }
374 }
375 
Definition of the SCH_SHEET class for Eeschema.
KICAD_T Type() const
Function Type()
Definition: base_struct.h:225
static const wxString & GetSymbolLibTableFileName()
static SYMBOL_LIB_TABLE & GetGlobalLibTable()
Part library alias object definition.
SCH_SCREEN * GetNext()
Hold a record identifying a symbol library accessed by the appropriate symbol library SCH_PLUGIN obje...
static void LibNamesAndPaths(PROJECT *aProject, bool doSave, wxString *aPaths, wxArrayString *aNames=NULL)
Save or load the names of the currently configured part libraries (without paths).
Hold a record identifying a library accessed by the appropriate plug in object in the LIB_TABLE...
bool InsertRow(LIB_TABLE_ROW *aRow, bool doReplace=false)
Adds aRow if it does not already exist or if doReplace is true.
This file is part of the common library.
size_t getLibsNotInGlobalSymbolLibTable(std::vector< PART_LIB * > &aLibs)
Add libraries found in the legacy library list to aLibs that are not found in the global symbol libra...
static const wxString ShowType(SCH_FILE_T aFileType)
Return a brief name for a plugin, given aFileType enum.
Definition: sch_io_mgr.cpp:76
VTBL_ENTRY const wxString GetProjectFullName() const
Function GetProjectFullName returns the full path and name of the project.
Definition: project.cpp:96
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: kicad.cpp:65
Schematic editor (Eeschema) main window.
Definition: schframe.h:118
Class REPORTER is a pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:61
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
SCH_ITEM * Next() const
This file contains miscellaneous commonly used macros and functions.
VTBL_ENTRY void SetElem(ELEM_T aIndex, _ELEM *aElem)
Definition: project.cpp:219
PROJECT & Prj() const
Function Prj returns a reference to the PROJECT "associated with" this KIWAY.
Class DIALOG_SYMBOL_REMAP_BASE.
void SetLibId(const LIB_ID &aName, PART_LIBS *aLibs=NULL)
void OnRemapSymbols(wxCommandEvent &aEvent) override
wxString wx_str() const
Definition: utf8.cpp:48
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString aExtraInfo)
Function DisplayErrorMessage displays an error message with aMessage.
Definition: confirm.cpp:87
void createProjectSymbolLibTable(REPORTER &aReporter)
bool empty() const
Definition: utf8.h:108
Definitions for the Eeschema program SCH_SCREEN class.
const UTF8 & GetLibItemName() const
Definition: lib_id.h:115
REPORTER & Reporter()
returns the reporter object that reports to this panel
void remapSymbolsToLibTable(REPORTER &aReporter)
The common library.
void backupProject()
Backup all of the files that could be modified by the remapping with a .v4 file extension in case som...
DIALOG_SYMBOL_REMAP(SCH_EDIT_FRAME *aParent)
virtual void Format(OUTPUTFORMATTER *aOutput, int aIndentLevel) const override
Generate the table in s-expression format to aOutput with an indention level of aIndentLevel.
WX_HTML_REPORT_PANEL * m_messagePanel
int SetLibNickname(const UTF8 &aNickname)
Override the logical library name portion of the LIB_ID to aNickname.
Definition: lib_id.cpp:219
A collection of PART_LIB objects.
SCH_ITEM * GetDrawItems() const
bool remapSymbolToLibTable(SCH_COMPONENT *aSymbol)
Definition the SCH_COMPONENT class for Eeschema.
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:33
const wxString & GetNickName() const
see class PGM_BASE
void UpdateSymbolLinks(bool aForce=false)
Initialize or reinitialize the weak reference to the LIB_PART for each SCH_COMPONENT found in the ful...
wxString NormalizePath(const wxFileName &aFilePath, const ENV_VAR_MAP *aEnvVars, const PROJECT *aProject)
Helper functions to substitute paths with environmental variables.
Definition: env_paths.cpp:68
Class SCH_COMPONENT describes a real schematic component.
Definition: sch_component.h:69
const LIB_ID & GetLibId() const
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_UNDEFINED)=0
Function Report is a pure virtual function to override in the derived object.
Class FILE_OUTPUTFORMATTER may be used for text file output.
Definition: richio.h:492
SCH_SCREEN * GetFirst()
Definition for part library class.
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:98
const wxString SchematicLibraryFileExtension
Struct IO_ERROR is a class used to hold an error message and may be used when throwing exceptions con...
Definition: ki_exception.h:47
Class SCH_ITEM is a base class for any item which can be embedded within the SCHEMATIC container clas...
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
bool IsEmpty(bool aIncludeFallback=true)
Return true if the table is empty.
std::vector< wxString > GetLogicalLibs()
Return the logical library names, all of them that are pertinent to a look up done on this LIB_TABLE...