Clean up Altium special string handling
1) Fix a couple of bugs in case processing 2) Make case processing more explicit to prevent more (1) 3) Move label processing to AltiumSpecialStringsToKiCadVariables 4) Strip double-quotes from special strings (and add test cases) 5) Change PROJECTNAME to just filename, not full path 6) PROJECTREV and REVISION are two different things 7) Add support for Altium's Application_BuildNumber 8) Fix some issues in trimming spaces around special strings
This commit is contained in:
parent
65c7958293
commit
a4263ebce5
|
@ -78,8 +78,8 @@ wxString AltiumPropertyToKiCadString( const wxString& aString )
|
|||
|
||||
|
||||
// https://www.altium.com/documentation/altium-designer/sch-obj-textstringtext-string-ad#!special-strings
|
||||
wxString AltiumSpecialStringsToKiCadVariables( const wxString& aString,
|
||||
const altium_override_map_t& aOverrides )
|
||||
wxString AltiumSpecialStringsToKiCadVariables( const wxString& aString,
|
||||
const std::map<wxString, wxString>& aOverrides )
|
||||
{
|
||||
if( aString.IsEmpty() || aString.at( 0 ) != '=' )
|
||||
{
|
||||
|
@ -112,23 +112,25 @@ wxString AltiumSpecialStringsToKiCadVariables( const wxString& aStr
|
|||
}
|
||||
else
|
||||
{
|
||||
wxString specialString = aString.substr( start, delimiter - start ).Trim( true );
|
||||
wxString specialString = aString.substr( start, delimiter - start ).Trim().Trim( false );
|
||||
|
||||
if( specialString.StartsWith( "\"" ) && specialString.EndsWith( "\"" ) )
|
||||
specialString = specialString.Mid( 1, specialString.Length() - 2 );
|
||||
|
||||
if( !specialString.IsEmpty() )
|
||||
{
|
||||
// Note: Altium variable references are case-insensitive. KiCad matches
|
||||
// case-senstive OR to all-upper-case, so make the references all-upper-case.
|
||||
specialString.UpperCase();
|
||||
|
||||
auto overrideIt = aOverrides.find( specialString );
|
||||
|
||||
if( overrideIt != aOverrides.end() )
|
||||
{
|
||||
result += overrideIt->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Note: Altium variable references are case-insensitive. KiCad matches
|
||||
// case-senstive OR to all-upper-case, so make the references all-upper-case.
|
||||
result += wxString::Format( wxT( "${%s}" ), specialString.Upper() );
|
||||
}
|
||||
specialString = overrideIt->second;
|
||||
|
||||
result += wxString::Format( wxT( "${%s}" ), specialString );
|
||||
}
|
||||
|
||||
start = delimiter + 1;
|
||||
}
|
||||
} while( delimiter != wxString::npos );
|
||||
|
|
|
@ -32,22 +32,11 @@
|
|||
|
||||
#include <iostream>
|
||||
|
||||
struct CASE_INSENSITIVE_COMPARATOR
|
||||
{
|
||||
bool operator()( const wxString& s1, const wxString& s2 ) const
|
||||
{
|
||||
// Altium variables are case insensitive.
|
||||
return s1.CmpNoCase( s2 ) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<wxString, wxString, CASE_INSENSITIVE_COMPARATOR> altium_override_map_t;
|
||||
|
||||
LIB_ID AltiumToKiCadLibID( wxString aLibName, wxString aLibReference );
|
||||
|
||||
wxString AltiumPropertyToKiCadString( const wxString& aString );
|
||||
|
||||
wxString AltiumSpecialStringsToKiCadVariables( const wxString& aString,
|
||||
const altium_override_map_t& aOverrides );
|
||||
wxString AltiumSpecialStringsToKiCadVariables( const wxString& aString,
|
||||
const std::map<wxString, wxString>& aOverrides );
|
||||
|
||||
#endif //ALTIUM_PARSER_UTILS_H
|
||||
|
|
|
@ -786,46 +786,38 @@ void SCH_ALTIUM_PLUGIN::ParseLabel( const std::map<wxString, wxString>& aPropert
|
|||
{
|
||||
ASCH_LABEL elem( aProperties );
|
||||
|
||||
// TODO: general text variable support
|
||||
|
||||
if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
|
||||
{
|
||||
if( elem.text.StartsWith( "=" ) )
|
||||
{
|
||||
wxString token = elem.text.AfterFirst( '=' ).Upper();
|
||||
std::map<wxString, wxString> variableMap = {
|
||||
{ "APPLICATION_BUILDNUMBER", "KICAD_VERSION" },
|
||||
{ "SHEETNUMBER", "#" },
|
||||
{ "SHEETTOTAL", "##" },
|
||||
{ "TITLE", "TITLE" }, // 1:1 maps are sort of useless, but it makes it
|
||||
{ "REVISION", "REVISION" }, // easier to see that the list is complete
|
||||
{ "DATE", "ISSUE_DATE" },
|
||||
{ "CURRENTDATE", "CURRENT_DATE" },
|
||||
{ "COMPANYNAME", "COMPANY" },
|
||||
{ "DOCUMENTNAME", "FILENAME" },
|
||||
{ "PROJECTNAME", "PROJECTNAME" },
|
||||
};
|
||||
|
||||
if( token == "SHEETNUMBER" ) elem.text = "${#}";
|
||||
else if( token == "SHEETTOTAL" ) elem.text = "${##}";
|
||||
else if( token == "TITLE" ) elem.text = "${TITLE}";
|
||||
else if( token == "PROJECTREV" ) elem.text = "${REVISION}";
|
||||
else if( token == "DATE" ) elem.text = "${ISSUE_DATE}";
|
||||
else if( token == "CURRENTDATE" ) elem.text = "${CURRENT_DATE}";
|
||||
else if( token == "COMPANYNAME" ) elem.text = "${COMPANY}";
|
||||
else if( token == "DOCUMENTNAME" ) elem.text = "${FILENAME}";
|
||||
else if( token == "PROJECTNAME" ) elem.text = "${PROJECTNAME}";
|
||||
else
|
||||
{
|
||||
if( m_schematic->Prj().GetTextVars().count( token ) )
|
||||
elem.text = wxString::Format( "${%s}", token );
|
||||
}
|
||||
}
|
||||
wxString kicadText = AltiumSpecialStringsToKiCadVariables( elem.text, variableMap );
|
||||
SCH_TEXT* textItem = new SCH_TEXT( elem.location + m_sheetOffset, kicadText );
|
||||
|
||||
SCH_TEXT* text = new SCH_TEXT( elem.location + m_sheetOffset, elem.text );
|
||||
|
||||
SetEdaTextJustification( text, elem.justification );
|
||||
SetEdaTextJustification( textItem, elem.justification );
|
||||
|
||||
size_t fontId = static_cast<int>( elem.fontId );
|
||||
|
||||
if( m_altiumSheet && fontId > 0 && fontId <= m_altiumSheet->fonts.size() )
|
||||
{
|
||||
const ASCH_SHEET_FONT& font = m_altiumSheet->fonts.at( fontId - 1 );
|
||||
text->SetItalic( font.italic );
|
||||
text->SetBold( font.bold );
|
||||
text->SetTextSize( { font.size / 2, font.size / 2 } );
|
||||
textItem->SetItalic( font.italic );
|
||||
textItem->SetBold( font.bold );
|
||||
textItem->SetTextSize( { font.size / 2, font.size / 2 } );
|
||||
}
|
||||
|
||||
text->SetFlags( IS_NEW );
|
||||
m_currentSheet->GetScreen()->Append( text );
|
||||
textItem->SetFlags(IS_NEW );
|
||||
m_currentSheet->GetScreen()->Append( textItem );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -841,23 +833,23 @@ void SCH_ALTIUM_PLUGIN::ParseLabel( const std::map<wxString, wxString>& aPropert
|
|||
}
|
||||
|
||||
SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
|
||||
LIB_TEXT* text = new LIB_TEXT( libSymbolIt->second );
|
||||
libSymbolIt->second->AddDrawItem( text );
|
||||
LIB_TEXT* textItem = new LIB_TEXT( libSymbolIt->second );
|
||||
libSymbolIt->second->AddDrawItem( textItem );
|
||||
|
||||
text->SetUnit( elem.ownerpartid );
|
||||
textItem->SetUnit( elem.ownerpartid );
|
||||
|
||||
text->SetPosition( GetRelativePosition( elem.location + m_sheetOffset, symbol ) );
|
||||
text->SetText( elem.text );
|
||||
SetEdaTextJustification( text, elem.justification );
|
||||
textItem->SetPosition( GetRelativePosition( elem.location + m_sheetOffset, symbol ) );
|
||||
textItem->SetText( elem.text );
|
||||
SetEdaTextJustification( textItem, elem.justification );
|
||||
|
||||
size_t fontId = static_cast<int>( elem.fontId );
|
||||
|
||||
if( m_altiumSheet && fontId > 0 && fontId <= m_altiumSheet->fonts.size() )
|
||||
{
|
||||
const ASCH_SHEET_FONT& font = m_altiumSheet->fonts.at( fontId - 1 );
|
||||
text->SetItalic( font.italic );
|
||||
text->SetBold( font.bold );
|
||||
text->SetTextSize( { font.size / 2, font.size / 2 } );
|
||||
textItem->SetItalic( font.italic );
|
||||
textItem->SetBold( font.bold );
|
||||
textItem->SetTextSize( { font.size / 2, font.size / 2 } );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2294,9 +2286,9 @@ void SCH_ALTIUM_PLUGIN::ParseParameter( const std::map<wxString, wxString>& aPro
|
|||
ASCH_PARAMETER elem( aProperties );
|
||||
|
||||
// TODO: fill in replacements from variant, sheet and project
|
||||
altium_override_map_t stringReplacement = {
|
||||
{ "Comment", "${VALUE}" },
|
||||
{ "Value", "${Altium_Value}" },
|
||||
std::map<wxString, wxString> variableMap = {
|
||||
{ "COMMENT", "VALUE" },
|
||||
{ "VALUE", "ALTIUM_VALUE" },
|
||||
};
|
||||
|
||||
if( elem.ownerindex <= 0 && elem.ownerpartid == ALTIUM_COMPONENT_NONE )
|
||||
|
@ -2334,8 +2326,6 @@ void SCH_ALTIUM_PLUGIN::ParseParameter( const std::map<wxString, wxString>& aPro
|
|||
{
|
||||
m_schematic->Prj().GetTextVars()[ paramName ] = elem.text;
|
||||
}
|
||||
|
||||
// TODO: handle parameters in labels
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2354,19 +2344,23 @@ void SCH_ALTIUM_PLUGIN::ParseParameter( const std::map<wxString, wxString>& aPro
|
|||
|
||||
SCH_FIELD* field = nullptr;
|
||||
|
||||
if( elem.name == "Comment" )
|
||||
if( elem.name.Upper() == "COMMENT" )
|
||||
{
|
||||
field = symbol->GetField( VALUE_FIELD );
|
||||
field->SetPosition( position );
|
||||
}
|
||||
else
|
||||
{
|
||||
int fieldIdx = symbol->GetFieldCount();
|
||||
wxString fieldName = elem.name.IsSameAs( "Value", false ) ? "Altium_Value" : elem.name;
|
||||
int fieldIdx = symbol->GetFieldCount();
|
||||
wxString fieldName = elem.name.Upper();
|
||||
|
||||
if( fieldName == "VALUE" )
|
||||
fieldName = "ALTIUM_VALUE";
|
||||
|
||||
field = symbol->AddField( { position, fieldIdx, symbol, fieldName } );
|
||||
}
|
||||
|
||||
wxString kicadText = AltiumSpecialStringsToKiCadVariables( elem.text, stringReplacement );
|
||||
wxString kicadText = AltiumSpecialStringsToKiCadVariables( elem.text, variableMap );
|
||||
field->SetText( kicadText );
|
||||
|
||||
field->SetVisible( !elem.isHidden );
|
||||
|
@ -2384,7 +2378,8 @@ void SCH_ALTIUM_PLUGIN::ParseParameter( const std::map<wxString, wxString>& aPro
|
|||
}
|
||||
|
||||
|
||||
void SCH_ALTIUM_PLUGIN::ParseImplementationList( int aIndex, const std::map<wxString, wxString>& aProperties )
|
||||
void SCH_ALTIUM_PLUGIN::ParseImplementationList( int aIndex,
|
||||
const std::map<wxString, wxString>& aProperties )
|
||||
{
|
||||
ASCH_IMPLEMENTATION_LIST elem( aProperties );
|
||||
|
||||
|
@ -2399,20 +2394,22 @@ void SCH_ALTIUM_PLUGIN::ParseImplementation( const std::map<wxString, wxString>&
|
|||
// Only get footprint, currently assigned only
|
||||
if( ( elem.type == "PCBLIB" ) && ( elem.isCurrent ) )
|
||||
{
|
||||
const auto& implementationOwnerindexIt = m_altiumImplementationList.find( elem.ownerindex );
|
||||
if( implementationOwnerindexIt == m_altiumImplementationList.end() ) {
|
||||
m_reporter->Report( wxString::Format( _( "Implementation list's owner (%d) not found." ),
|
||||
const auto& implementationOwnerIt = m_altiumImplementationList.find( elem.ownerindex );
|
||||
|
||||
if( implementationOwnerIt == m_altiumImplementationList.end() )
|
||||
{
|
||||
m_reporter->Report( wxString::Format( _( "Implementation's owner (%d) not found." ),
|
||||
elem.ownerindex ),
|
||||
RPT_SEVERITY_ERROR );
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& libSymbolIt = m_libSymbols.find( implementationOwnerindexIt->second );
|
||||
const auto& libSymbolIt = m_libSymbols.find( implementationOwnerIt->second );
|
||||
|
||||
if( libSymbolIt == m_libSymbols.end() )
|
||||
{
|
||||
m_reporter->Report( wxString::Format( _( "Footprint's owner (%d) not found." ),
|
||||
implementationOwnerindexIt->second ),
|
||||
implementationOwnerIt->second ),
|
||||
RPT_SEVERITY_ERROR );
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -147,7 +147,7 @@ bool SCHEMATIC::ResolveTextVar( wxString* token, int aDepth ) const
|
|||
}
|
||||
else if( token->IsSameAs( wxT( "PROJECTNAME" ) ) )
|
||||
{
|
||||
*token = Prj().GetProjectFullName();
|
||||
*token = Prj().GetProjectName();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,9 +44,9 @@ BOOST_FIXTURE_TEST_SUITE( AltiumParserUtils, ALTIUM_PARSER_UTILS_FIXTURE )
|
|||
|
||||
struct SPECIAL_STRINGS_TO_KICAD
|
||||
{
|
||||
wxString input;
|
||||
wxString exp_result;
|
||||
altium_override_map_t override;
|
||||
wxString input;
|
||||
wxString exp_result;
|
||||
std::map<wxString, wxString> override;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -77,24 +77,20 @@ static const std::vector<SPECIAL_STRINGS_TO_KICAD> special_string_to_kicad_prope
|
|||
{ "${A}", "${A}", {} }, // TODO: correct substitution
|
||||
// Simple special strings
|
||||
{ "=A", "${A}", {} },
|
||||
{ "=A", "C", { { "A", "C" } } },
|
||||
{ "=A", "${C}", { { "A", "${C}" } } },
|
||||
{ "=A", "${C}", { { "A", "C" } } },
|
||||
{ "=A_B", "${A_B}", {} },
|
||||
// Combined special strings
|
||||
{ "=A+B", "${A}${B}", {} },
|
||||
{ "=A+B", "${A}${B}", {} },
|
||||
{ "=A+B", "C${B}", { { "A", "C" } } },
|
||||
{ "=A+B", "CD", { { "A", "C" }, { "B", "D" } } },
|
||||
{ "=A+B", "${C}${B}", { { "A", "C" } } },
|
||||
{ "=A+B", "${C}${D}", { { "A", "C" }, { "B", "D" } } },
|
||||
// Case insensitive special strings
|
||||
{ "=A", "C", { { "a", "C" } } },
|
||||
{ "=a", "C", { { "A", "C" } } },
|
||||
{ "=AB", "C", { { "Ab", "C" } } },
|
||||
{ "=AB", "C", { { "aB", "C" } } },
|
||||
{ "=AB", "C", { { "ab", "C" } } },
|
||||
{ "=AB", "C", { { "AB", "C" } } },
|
||||
{ "=aB", "C", { { "Ab", "C" } } },
|
||||
{ "=Ab", "C", { { "aB", "C" } } },
|
||||
{ "=ab", "C", { { "AB", "C" } } },
|
||||
{ "=A", "${C}", { { "A", "C" } } },
|
||||
{ "=a", "${C}", { { "A", "C" } } },
|
||||
{ "=AB", "${C}", { { "AB", "C" } } },
|
||||
{ "=aB", "${C}", { { "AB", "C" } } },
|
||||
{ "=Ab", "${C}", { { "AB", "C" } } },
|
||||
{ "=ab", "${C}", { { "AB", "C" } } },
|
||||
// Special strings with text
|
||||
{ "='A'", "A", {} },
|
||||
{ "='This is a long text with spaces'", "This is a long text with spaces", {} },
|
||||
|
@ -108,6 +104,10 @@ static const std::vector<SPECIAL_STRINGS_TO_KICAD> special_string_to_kicad_prope
|
|||
{ "='A'+' '", "A ", {} },
|
||||
{ "=' '+'B'", " B", {} },
|
||||
{ "='A'+B", "A${B}", {} },
|
||||
{ "='A'+\"B\"", "A${B}", {} },
|
||||
{ "='A' + \"B\"", "A${B}", {} },
|
||||
{ "=\"A\"+'B'", "${A}B", {} },
|
||||
{ "=\"A\" + 'B'", "${A}B", {} },
|
||||
{ "=A+'B'", "${A}B", {} },
|
||||
{ "=A+' '+B", "${A} ${B}", {} },
|
||||
{ "='A'+B+'C'+D", "A${B}C${D}", {} },
|
||||
|
|
Loading…
Reference in New Issue