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 <string_utils.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  entry->SetName( EscapeString( entry->GetName(), CTX_LIBID ) );
95 
96  if( m_libMgr->SymbolExists( entry->GetName(), libName ) )
97  {
98  msg.Printf( _( "Symbol %s already exists in library '%s'." ), symbolName, libName );
99 
100  KIDIALOG errorDlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
101  errorDlg.SetOKLabel( _( "Overwrite" ) );
102  errorDlg.DoNotShowCheckbox( __FILE__, __LINE__ );
103 
104  if( errorDlg.ShowModal() == wxID_CANCEL )
105  return;
106  }
107 
108  m_libMgr->UpdateSymbol( entry, libName );
109  SyncLibraries( false );
110  LoadSymbol( entry->GetName(), libName, 1 );
111 }
112 
113 
115 {
116  wxString msg, title;
117  LIB_SYMBOL* symbol = getTargetSymbol();
118 
119  if( !symbol )
120  {
121  ShowInfoBarError( _( "There is no symbol selected to save." ) );
122  return;
123  }
124 
125  wxFileName fn;
126 
127  fn.SetName( symbol->GetName().Lower() );
128  fn.SetExt( KiCadSymbolLibFileExtension );
129 
130  wxFileDialog dlg( this, _( "Export Symbol" ), m_mruPath, fn.GetFullName(),
131  KiCadSymbolLibFileWildcard(), wxFD_SAVE );
132 
133  if( dlg.ShowModal() == wxID_CANCEL )
134  return;
135 
136  fn = dlg.GetPath();
137  fn.MakeAbsolute();
138 
139  LIB_SYMBOL* old_symbol = nullptr;
140  SCH_IO_MGR::SCH_FILE_T pluginType = SCH_IO_MGR::GuessPluginTypeFromLibPath( fn.GetFullPath() );
141  SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( pluginType ) );
142 
143  if( fn.FileExists() )
144  {
145  try
146  {
147  old_symbol = pi->LoadSymbol( fn.GetFullPath(), symbol->GetName() );
148  }
149  catch( const IO_ERROR& ioe )
150  {
151  msg.Printf( _( "Error occurred attempting to load symbol library file '%s'." ),
152  fn.GetFullPath() );
153  DisplayErrorMessage( this, msg, ioe.What() );
154  return;
155  }
156 
157  if( old_symbol )
158  {
159  msg.Printf( _( "Symbol %s already exists in library '%s'." ),
160  UnescapeString( symbol->GetName() ),
161  fn.GetFullName() );
162 
163  KIDIALOG errorDlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
164  errorDlg.SetOKLabel( _( "Overwrite" ) );
165  errorDlg.DoNotShowCheckbox( __FILE__, __LINE__ );
166 
167  if( errorDlg.ShowModal() == wxID_CANCEL )
168  return;
169  }
170  }
171 
172  if( fn.Exists() && !fn.IsDirWritable() )
173  {
174  msg.Printf( _( "Insufficient permissions to save library '%s'." ),
175  fn.GetFullPath() );
176  DisplayError( this, msg );
177  return;
178  }
179 
180  try
181  {
182  if( !fn.FileExists() )
183  pi->CreateSymbolLib( fn.GetFullPath() );
184 
185  // The flattened symbol is most likely what the user would want. As some point in
186  // the future as more of the symbol library inheritance is implemented, this may have
187  // to be changes to save symbols of inherited symbols.
188  pi->SaveSymbol( fn.GetFullPath(), symbol->Flatten().release() );
189  }
190  catch( const IO_ERROR& ioe )
191  {
192  msg.Printf( _( "Failed to create symbol library file '%s'." ), fn.GetFullPath() );
193  DisplayErrorMessage( this, msg, ioe.What() );
194  msg.Printf( _( "Error creating symbol library '%s'." ), fn.GetFullName() );
195  SetStatusText( msg );
196  return;
197  }
198 
199  m_mruPath = fn.GetPath();
200 
201  msg.Printf( _( "Symbol %s saved to library '%s'." ),
202  UnescapeString( symbol->GetName() ),
203  fn.GetFullPath() );
204  SetStatusText( msg );
205 
206  // See if the user wants it added to a library table (global or project)
207  SYMBOL_LIB_TABLE* libTable = selectSymLibTable( true );
208 
209  if( libTable )
210  {
211  if( !m_libMgr->AddLibrary( fn.GetFullPath(), libTable ) )
212  {
213  DisplayError( this, _( "Could not open the library file." ) );
214  return;
215  }
216 
217  bool globalTable = ( libTable == &SYMBOL_LIB_TABLE::GetGlobalLibTable() );
218  saveSymbolLibTables( globalTable, !globalTable );
219  }
220 }
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:279
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:292
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:331
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 ShowInfoBarError(const wxString &aErrorMsg, bool aShowCloseButton=false, WX_INFOBAR::MESSAGE_TYPE aType=WX_INFOBAR::MESSAGE_TYPE::GENERIC)
Show the WX_INFOBAR displayed on the top of the canvas with a message and an error icon on the left o...
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
virtual void SetName(const wxString &aName)
Definition: lib_symbol.cpp:313
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()
wxString UnescapeString(const wxString &aSource)
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.
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
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
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