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>
31 #include <wx_html_report_panel.h>
32 
33 #include <class_library.h>
34 #include <sch_io_mgr.h>
35 #include <sch_sheet.h>
36 #include <sch_component.h>
37 #include <class_sch_screen.h>
38 #include <symbol_lib_table.h>
39 
40 #include <dialog_symbol_remap.h>
41 
42 
44  DIALOG_SYMBOL_REMAP_BASE( aParent )
45 {
46 }
47 
48 
49 void DIALOG_SYMBOL_REMAP::OnRemapSymbols( wxCommandEvent& aEvent )
50 {
51  // The schematic is fully loaded, any legacy library symbols have been rescued. Now
52  // check to see if the schematic has not been converted to the symbol library table
53  // method for looking up symbols.
54  wxFileName prjSymLibTableFileName( Prj().GetProjectPath(),
56 
57  if( !prjSymLibTableFileName.FileExists() )
58  {
61  Prj().SchSymbolLibTable();
62  }
63 
65 }
66 
67 
68 size_t DIALOG_SYMBOL_REMAP::getLibsNotInGlobalSymbolLibTable( std::vector< PART_LIB* >& aLibs )
69 {
70  PART_LIBS* libs = Prj().SchLibs();
71 
72  for( PART_LIBS_BASE::iterator it = libs->begin(); it != libs->end(); ++it )
73  {
74  // Ignore the cache library.
75  if( it->IsCache() )
76  continue;
77 
78  // Check for the obvious library name.
79  wxString libFileName = it->GetFullFileName();
80 
81  if( !SYMBOL_LIB_TABLE::GetGlobalLibTable().FindRowByURI( libFileName ) )
82  aLibs.push_back( &(*it) );
83  }
84 
85  return aLibs.size();
86 }
87 
88 
90 {
91  wxString msg;
92  std::vector< PART_LIB* > libs;
93 
95  {
96  SYMBOL_LIB_TABLE prjLibTable;
97  std::vector< wxString > libNames = SYMBOL_LIB_TABLE::GetGlobalLibTable().GetLogicalLibs();
98 
99  for( auto lib : libs )
100  {
101  wxString libName = lib->GetName();
102  int libNameInc = 1;
103  int libNameLen = libName.Length();
104 
105  // Don't create duplicate table entries.
106  while( std::find( libNames.begin(), libNames.end(), libName ) != libNames.end() )
107  {
108  libName = libName.Left( libNameLen );
109  libName << libNameInc;
110  libNameInc++;
111  }
112 
113  wxString tmp;
114  wxString fullFileName;
115  wxString pluginType = SCH_IO_MGR::ShowType( SCH_IO_MGR::SCH_LEGACY );
116  wxFileName fn = lib->GetFullFileName();
117 
118  // Use environment variable substitution where possible. This is based solely
119  // on the internal user environment variable list. Checking against all of the
120  // system wide environment variables is probably not a good idea.
121  const ENV_VAR_MAP& envMap = Pgm().GetLocalEnvVariables();
122  wxFileName envPath;
123 
124  for( auto& entry : envMap )
125  {
126  envPath.SetPath( entry.second.GetValue() );
127 
128  if( normalizeAbsolutePaths( envPath, fn, &tmp ) )
129  {
130  fullFileName = "${" + entry.first + "}/";
131 
132  if( !tmp.IsEmpty() )
133  fullFileName += tmp;
134 
135  fullFileName += fn.GetFullName();
136  break;
137  }
138  }
139 
140  // Check the project path if no local environment variable paths where found.
141  if( fullFileName.IsEmpty() )
142  {
143  envPath.SetPath( Prj().GetProjectPath() );
144 
145  if( normalizeAbsolutePaths( envPath, fn, &tmp ) )
146  {
147  fullFileName = wxString( "${" ) + PROJECT_VAR_NAME + wxString( "}/" );
148 
149  if( !tmp.IsEmpty() )
150  fullFileName += tmp;
151 
152  fullFileName += fn.GetFullName();
153  break;
154  }
155  }
156 
157  // Fall back to the absolute library path.
158  if( fullFileName.IsEmpty() )
159  fullFileName = lib->GetFullFileName();
160 
161  msg.Printf( _( "Adding library '%s', file '%s' to project symbol library table." ),
162  libName, fullFileName );
163  aReporter.Report( msg, REPORTER::RPT_INFO );
164 
165  prjLibTable.InsertRow( new SYMBOL_LIB_TABLE_ROW( libName, fullFileName, pluginType ) );
166  }
167 
168  wxFileName fn( Prj().GetProjectPath(), SYMBOL_LIB_TABLE::GetSymbolLibTableFileName() );
169 
170  try
171  {
172  FILE_OUTPUTFORMATTER formatter( fn.GetFullPath() );
173  prjLibTable.Format( &formatter, 0 );
174  }
175  catch( const IO_ERROR& ioe )
176  {
177  msg.Printf( _( "Failed to write project symbol library table. Error:\n %s" ),
178  ioe.What() );
179  aReporter.Report( msg, REPORTER::RPT_ERROR );
180  }
181  }
182 }
183 
184 
186 {
187  wxString msg;
188  SCH_SCREENS schematic;
189  SCH_COMPONENT* symbol;
190  SCH_ITEM* item;
191  SCH_ITEM* nextItem;
192  SCH_SCREEN* screen;
193 
194  for( screen = schematic.GetFirst(); screen; screen = schematic.GetNext() )
195  {
196  for( item = screen->GetDrawItems(); item; item = nextItem )
197  {
198  nextItem = item->Next();
199 
200  if( item->Type() != SCH_COMPONENT_T )
201  continue;
202 
203  symbol = dynamic_cast< SCH_COMPONENT* >( item );
204 
205  if( !remapSymbolToLibTable( symbol ) )
206  {
207  msg.Printf( _( "No symbol '%s' founded in symbol library table." ),
208  FROM_UTF8( symbol->GetLibId().GetLibItemName() ) );
209  aReporter.Report( msg, REPORTER::RPT_WARNING );
210  }
211  else
212  {
213  msg.Printf( _( "Symbol '%s' mapped to symbol library '%s'." ),
214  FROM_UTF8( symbol->GetLibId().GetLibItemName() ),
215  FROM_UTF8( symbol->GetLibId().GetLibNickname() ) );
216  aReporter.Report( msg, REPORTER::RPT_ACTION );
217  }
218  }
219  }
220 }
221 
222 
224 {
225  wxCHECK_MSG( aSymbol != NULL, false, "Null pointer passed to remapSymbolToLibTable." );
226  wxCHECK_MSG( aSymbol->GetLibId().GetLibNickname().empty(), false,
227  "Cannot remap symbol that is already mapped." );
228  wxCHECK_MSG( !aSymbol->GetLibId().GetLibItemName().empty(), false,
229  "The symbol LIB_ID name is empty." );
230 
231  PART_LIBS* libs = Prj().SchLibs();
232 
233  for( PART_LIBS_BASE::iterator it = libs->begin(); it != libs->end(); ++it )
234  {
235  // Ignore the cache library.
236  if( it->IsCache() )
237  continue;
238 
239  LIB_ALIAS* alias = it->FindAlias( aSymbol->GetLibId().GetLibItemName() );
240 
241  // Found in the same library as the old look up method assuming the user didn't
242  // change the libraries or library ordering since the last time the schematic was
243  // loaded.
244  if( alias )
245  {
246  // Find the same library in the symbol library table using the full path and file name.
247  wxString libFileName = it->GetFullFileName();
248 
249  const LIB_TABLE_ROW* row = Prj().SchSymbolLibTable()->FindRowByURI( libFileName );
250 
251  if( row )
252  {
253  LIB_ID id = aSymbol->GetLibId();
254 
255  id.SetLibNickname( row->GetNickName() );
256  aSymbol->SetLibId( id, Prj().SchSymbolLibTable() );
257  return true;
258  }
259  }
260  }
261 
262  return false;
263 }
264 
265 
266 bool DIALOG_SYMBOL_REMAP::normalizeAbsolutePaths( const wxFileName& aPathA,
267  const wxFileName& aPathB,
268  wxString* aResultPath )
269 {
270  wxCHECK_MSG( aPathA.IsAbsolute(), false, "Arguement 'aPathA' must be an absolute path." );
271  wxCHECK_MSG( aPathB.IsAbsolute(), false, "Arguement 'aPathB' must be an absolute path." );
272 
273  if( aPathA.GetPath() == aPathB.GetPath() )
274  return true;
275 
276  if( ( aPathA.GetDirCount() > aPathB.GetDirCount() )
277  || ( aPathA.HasVolume() && !aPathB.HasVolume() )
278  || ( !aPathA.HasVolume() && aPathB.HasVolume() )
279  || ( ( aPathA.HasVolume() && aPathB.HasVolume() )
280  && ( aPathA.GetVolume() == aPathB.GetVolume() ) ) )
281  return false;
282 
283  wxArrayString aDirs = aPathA.GetDirs();
284  wxArrayString bDirs = aPathB.GetDirs();
285 
286  size_t i = 0;
287 
288  while( i < aDirs.GetCount() )
289  {
290  if( aDirs[i] != bDirs[i] )
291  return false;
292 
293  i++;
294  }
295 
296  if( aResultPath )
297  {
298  while( i < bDirs.GetCount() )
299  {
300  *aResultPath += bDirs[i] + wxT( "/" );
301  i++;
302  }
303  }
304 
305  return true;
306 }
DIALOG_SYMBOL_REMAP(wxWindow *aParent)
Definition of the SCH_SHEET class for Eeschema.
KICAD_T Type() const
Function Type()
Definition: base_struct.h:198
static const wxString & GetSymbolLibTableFileName()
static SYMBOL_LIB_TABLE & GetGlobalLibTable()
Part library alias object definition.
SCH_SCREEN * GetNext()
Class SYMBOL_LIB_TABLE_ROW.
Class LIB_TABLE_ROW.
static wxString FROM_UTF8(const char *cstring)
function FROM_UTF8 converts a UTF8 encoded C string to a wxString for all wxWidgets build modes...
Definition: macros.h:53
bool InsertRow(LIB_TABLE_ROW *aRow, bool doReplace=false)
Function InsertRow.
This file is part of the common library.
size_t getLibsNotInGlobalSymbolLibTable(std::vector< PART_LIB * > &aLibs)
Function getLibsNotInGlobalSymbolLibTable.
static const wxString ShowType(SCH_FILE_T aFileType)
Return a brief name for a plugin, given aFileType enum.
Definition: sch_io_mgr.cpp:75
#define PROJECT_VAR_NAME
A variable name whose value holds the current project directory.
Definition: project.h:32
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: kicad.cpp:65
Class REPORTER is a pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:61
Class LIB_ID.
Definition: lib_id.h:56
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:208
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
void createProjectSymbolLibTable(REPORTER &aReporter)
VTBL_ENTRY const ENV_VAR_MAP & GetLocalEnvVariables() const
Definition: pgm_base.h:270
std::map< wxString, ENV_VAR_ITEM > ENV_VAR_MAP
Definition: pgm_base.h:87
Legacy Eeschema file formats prior to s-expression.
Definition: sch_io_mgr.h:54
Definitions for the Eeschema program SCH_SCREEN class.
const UTF8 & GetLibItemName() const
Function GetLibItemName.
Definition: lib_id.h:129
REPORTER & Reporter()
returns the reporter object that reports to this panel
void remapSymbolsToLibTable(REPORTER &aReporter)
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)
Function SetLibNickname.
Definition: lib_id.cpp:219
Class PART_LIBS is a collection of PART_LIBs.
SCH_ITEM * GetDrawItems() const
Function GetDrawItems().
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
Function GetNickName.
see class PGM_BASE
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
Function GetLibNickname.
Definition: lib_id.h:108
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...
bool normalizeAbsolutePaths(const wxFileName &aPathA, const wxFileName &aPathB, wxString *aResultPath)
Class SCH_SCREENS is a container class that holds multiple SCH_SCREENs in a hierarchy.
std::vector< wxString > GetLogicalLibs()
Function GetLogicalLibs.