KiCad PCB EDA Suite
eeschema/eeschema.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
5  * Copyright (C) 2008 Wayne Stambaugh <stambaughw@verizon.net>
6  * Copyright (C) 2004-2017 KiCad Developers, see change_log.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
26 #include <fctsys.h>
27 #include <pgm_base.h>
28 #include <kiface_i.h>
29 #include <confirm.h>
30 #include <gestfich.h>
31 #include <eda_dde.h>
32 #include <eeschema_settings.h>
33 #include <sch_edit_frame.h>
34 #include <lib_edit_frame.h>
35 #include <lib_view_frame.h>
36 #include <general.h>
37 #include <class_libentry.h>
38 #include <transform.h>
39 #include <symbol_lib_table.h>
42 #include <kiway.h>
43 #include <sim/sim_plot_frame.h>
45 #include <sexpr/sexpr.h>
46 #include <sexpr/sexpr_parser.h>
47 
48 // The main sheet of the project
50 
51 // a transform matrix, to display components in lib editor
53 
54 
55 namespace SCH {
56 
57 static struct IFACE : public KIFACE_I
58 {
59  // Of course all are virtual overloads, implementations of the KIFACE.
60 
61  IFACE( const char* aName, KIWAY::FACE_T aType ) :
62  KIFACE_I( aName, aType )
63  {}
64 
65  bool OnKifaceStart( PGM_BASE* aProgram, int aCtlBits ) override;
66 
67  void OnKifaceEnd() override;
68 
69  wxWindow* CreateWindow( wxWindow* aParent, int aClassId, KIWAY* aKiway, int aCtlBits = 0 ) override
70  {
71  switch( aClassId )
72  {
73  case FRAME_SCH:
74  {
75  SCH_EDIT_FRAME* frame = new SCH_EDIT_FRAME( aKiway, aParent );
76 
77  if( Kiface().IsSingle() )
78  {
79  // only run this under single_top, not under a project manager.
81  }
82 
83  return frame;
84  }
85 
87  {
88  LIB_EDIT_FRAME* frame = new LIB_EDIT_FRAME( aKiway, aParent );
89  return frame;
90  }
91 
92 #ifdef KICAD_SPICE
93  case FRAME_SIMULATOR:
94  {
95  SIM_PLOT_FRAME* frame = new SIM_PLOT_FRAME( aKiway, aParent );
96  return frame;
97  }
98 #endif
99  case FRAME_SCH_VIEWER:
101  {
102  LIB_VIEW_FRAME* frame = new LIB_VIEW_FRAME( aKiway, aParent, FRAME_T( aClassId ) );
103  return frame;
104  }
105 
107  InvokeSchEditSymbolLibTable( aKiway, aParent );
108  // Dialog has completed; nothing to return.
109  return nullptr;
110 
111  default:
112  return NULL;
113  }
114  }
115 
124  void* IfaceOrAddress( int aDataId ) override
125  {
126  return NULL;
127  }
128 
135  void SaveFileAs( const wxString& aProjectBasePath, const wxString& aProjectName,
136  const wxString& aNewProjectBasePath, const wxString& aNewProjectName,
137  const wxString& aSrcFilePath, wxString& aErrors ) override;
138 
139 } kiface( "eeschema", KIWAY::FACE_SCH );
140 
141 } // namespace
142 
143 using namespace SCH;
144 
146 
147 
148 KIFACE_I& Kiface() { return kiface; }
149 
150 
151 // KIFACE_GETTER's actual spelling is a substitution macro found in kiway.h.
152 // KIFACE_GETTER will not have name mangling due to declaration in kiway.h.
153 MY_API( KIFACE* ) KIFACE_GETTER( int* aKIFACEversion, int aKiwayVersion, PGM_BASE* aProgram )
154 {
155  process = aProgram;
156  return &kiface;
157 }
158 
159 
161 {
162  wxASSERT( process ); // KIFACE_GETTER has already been called.
163  return *process;
164 }
165 
166 
167 bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits )
168 {
169  // This is process-level-initialization, not project-level-initialization of the DSO.
170  // Do nothing in here pertinent to a project!
173 
174  start_common( aCtlBits );
175 
177 
178  if( !fn.FileExists() )
179  {
181 
182  fpDialog.ShowModal();
183  }
184  else
185  {
186  try
187  {
188  // The global table is not related to a specific project. All projects
189  // will use the same global table. So the KIFACE::OnKifaceStart() contract
190  // of avoiding anything project specific is not violated here.
192  return false;
193  }
194  catch( const IO_ERROR& ioe )
195  {
196  // if we are here, a incorrect global symbol library table was found.
197  // Incorrect global symbol library table is not a fatal error:
198  // the user just has to edit the (partially) loaded table.
199  wxString msg = _(
200  "An error occurred attempting to load the global symbol library table.\n"
201  "Please edit this global symbol library table in Preferences menu."
202  );
203 
204  DisplayErrorMessage( NULL, msg, ioe.What() );
205  }
206  }
207 
208  return true;
209 }
210 
211 
213 {
215 
216  for( SCH_LAYER_ID layer = SCH_LAYER_ID_START; layer < SCH_LAYER_ID_END; ++layer )
217  {
218  cs->SetColor( layer, GetLayerColor( layer ) );
219  }
220 
221  end_common();
222 }
223 
224 static void traverseSEXPR( SEXPR::SEXPR* aNode,
225  const std::function<void( SEXPR::SEXPR* )>& aVisitor )
226 {
227  aVisitor( aNode );
228 
229  if( aNode->IsList() )
230  {
231  for( unsigned i = 0; i < aNode->GetNumberOfChildren(); i++ )
232  traverseSEXPR( aNode->GetChild( i ), aVisitor );
233  }
234 }
235 
236 
237 void IFACE::SaveFileAs( const wxString& aProjectBasePath, const wxString& aProjectName,
238  const wxString& aNewProjectBasePath, const wxString& aNewProjectName,
239  const wxString& aSrcFilePath, wxString& aErrors )
240 {
241  wxFileName destFile( aSrcFilePath );
242  wxString destPath = destFile.GetPathWithSep();
243  wxUniChar pathSep = wxFileName::GetPathSeparator();
244  wxString ext = destFile.GetExt();
245 
246  if( destPath.StartsWith( aProjectBasePath + pathSep ) )
247  destPath.Replace( aProjectBasePath, aNewProjectBasePath, false );
249 #if 0
250  // WAYNE STAMBAUGH TODO:
251  // If we end up with a symbol equivalent to ".pretty" we'll want to handle it here....
252  wxString srcProjectSymbolLib = pathSep + aProjectName + ".sym_lib_dir_extension" + pathSep;
253  wxString newProjectSymbolLib = pathSep + aNewProjectName + ".sym_lib_dir_extension" + pathSep;
254 
255  destPath.Replace( srcProjectSymbolLib, newProjectSymbolLib, true );
256 #endif
257 
258  destFile.SetPath( destPath );
259 
260  if( ext == "sch" || ext == "sch-bak" )
261  {
262  if( destFile.GetName() == aProjectName )
263  destFile.SetName( aNewProjectName );
264 
265  // Sheet paths when auto-generated are relative to the root, so those will stay
266  // pointing to whatever they were pointing at.
267  // The author can create their own absolute and relative sheet paths. Absolute
268  // sheet paths aren't an issue, and relative ones will continue to work as long
269  // as the author didn't include any '..'s. If they did, it's still not clear
270  // whether they should be adjusted or not (as the author may be duplicating an
271  // entire tree with several projects within it), so we leave this as an exercise
272  // to the author.
273 
274  CopyFile( aSrcFilePath, destFile.GetFullPath(), aErrors );
275  }
276  else if( ext == "sym" )
277  {
278  // Symbols are not project-specific. Keep their source names.
279  CopyFile( aSrcFilePath, destFile.GetFullPath(), aErrors );
280  }
281  else if( ext == "lib" )
282  {
283  if( destFile.GetName() == aProjectName )
284  destFile.SetName( aNewProjectName );
285  else if( destFile.GetName() == aProjectName + "-cache" )
286  destFile.SetName( aNewProjectName + "-cache" );
287  else if( destFile.GetName() == aProjectName + "-rescue" )
288  destFile.SetName( aNewProjectName + "-rescue" );
289 
290  CopyFile( aSrcFilePath, destFile.GetFullPath(), aErrors );
291  }
292  else if( ext == "net" )
293  {
294  bool success = false;
295 
296  if( destFile.GetName() == aProjectName )
297  destFile.SetName( aNewProjectName );
298 
299  try
300  {
301  SEXPR::PARSER parser;
302  std::unique_ptr<SEXPR::SEXPR> sexpr( parser.ParseFromFile( TO_UTF8( aSrcFilePath ) ) );
304  traverseSEXPR( sexpr.get(), [&]( SEXPR::SEXPR* node )
305  {
306  if( node->IsList() && node->GetNumberOfChildren() > 1
307  && node->GetChild( 0 )->IsSymbol()
308  && node->GetChild( 0 )->GetSymbol() == "source" )
309  {
310  auto pathNode = dynamic_cast<SEXPR::SEXPR_STRING*>( node->GetChild( 1 ) );
311  auto symNode = dynamic_cast<SEXPR::SEXPR_SYMBOL*>( node->GetChild( 1 ) );
312  wxString path;
313 
314  if( pathNode )
315  path = pathNode->m_value;
316  else if( symNode )
317  path = symNode->m_value;
318 
319  if( path == aProjectName + ".sch" )
320  path = aNewProjectName + ".sch";
321  else if( path == aProjectBasePath + "/" + aProjectName + ".sch" )
322  path = aNewProjectBasePath + "/" + aNewProjectName + ".sch";
323  else if( path.StartsWith( aProjectBasePath ) )
324  path.Replace( aProjectBasePath, aNewProjectBasePath, false );
325 
326  if( pathNode )
327  pathNode->m_value = path;
328  else if( symNode )
329  symNode->m_value = path;
330  }
331  } );
332 
333  wxFile destNetList( destFile.GetFullPath(), wxFile::write );
334 
335  if( destNetList.IsOpened() )
336  success = destNetList.Write( sexpr->AsString( 0 ) );
337 
338  // wxFile dtor will close the file
339  }
340  catch( ... )
341  {
342  success = false;
343  }
344 
345  if( !success )
346  {
347  wxString msg;
348 
349  if( !aErrors.empty() )
350  aErrors += "\n";
351 
352  msg.Printf( _( "Cannot copy file \"%s\"." ), destFile.GetFullPath() );
353  aErrors += msg;
354  }
355  }
356  else if( destFile.GetName() == "sym-lib-table" )
357  {
358  SYMBOL_LIB_TABLE symbolLibTable;
359  symbolLibTable.Load( aSrcFilePath );
360 
361  for( unsigned i = 0; i < symbolLibTable.GetCount(); i++ )
362  {
363  LIB_TABLE_ROW& row = symbolLibTable.At( i );
364  wxString uri = row.GetFullURI();
365 
366  uri.Replace( "/" + aProjectName + "-cache.lib", "/" + aNewProjectName + "-cache.lib" );
367  uri.Replace( "/" + aProjectName + "-rescue.lib", "/" + aNewProjectName + "-rescue.lib" );
368  uri.Replace( "/" + aProjectName + ".lib", "/" + aNewProjectName + ".lib" );
369 
370  row.SetFullURI( uri );
371  }
372 
373  try
374  {
375  symbolLibTable.Save( destFile.GetFullPath() );
376  }
377  catch( ... )
378  {
379  wxString msg;
380 
381  if( !aErrors.empty() )
382  aErrors += "\n";
383 
384  msg.Printf( _( "Cannot copy file \"%s\"." ), destFile.GetFullPath() );
385  aErrors += msg;
386  }
387  }
388  else
389  {
390  wxFAIL_MSG( "Unexpected filetype for Eeschema::SaveFileAs()" );
391  }
392 }
393 
SCH::IFACE KIFACE_I kiface("eeschema", KIWAY::FACE_SCH)
PGM_BASE & Pgm()
The global Program "get" accessor.
static SYMBOL_LIB_TABLE & GetGlobalLibTable()
KIFACE_I is a KIFACE (I)mplementation, with some features useful for DSOs which implement a KIFACE.
Definition: kiface_i.h:37
int aKiwayVersion
DDE server & client.
bool start_common(int aCtlBits)
Common things to do for a top program module, during OnKifaceStart().
Definition: kiface_i.cpp:89
Hold a record identifying a library accessed by the appropriate plug in object in the LIB_TABLE.
VTBL_ENTRY SETTINGS_MANAGER & GetSettingsManager() const
Definition: pgm_base.h:175
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:252
This file is part of the common library TODO brief description.
This file is part of the common library.
void OnKifaceEnd() override
Function OnKifaceEnd is called just once just before the DSO is to be unloaded.
PGM_BASE keeps program (whole process) data for KiCad programs.
Definition: pgm_base.h:137
FRAME_T
Enum FRAME_T is the set of EDA_BASE_FRAME derivatives, typically stored in EDA_BASE_FRAME::m_Ident.
Definition: frame_type.h:34
unsigned GetCount() const
Get the number of rows contained in the table.
wxWindow * CreateWindow(wxWindow *aParent, int aClassId, KIWAY *aKiway, int aCtlBits=0) override
Function CreateWindow creates a wxWindow for the current project.
void * IfaceOrAddress(int aDataId) override
Function IfaceOrAddress return a pointer to the requested object.
void InvokeSchEditSymbolLibTable(KIWAY *aKiway, wxWindow *aParent)
bool IsList() const
Definition: sexpr.h:54
void CopyFile(const wxString &aSrcPath, const wxString &aDestPath, wxString &aErrors)
Function CopyFile.
Definition: gestfich.cpp:363
IFACE(const char *aName, KIWAY::FACE_T aType)
APP_SETTINGS_BASE * KifaceSettings() const
Definition: kiface_i.h:103
TRANSFORM DefaultTransform
Schematic editor (Eeschema) main window.
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
Symbol library viewer main window.
const wxString GetFullURI(bool aSubstituted=false) const
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
int PGM_BASE * aProgram
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:48
for transforming drawing coordinates for a wxDC device context.
Definition: transform.h:45
static bool LoadGlobalTable(SYMBOL_LIB_TABLE &aTable)
Load the global symbol library table into aTable.
#define KICAD_SCH_PORT_SERVICE_NUMBER
Definition: eda_dde.h:42
bool OnKifaceStart(PGM_BASE *aProgram, int aCtlBits) override
Function OnKifaceStart is called just once shortly after the DSO is loaded.
#define NULL
bool IsSingle() const
Function IsSingle is this KIFACE_I running under single_top?
Definition: kiface_i.h:117
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:33
void end_common()
Common things to do for a top program module, during OnKifaceEnd();.
Definition: kiface_i.cpp:99
void SaveFileAs(const wxString &aProjectBasePath, const wxString &aProjectName, const wxString &aNewProjectBasePath, const wxString &aNewProjectName, const wxString &aSrcFilePath, wxString &aErrors) override
Function SaveFileAs Saving a file under a different name is delegated to the various KIFACEs because ...
SEXPR * GetChild(size_t aIndex) const
Definition: sexpr.cpp:47
Class LIB_PIN definition.
COLOR4D GetLayerColor(SCH_LAYER_ID aLayer)
Helper for all the old plotting/printing code while it still exists.
static PGM_BASE * process
KIWAY is a minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the s...
Definition: kiway.h:273
static void traverseSEXPR(SEXPR::SEXPR *aNode, const std::function< void(SEXPR::SEXPR *)> &aVisitor)
Subclass of SIM_PLOT_FRAME_BASE, which is generated by wxFormBuilder.
#define KIFACE_GETTER
Definition: kiway.h:112
SCH_LAYER_ID
Eeschema drawing layers.
void Load(const wxString &aFileName)
Load the library table using the path defined by aFileName aFallBackTable.
Implementing SIM_PLOT_FRAME_BASE.
FACE_T
Known KIFACE implementations.
Definition: kiway.h:279
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:215
JSON_SETTINGS * RegisterSettings(JSON_SETTINGS *aSettings, bool aLoadNow=true)
Takes ownership of the pointer passed in.
eeschema DSO
Definition: kiway.h:281
COLOR_SETTINGS * GetColorSettings(const wxString &aName="user")
Retrieves a color settings object that applications can read colors from.
The symbol library editor main window.
void SetFullURI(const wxString &aFullURI)
Change the full URI for the library.
see class PGM_BASE
LIB_TABLE_ROW & At(unsigned aIndex)
Get the 'n'th LIB_TABLE_ROW object.
#define _(s)
Definition: 3d_actions.cpp:33
MY_API(KIFACE *) KIFACE_GETTER(int *aKIFACEversion
KIFACE is used by a participant in the KIWAY alchemy.
Definition: kiway.h:150
void Save(const wxString &aFileName) const
Write this library table to aFileName in s-expression form.
void InitSettings(APP_SETTINGS_BASE *aSettings)
Definition: kiface_i.h:105
SCH_SHEET * g_RootSheet
void CreateServer(int service, bool local=true)
Definition: eda_dde.cpp:49
size_t GetNumberOfChildren() const
Definition: sexpr.cpp:69
Struct IO_ERROR is a class used to hold an error message and may be used when throwing exceptions con...
Definition: ki_exception.h:76
static wxString GetGlobalTableFileName()
Fetch the global symbol library table file name.
std::unique_ptr< SEXPR > ParseFromFile(const std::string &aFilename)
void SetColor(int aLayer, COLOR4D aColor)