22#include <fmt/format.h>
69 wxString::Format( wxT(
"Cannot use relative file paths in sexpr plugin to open library '%s'." ),
92 if( !warnings.empty() )
96 wxString errorMsg = wxString::Format(
97 _(
"Library '%s' loaded with errors:\n\n" ),
m_libFileName.GetFullPath() );
99 for(
const wxString& warning : warnings )
100 errorMsg += warning + wxT(
"\n\n" );
102 errorMsg +=
_(
"The library cannot be saved until these errors are fixed manually." );
109 wxString libFileName;
120 if( dir.GetFirst( &libFileName, fileSpec ) )
126 tmp.SetFullName( libFileName );
127 wxString sourceFilePath = tmp.GetFullPath();
132 std::map<wxString, LIB_SYMBOL*> existingPtrs;
135 existingPtrs[
name ] = symbol;
150 auto it = existingPtrs.find(
name );
152 if( it == existingPtrs.end() )
157 else if( it->second != symbol )
171 if( !errorCache.IsEmpty() )
172 errorCache += wxT(
"\n\n" );
174 errorCache += warning;
182 if( !errorCache.IsEmpty() )
183 errorCache += wxT(
"\n\n" );
185 errorCache += wxString::Format(
_(
"Unable to read file '%s'" ) +
'\n', sourceFilePath );
186 errorCache += ioe.
What();
188 }
while( dir.GetNext( &libFileName ) );
190 if( !errorCache.IsEmpty() )
192 errorCache +=
_(
"\n\nThe library cannot be saved until these errors are fixed manually." );
217 THROW_IO_ERRORF(
_(
"Cannot save library '%s' because it had a parse error during loading.\n\n"
218 "Saving would permanently lose symbols that could not be loaded.\n"
219 "Please fix the library file manually before saving." ),
228 if( !fn.IsDir() && wxFileName::DirExists( fn.GetFullPath() ) )
229 fn.AssignDir( fn.GetFullPath() );
233 auto formatter = std::make_unique<PRETTIFIED_FILE_OUTPUTFORMATTER>( fn.GetFullPath() );
237 std::vector<LIB_SYMBOL*> orderedSymbols;
242 orderedSymbols.push_back( symbol );
246 std::sort( orderedSymbols.begin(), orderedSymbols.end(),
249 unsigned int lhDepth = aLhs->GetInheritanceDepth();
250 unsigned int rhDepth = aRhs->GetInheritanceDepth();
252 if( lhDepth == rhDepth )
253 return aLhs->GetName() < aRhs->GetName();
255 return lhDepth < rhDepth;
261 formatter->Print(
")" );
267 if( !fn.DirExists() )
269 if( !fn.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) )
270 THROW_IO_ERRORF(
_(
"Cannot create symbol library path '%s'." ), fn.GetPath() );
289 std::map<wxString, std::vector<LIB_SYMBOL*>> symbolsByFile;
298 symbolsByFile[ it->second ].push_back( symbol );
303 wxFileName saveFn( fn );
307 symbolsByFile[ saveFn.GetFullPath() ].push_back( symbol );
312 auto sortByInheritance =
316 unsigned int rhDepth = aRhs->GetInheritanceDepth();
318 if( lhDepth == rhDepth )
319 return aLhs->
GetName() < aRhs->GetName();
321 return lhDepth < rhDepth;
325 for(
auto& [ filePath, symbols ] : symbolsByFile )
327 wxFileName oldFn = filePath;
332 std::sort( symbols.begin(), symbols.end(), sortByInheritance );
334 auto formatter = std::make_unique<PRETTIFIED_FILE_OUTPUTFORMATTER>( oldFn.GetFullPath() );
341 formatter->Print(
")" );
353 if( symbolsByFile.find( deadFile ) == symbolsByFile.end() && wxFileExists( deadFile ) )
355 wxRemoveFile( deadFile );
368 const wxString& aLibName,
bool aIncludeData )
370 wxCHECK_RET( aSymbol,
"Invalid LIB_SYMBOL pointer." );
380 std::vector<SCH_FIELD*> orderedFields;
384 if( !aLibName.IsEmpty() )
390 wxCHECK2( unitId.
Parse( aLibName ) < 0, );
397 aFormatter.
Print(
"(symbol %s",
name.c_str() );
400 aFormatter.
Print(
"(power global)" );
402 aFormatter.
Print(
"(power local)" );
410 aFormatter.
Print(
"(body_styles " );
414 aFormatter.
Print(
"demorgan" );
419 aFormatter.
Print(
"%s ", aFormatter.
Quotew( bodyStyle ).c_str() );
422 aFormatter.
Print(
")" );
426 aFormatter.
Print(
"(pin_numbers (hide yes))" );
431 aFormatter.
Print(
"(pin_names" );
435 aFormatter.
Print(
"(offset %s)",
443 aFormatter.
Print(
")" );
458 aFormatter.
Print(
"(jumper_pin_groups" );
462 aFormatter.
Print(
"(" );
464 for(
const wxString& padName :
group.GetNames() )
465 aFormatter.
Print(
"%s ", aFormatter.
Quotew( padName ).c_str() );
467 aFormatter.
Print(
")" );
470 aFormatter.
Print(
")" );
501 aFormatter.
Print(
"(symbol %s_%d_%d\"",
510 aFormatter.
Print(
"(unit_name %s)", aFormatter.
Quotes(
name ).c_str() );
520 std::multiset<
SCH_ITEM*,
decltype( cmp )> save_map( cmp );
522 for(
SCH_ITEM* item : unit.m_items )
523 save_map.insert( item );
528 aFormatter.
Print(
")" );
538 std::shared_ptr<LIB_SYMBOL> parent = aSymbol->
GetParent().lock();
551 if( parentName.IsEmpty() && parent )
552 parentName = parent->GetName();
554 aFormatter.
Print(
"(symbol %s (extends %s)",
556 aFormatter.
Quotew( parentName ).c_str() );
573 aFormatter.
Print(
")" );
580 wxCHECK_RET( aSymbol,
"Invalid LIB_SYMBOL pointer." );
592 if( !fpFilters.IsEmpty() )
596 for(
const wxString&
filter : fpFilters )
604 tmp +=
" " + curr_filter;
617 wxCHECK_RET( aSymbol,
"Invalid LIB_SYMBOL pointer." );
623 if( !associations.empty() )
625 aFormatter.
Print(
"(associated_footprints" );
629 aFormatter.
Print(
"(footprint %s",
630 aFormatter.
Quotew( assoc.m_FootprintLibId.GetUniStringLibId() ).c_str() );
632 if( !assoc.m_MapName.IsEmpty() )
633 aFormatter.
Print(
"(map %s)", aFormatter.
Quotew( assoc.m_MapName ).c_str() );
635 aFormatter.
Print(
")" );
638 aFormatter.
Print(
")" );
645 aFormatter.
Print(
"(pin_maps" );
647 for(
const PIN_MAP& map : maps )
649 aFormatter.
Print(
"(pin_map %s", aFormatter.
Quotew( map.GetName() ).c_str() );
653 aFormatter.
Print(
"(entry %s %s)",
654 aFormatter.
Quotew( entry.m_PinNumber ).c_str(),
655 aFormatter.
Quotew( entry.m_PadNumber ).c_str() );
658 aFormatter.
Print(
")" );
661 aFormatter.
Print(
")" );
668 wxCHECK_RET( aItem,
"Invalid SCH_ITEM pointer." );
670 switch( aItem->
Type() )
683 formatArc( &aFormatter, shape, isPrivate, stroke, fillMode, fillColor,
true );
687 formatCircle( &aFormatter, shape, isPrivate, stroke, fillMode, fillColor,
true );
691 formatRect( &aFormatter, shape, isPrivate, stroke, fillMode, fillColor,
true );
695 formatBezier(&aFormatter, shape, isPrivate, stroke, fillMode, fillColor,
true );
699 formatPoly( &aFormatter, shape, isPrivate, stroke, fillMode, fillColor,
true );
703 formatEllipse( &aFormatter, shape, isPrivate, stroke, fillMode, fillColor,
true );
707 formatEllipseArc( &aFormatter, shape, isPrivate, stroke, fillMode, fillColor,
true );
737 wxCHECK_RET( aField && aField->
Type() ==
SCH_FIELD_T,
"Invalid SCH_FIELD object." );
739 wxString fieldName = aField->
GetName();
744 aFormatter.
Print(
"(property %s %s %s (at %s %s %s)",
746 aFormatter.
Quotew( fieldName ).c_str(),
759 aField->
Format( &aFormatter, 0 );
761 aFormatter.
Print(
")" );
767 wxCHECK_RET( aPin && aPin->
Type() ==
SCH_PIN_T,
"Invalid SCH_PIN object." );
771 aFormatter.
Print(
"(pin %s %s (at %s %s %s) (length %s)",
783 aFormatter.
Print(
"(name %s (effects (font (size %s %s))))",
788 aFormatter.
Print(
"(number %s (effects (font (size %s %s))))",
794 for(
const std::pair<const wxString, SCH_PIN::ALT>& alt : aPin->
GetAlternates() )
799 if( alt.second.m_Name.IsEmpty() )
802 aFormatter.
Print(
"(alternate %s %s %s)",
803 aFormatter.
Quotew( alt.second.m_Name ).c_str(),
809 aFormatter.
Print(
")" );
815 wxCHECK_RET( aText && aText->
Type() ==
SCH_TEXT_T,
"Invalid SCH_TEXT object." );
817 aFormatter.
Print(
"(text %s %s (at %s %s %d)",
824 aText->EDA_TEXT::Format( &aFormatter, 0 );
826 aFormatter.
Print(
")" );
832 wxCHECK_RET( aTextBox && aTextBox->
Type() ==
SCH_TEXTBOX_T,
"Invalid SCH_TEXTBOX object." );
834 aFormatter.
Print(
"(text_box %s %s",
841 aFormatter.
Print(
"(at %s %s %s) (size %s %s) (margins %s %s %s %s)",
854 aTextBox->EDA_TEXT::Format( &aFormatter, 0 );
856 aFormatter.
Print(
")" );
862 LIB_SYMBOL_MAP::iterator it =
m_symbols.find( aSymbolName );
869 auto recordSourceFileForDeletion = [
this](
const wxString& aName )
884 recordSourceFileForDeletion( aSymbolName );
889 LIB_SYMBOL_MAP::iterator it1 =
m_symbols.begin();
893 if( it1->second->IsDerived()
894 && it1->second->GetParent().lock() == rootSymbol->
SharedPtr() )
896 recordSourceFileForDeletion( it1->first );
910 recordSourceFileForDeletion( aSymbolName );
925 if( symbol->GetParentName().IsEmpty() )
928 auto it =
m_symbols.find( symbol->GetParentName() );
934 error.Printf(
_(
"No parent for extended symbol %s found in library '%s'" ),
939 symbol->SetParent( it->second );
946 aFormatter.
Print(
"(kicad_symbol_lib (version %d) (generator \"kicad_symbol_editor\") "
947 "(generator_version \"%s\")",
constexpr EDA_IU_SCALE schIUScale
wxString GetMajorMinorVersion()
Get only the major and minor version in a string major.minor.
int AsTenthsOfADegree() const
KICAD_T Type() const
Returns the type of object.
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
FILL_T GetFillMode() const
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
COLOR4D GetFillColor() const
wxString SHAPE_T_asString() const
virtual const wxString & GetText() const
Return the string associated with the text object.
virtual bool IsVisible() const
virtual void Format(OUTPUTFORMATTER *aFormatter, int aControlBits) const
Output the object to aFormatter in s-expression form.
virtual void SetVisible(bool aVisible)
virtual EDA_ANGLE GetTextAngle() const
void WriteEmbeddedFiles(OUTPUTFORMATTER &aOut, bool aWriteData) const
Output formatter for the embedded files.
void ClearEmbeddedFonts()
Remove all embedded fonts from the collection.
const std::map< wxString, std::shared_ptr< EMBEDDED_FILE > > & EmbeddedFileMap() const
Provide an iterable view of the file collection.
bool GetAreFontsEmbedded() const
A LINE_READER that reads from an open file.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
Represents an (ordered) list of JUMPER_GROUP objects.
const std::vector< JUMPER_GROUP > & GetAll() const
Represents a group of jumper pins or pads, keyed by name.
A color representation with 4 components: red, green, blue, alpha.
A logical library item identifier and consists of various portions much like a URI.
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
const UTF8 & GetLibItemName() const
Define a library symbol object.
const wxString & GetRawKeyWords() const
Return only this symbol's keywords, without inheriting from its parent.
const LIB_ID & GetLibId() const override
std::weak_ptr< LIB_SYMBOL > & GetParent()
void GetFields(std::vector< SCH_FIELD * > &aList, bool aVisibleOnly=false) const override
Populate a std::vector with SCH_FIELDs, sorted in ordinal order.
bool UnitsLocked() const
Check whether symbol units are interchangeable.
bool IsRoot() const override
For symbols derived from other symbols, IsRoot() indicates no derivation.
std::vector< struct LIB_SYMBOL_UNIT > GetUnitDrawItems()
Return a list of SCH_ITEM objects separated by unit and convert number.
std::map< int, wxString > & GetUnitDisplayNames()
bool IsMultiBodyStyle() const override
JUMPER_GROUP_SET & JumperPinGroups()
Each jumper pin group is a set of pin numbers that should be treated as internally connected.
wxString GetName() const override
bool IsLocalPower() const override
wxArrayString GetFPFilters() const
std::shared_ptr< LIB_SYMBOL > SharedPtr() const
http://www.boost.org/doc/libs/1_55_0/libs/smart_ptr/sp_techniques.html#weak_without_shared.
const std::vector< wxString > & GetBodyStyleNames() const
bool HasDeMorganBodyStyles() const override
const PIN_MAP_SET & GetPinMaps() const
Pin-to-pad mapping (issue #2282).
EMBEDDED_FILES * GetEmbeddedFiles() override
bool IsGlobalPower() const override
const wxString & GetParentName() const
unsigned GetInheritanceDepth() const
Get the number of parents for this symbol.
bool GetDuplicatePinNumbersAreJumpers() const
void EmbedFonts() override
const std::vector< ASSOCIATED_FOOTPRINT > & GetAssociatedFootprints() const
const std::vector< PIN_MAP > & GetAll() const
VECTOR2I GetPosition() const override
virtual const wxString & GetText() const override
Return the string associated with the text object.
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
bool CanAutoplace() const
void SetText(const wxString &aText) override
int m_fileFormatVersionAtLoad
static void saveSymbolDrawItem(SCH_ITEM *aItem, OUTPUTFORMATTER &aFormatter)
SCH_IO_KICAD_SEXPR_LIB_CACHE(const wxString &aLibraryPath)
static void saveDcmInfoAsFields(LIB_SYMBOL *aSymbol, OUTPUTFORMATTER &aFormatter)
static void savePinMapData(LIB_SYMBOL *aSymbol, OUTPUTFORMATTER &aFormatter)
Write the symbol's own (non-inherited) pin maps and associated footprints (issue #2282).
virtual ~SCH_IO_KICAD_SEXPR_LIB_CACHE()
static void SaveSymbol(LIB_SYMBOL *aSymbol, OUTPUTFORMATTER &aFormatter, const wxString &aLibName=wxEmptyString, bool aIncludeData=true)
static void saveTextBox(SCH_TEXTBOX *aTextBox, OUTPUTFORMATTER &aFormatter)
std::set< wxString > m_pendingFileDeletes
bool isLibraryPathValid() const
static void saveField(SCH_FIELD *aField, OUTPUTFORMATTER &aFormatter)
void formatLibraryHeader(OUTPUTFORMATTER &aFormatter)
void DeleteSymbol(const wxString &aName) override
static void savePin(SCH_PIN *aPin, OUTPUTFORMATTER &aFormatter)
static void saveText(SCH_TEXT *aText, OUTPUTFORMATTER &aFormatter)
void SetFileFormatVersionAtLoad(int aVersion)
void Save(const std::optional< bool > &aOpt=std::nullopt) override
Save the entire library to file m_libFileName;.
void updateParentSymbolLinks()
Update the parent symbol links for derived symbols.
Object to parser s-expression symbol library and schematic file formats.
const std::vector< wxString > & GetParseWarnings() const
Return any non-fatal parse warnings that occurred during parsing.
int GetParsedRequiredVersion() const
void ParseLib(LIB_SYMBOL_MAP &aSymbolLibMap)
void SetParseError(bool aHasError=true)
Set the parse error state.
bool HasParseError() const
wxFileName GetRealFile() const
long long GetLibModificationTime()
std::map< wxString, wxString > m_symbolSourceFiles
For folder-based libraries, track which source file each symbol was loaded from.
SCH_IO_LIB_CACHE(const wxString &aLibraryPath)
void IncrementModifyHash()
Base class for any item which can be embedded within the SCHEMATIC container class,...
wxString GetClass() const override
Return the class name.
int GetNumberTextSize() const
const std::map< wxString, ALT > & GetAlternates() const
const wxString & GetName() const
PIN_ORIENTATION GetOrientation() const
VECTOR2I GetPosition() const override
int GetNameTextSize() const
const wxString & GetNumber() const
GRAPHIC_PINSHAPE GetShape() const
ELECTRICAL_PINTYPE GetType() const
STROKE_PARAMS GetStroke() const override
int GetMarginBottom() const
int GetMarginLeft() const
int GetMarginRight() const
VECTOR2I GetPosition() const override
Simple container to manage line stroke parameters.
void Format(OUTPUTFORMATTER *out, const EDA_IU_SCALE &aIuScale) const
bool GetExcludedFromPosFiles(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
int GetPinNameOffset() const
virtual bool GetExcludedFromBOM(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
virtual bool GetShowPinNames() const
bool GetExcludedFromBoard(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
virtual bool GetExcludedFromSim(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
virtual bool GetShowPinNumbers() const
#define DEFAULT_PIN_NAME_OFFSET
The offset of the pin name string from the end of the pin in mils.
#define IS_CHANGED
Item was edited, and modified.
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
#define THROW_IO_ERRORF(msg,...)
static const std::string KiCadSymbolLibFileExtension
const wxChar *const traceSchLegacyPlugin
Flag to enable legacy schematic plugin debug output.
This file contains miscellaneous commonly used macros and functions.
#define UNIMPLEMENTED_FOR(type)
KICOMMON_API std::string FormatAngle(const EDA_ANGLE &aAngle)
Convert aAngle from board units to a string appropriate for writing to file.
KICOMMON_API std::string FormatInternalUnits(const EDA_IU_SCALE &aIuScale, int aValue, EDA_DATA_TYPE aDataType=EDA_DATA_TYPE::DISTANCE)
Converts aValue from internal units to a string appropriate for writing to file.
#define SEXPR_SYMBOL_LIB_FILE_VERSION
This file contains the file format version information for the s-expression schematic and symbol libr...
EDA_ANGLE getPinAngle(PIN_ORIENTATION aOrientation)
void formatArc(OUTPUTFORMATTER *aFormatter, EDA_SHAPE *aArc, bool aIsPrivate, const STROKE_PARAMS &aStroke, FILL_T aFillMode, const COLOR4D &aFillColor, bool aInvertY, const KIID &aUuid, bool aLocked)
void formatEllipseArc(OUTPUTFORMATTER *aFormatter, EDA_SHAPE *aEllipseArc, bool aIsPrivate, const STROKE_PARAMS &aStroke, FILL_T aFillMode, const COLOR4D &aFillColor, bool aInvertY, const KIID &aUuid, bool aLocked)
void formatCircle(OUTPUTFORMATTER *aFormatter, EDA_SHAPE *aCircle, bool aIsPrivate, const STROKE_PARAMS &aStroke, FILL_T aFillMode, const COLOR4D &aFillColor, bool aInvertY, const KIID &aUuid, bool aLocked)
void formatRect(OUTPUTFORMATTER *aFormatter, EDA_SHAPE *aRect, bool aIsPrivate, const STROKE_PARAMS &aStroke, FILL_T aFillMode, const COLOR4D &aFillColor, bool aInvertY, const KIID &aUuid, bool aLocked)
const char * getPinElectricalTypeToken(ELECTRICAL_PINTYPE aType)
void formatBezier(OUTPUTFORMATTER *aFormatter, EDA_SHAPE *aBezier, bool aIsPrivate, const STROKE_PARAMS &aStroke, FILL_T aFillMode, const COLOR4D &aFillColor, bool aInvertY, const KIID &aUuid, bool aLocked)
void formatEllipse(OUTPUTFORMATTER *aFormatter, EDA_SHAPE *aEllipse, bool aIsPrivate, const STROKE_PARAMS &aStroke, FILL_T aFillMode, const COLOR4D &aFillColor, bool aInvertY, const KIID &aUuid, bool aLocked)
void formatPoly(OUTPUTFORMATTER *aFormatter, EDA_SHAPE *aPolyLine, bool aIsPrivate, const STROKE_PARAMS &aStroke, FILL_T aFillMode, const COLOR4D &aFillColor, bool aInvertY, const KIID &aUuid, bool aLocked)
void formatFill(OUTPUTFORMATTER *aFormatter, FILL_T aFillMode, const COLOR4D &aFillColor)
Fill token formatting helper.
const char * getPinShapeToken(GRAPHIC_PINSHAPE aShape)
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
One symbol-pin to footprint-pad mapping inside a PIN_MAP.
wxString GetDefaultFieldName(FIELD_T aFieldId, TRANSLATION aTranslation)
Return a default symbol field name for a mandatory field type.
@ USER
The field ID hasn't been set yet; field is invalid.
wxLogTrace helper definitions.
VECTOR2< int32_t > VECTOR2I