KiCad PCB EDA Suite
symbol_editor_import_export.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) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com>
6  * Copyright (C) 2004-2021 KiCad Developers, see AUTHORS.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 <confirm.h>
27 #include <symbol_lib_table.h>
28 #include <symbol_edit_frame.h>
29 #include <symbol_library.h>
31 #include <symbol_library_manager.h>
32 #include <wx/filename.h>
33 #include <wx/filedlg.h>
34 #include <kicad_string.h>
35 
36 
38 {
39  wxString msg;
40  wxString libName = getTargetLib();
41 
42  if( !m_libMgr->LibraryExists( libName ) )
43  {
44  libName = SelectLibraryFromList();
45 
46  if( !m_libMgr->LibraryExists( libName ) )
47  return;
48  }
49 
50  wxString wildcards = KiCadSymbolLibFileWildcard();
51 
52  wildcards += "|" + LegacySymbolLibFileWildcard();
53 
54  wxFileDialog dlg( this, _( "Import Symbol" ), m_mruPath, wxEmptyString,
55  wildcards, wxFD_OPEN | wxFD_FILE_MUST_EXIST );
56 
57  if( dlg.ShowModal() == wxID_CANCEL )
58  return;
59 
60  wxFileName fn = dlg.GetPath();
61 
62  if( fn.GetExt().IsEmpty() )
63  fn.SetExt( (dlg.GetFilterIndex() == 0) ?
65 
66  m_mruPath = fn.GetPath();
67 
68  wxArrayString symbols;
69  SCH_IO_MGR::SCH_FILE_T piType = SCH_IO_MGR::GuessPluginTypeFromLibPath( fn.GetFullPath() );
70  SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( piType ) );
71 
72  // TODO dialog to select the symbol to be imported if there is more than one
73  try
74  {
75  pi->EnumerateSymbolLib( symbols, fn.GetFullPath() );
76  }
77  catch( const IO_ERROR& ioe )
78  {
79  msg.Printf( _( "Cannot import symbol library '%s'." ), fn.GetFullPath() );
80  DisplayErrorMessage( this, msg, ioe.What() );
81  return;
82  }
83 
84  if( symbols.empty() )
85  {
86  msg.Printf( _( "Symbol library file '%s' is empty." ), fn.GetFullPath() );
87  DisplayError( this, msg );
88  return;
89  }
90 
91  wxString symbolName = symbols[0];
92  LIB_SYMBOL* entry = pi->LoadSymbol( fn.GetFullPath(), symbolName );
93 
94  if( m_libMgr->SymbolExists( symbols[0], libName ) )
95  {
96  msg.Printf( _( "Symbol %s already exists in library '%s'." ), symbolName, libName );
97  DisplayError( this, msg );
98  return;
99  }
100 
101  m_libMgr->UpdateSymbol( entry, libName );
102  SyncLibraries( false );
103  LoadSymbol( symbolName, libName, 1 );
104 }
105 
106 
108 {
109  wxString msg, title;
110  LIB_SYMBOL* symbol = getTargetSymbol();
111 
112  if( !symbol )
113  {
114  ShowInfoBarError( _( "There is no symbol selected to save." ) );
115  return;
116  }
117 
118  wxFileName fn;
119 
120  fn.SetName( symbol->GetName().Lower() );
121  fn.SetExt( KiCadSymbolLibFileExtension );
122 
123  wxFileDialog dlg( this, _( "Export Symbol" ), m_mruPath, fn.GetFullName(),
124  KiCadSymbolLibFileWildcard(), wxFD_SAVE );
125 
126  if( dlg.ShowModal() == wxID_CANCEL )
127  return;
128 
129  fn = dlg.GetPath();
130  fn.MakeAbsolute();
131 
132  LIB_SYMBOL* old_symbol = nullptr;
133  SCH_IO_MGR::SCH_FILE_T pluginType = SCH_IO_MGR::GuessPluginTypeFromLibPath( fn.GetFullPath() );
134  SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( pluginType ) );
135 
136  if( fn.FileExists() )
137  {
138  try
139  {
140  old_symbol = pi->LoadSymbol( fn.GetFullPath(), symbol->GetName() );
141  }
142  catch( const IO_ERROR& ioe )
143  {
144  msg.Printf( _( "Error occurred attempting to load symbol library file '%s'." ),
145  fn.GetFullPath() );
146  DisplayErrorMessage( this, msg, ioe.What() );
147  return;
148  }
149 
150  if( old_symbol )
151  {
152  msg.Printf( _( "Symbol %s already exists in library '%s'." ),
153  UnescapeString( symbol->GetName() ),
154  fn.GetFullName() );
155 
156  KIDIALOG errorDlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
157  errorDlg.SetOKLabel( _( "Overwrite" ) );
158  errorDlg.DoNotShowCheckbox( __FILE__, __LINE__ );
159 
160  if( errorDlg.ShowModal() == wxID_CANCEL )
161  return;
162  }
163  }
164 
165  if( fn.Exists() && !fn.IsDirWritable() )
166  {
167  msg.Printf( _( "Insufficient permissions to save library '%s'." ),
168  fn.GetFullPath() );
169  DisplayError( this, msg );
170  return;
171  }
172 
173  try
174  {
175  if( !fn.FileExists() )
176  pi->CreateSymbolLib( fn.GetFullPath() );
177 
178  // The flattened symbol is most likely what the user would want. As some point in
179  // the future as more of the symbol library inheritance is implemented, this may have
180  // to be changes to save symbols of inherited symbols.
181  pi->SaveSymbol( fn.GetFullPath(), symbol->Flatten().release() );
182  }
183  catch( const IO_ERROR& ioe )
184  {
185  msg.Printf( _( "Failed to create symbol library file '%s'." ), fn.GetFullPath() );
186  DisplayErrorMessage( this, msg, ioe.What() );
187  msg.Printf( _( "Error creating symbol library '%s'." ), fn.GetFullName() );
188  SetStatusText( msg );
189  return;
190  }
191 
192  m_mruPath = fn.GetPath();
193 
194  msg.Printf( _( "Symbol %s saved to library '%s'." ),
195  UnescapeString( symbol->GetName() ),
196  fn.GetFullPath() );
197  SetStatusText( msg );
198 
199  // See if the user wants it added to a library table (global or project)
200  SYMBOL_LIB_TABLE* libTable = selectSymLibTable( true );
201 
202  if( libTable )
203  {
204  if( !m_libMgr->AddLibrary( fn.GetFullPath(), libTable ) )
205  {
206  DisplayError( this, _( "Could not open the library file." ) );
207  return;
208  }
209 
210  bool globalTable = ( libTable == &SYMBOL_LIB_TABLE::GetGlobalLibTable() );
211  saveSymbolLibTables( globalTable, !globalTable );
212  }
213 }
static SCH_FILE_T GuessPluginTypeFromLibPath(const wxString &aLibPath)
Return a plugin type given a symbol library using the file extension of aLibPath.
Definition: sch_io_mgr.cpp:151
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:252
static SYMBOL_LIB_TABLE & GetGlobalLibTable()
void DoNotShowCheckbox(wxString file, int line)
Checks the 'do not show again' setting for the dialog.
Definition: confirm.cpp:55
wxString m_mruPath
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:265
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: confirm.h:45
This file is part of the common library.
wxString GetName() const override
Definition: lib_symbol.h:133
bool AddLibrary(const wxString &aFilePath, SYMBOL_LIB_TABLE *aTable)
Add an existing library.
const std::string LegacySymbolLibFileExtension
Define a library symbol object.
Definition: lib_symbol.h:96
SYMBOL_LIB_TABLE * selectSymLibTable(bool aOptional=false)
Display a dialog asking the user to select a symbol library table.
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
Definition: lib_symbol.cpp:332
LIB_SYMBOL * getTargetSymbol() const
Return either the library selected in the symbol tree, if context menu is active or the library that ...
bool SymbolExists(const wxString &aAlias, const wxString &aLibrary) const
Return true if symbol with a specific alias exists in library (either original one or buffered).
void LoadSymbol(const wxString &aLibrary, const wxString &aSymbol, int Unit)
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
wxString getTargetLib() const
Definition of file extensions used in Kicad.
Definition for symbol library class.
bool saveSymbolLibTables(bool aGlobal, bool aProject)
Save Symbol Library Tables to disk.
#define _(s)
wxString SelectLibraryFromList()
Display a list of loaded libraries in the symbol library and allows the user to select a library.
wxString KiCadSymbolLibFileWildcard()
wxString LegacySymbolLibFileWildcard()
Helper object to release a SCH_PLUGIN in the context of a potential thrown exception through its dest...
Definition: sch_io_mgr.h:479
bool LibraryExists(const wxString &aLibrary, bool aCheckEnabled=false) const
Return true if library exists.
wxString UnescapeString(const wxString &aSource)
Definition: string.cpp:222
void ShowInfoBarError(const wxString &aErrorMsg, bool aShowCloseButton=false)
Show the WX_INFOBAR displayed on the top of the canvas with a message and an error icon on the left o...
int ShowModal() override
Definition: confirm.cpp:99
bool UpdateSymbol(LIB_SYMBOL *aSymbol, const wxString &aLibrary)
Update the symbol buffer with a new version of the symbol.
SYMBOL_LIBRARY_MANAGER * m_libMgr
void SyncLibraries(bool aShowProgress, const wxString &aForceRefresh=wxEmptyString)
Synchronize the library manager to the symbol library table, and then the symbol tree to the library ...
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:75
const std::string KiCadSymbolLibFileExtension