KiCad PCB EDA Suite
Loading...
Searching...
No Matches
altium_project_variants.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
25
26#include <wx/fileconf.h>
27#include <wx/log.h>
28
29
30static ALTIUM_VARIANT_ENTRY ParseVariationString( const wxString& aValue )
31{
33
34 for( const wxString& token : wxSplit( aValue, '|' ) )
35 {
36 int eqPos = token.Find( '=' );
37
38 if( eqPos == wxNOT_FOUND )
39 continue;
40
41 wxString key = token.Left( eqPos ).Trim().Trim( false );
42 wxString val = token.Mid( eqPos + 1 ).Trim().Trim( false );
43
44 if( key.CmpNoCase( wxS( "Designator" ) ) == 0 )
45 {
46 entry.designator = val;
47 }
48 else if( key.CmpNoCase( wxS( "UniqueId" ) ) == 0 )
49 {
50 entry.uniqueId = val;
51 }
52 else if( key.CmpNoCase( wxS( "Kind" ) ) == 0 )
53 {
54 long k = 0;
55 val.ToLong( &k );
56 entry.kind = static_cast<int>( k );
57 }
58 else if( key.CmpNoCase( wxS( "AlternatePart" ) ) == 0 )
59 {
60 if( val.empty() )
61 continue;
62
63 // AlternatePart contains sub-fields in the same pipe-delimited format, but since
64 // it appears at the end of the line, the remaining tokens are its sub-fields.
65 // We've already split on '|', so we just keep accumulating from here.
66 // However, wxSplit already split everything. The AlternatePart sub-fields are the
67 // remaining tokens after this one. We handle this below after the loop.
68 }
69 }
70
71 // Parse AlternatePart sub-fields. In the raw line, AlternatePart= is followed by
72 // pipe-separated key=value pairs that are part of the alternate part definition.
73 // Since we already split on '|', find the AlternatePart token and treat everything
74 // after it as sub-fields.
75 bool inAlternatePart = false;
76
77 for( const wxString& token : wxSplit( aValue, '|' ) )
78 {
79 int eqPos = token.Find( '=' );
80
81 if( eqPos == wxNOT_FOUND )
82 continue;
83
84 wxString key = token.Left( eqPos ).Trim().Trim( false );
85 wxString val = token.Mid( eqPos + 1 ).Trim().Trim( false );
86
87 if( key.CmpNoCase( wxS( "AlternatePart" ) ) == 0 )
88 {
89 inAlternatePart = true;
90
91 // The value after AlternatePart= might itself be the first sub-field value
92 // In practice it's typically empty for Kind=1, or a lib reference for Kind=0
93 if( !val.empty() )
94 entry.alternateFields[wxS( "LibReference" )] = val;
95
96 continue;
97 }
98
99 if( inAlternatePart && !val.empty() )
100 entry.alternateFields[key] = val;
101 }
102
103 return entry;
104}
105
106
107std::vector<ALTIUM_PROJECT_VARIANT> ParseAltiumProjectVariants( const wxString& aPrjPcbPath )
108{
109 std::vector<ALTIUM_PROJECT_VARIANT> variants;
110
111 wxFileConfig config( wxEmptyString, wxEmptyString, wxEmptyString, aPrjPcbPath,
112 wxCONFIG_USE_NO_ESCAPE_CHARACTERS );
113
114 wxString groupname;
115 long groupid;
116
117 for( bool more = config.GetFirstGroup( groupname, groupid ); more;
118 more = config.GetNextGroup( groupname, groupid ) )
119 {
120 if( !groupname.StartsWith( wxS( "ProjectVariant" ) ) )
121 continue;
122
123 wxString numStr = groupname.Mid( 14 );
124 long num;
125
126 if( !numStr.ToLong( &num ) )
127 continue;
128
130
131 pv.description = config.Read( groupname + wxS( "/Description" ), wxEmptyString );
132 pv.name = pv.description;
133
134 if( pv.name.empty() )
135 pv.name = groupname;
136
137 long variationCount = 0;
138 config.Read( groupname + wxS( "/VariationCount" ), &variationCount, 0 );
139
140 for( long vi = 1; vi <= variationCount; ++vi )
141 {
142 wxString key = wxString::Format( wxS( "%s/Variation%ld" ), groupname, vi );
143 wxString value = config.Read( key, wxEmptyString );
144
145 if( value.empty() )
146 continue;
147
149
150 if( !entry.designator.empty() )
151 pv.variations.push_back( std::move( entry ) );
152 }
153
154 if( !pv.variations.empty() )
155 variants.push_back( std::move( pv ) );
156 }
157
158 return variants;
159}
std::vector< ALTIUM_PROJECT_VARIANT > ParseAltiumProjectVariants(const wxString &aPrjPcbPath)
Parse all [ProjectVariantN] sections from an Altium .PrjPcb project file.
static ALTIUM_VARIANT_ENTRY ParseVariationString(const wxString &aValue)
A project-level assembly variant parsed from an Altium .PrjPcb file.
std::vector< ALTIUM_VARIANT_ENTRY > variations
A single component variation within an Altium project variant.
int kind
wxString uniqueId
wxString designator
std::map< wxString, wxString > alternateFields