From 4482b3baba26b5a2b17a192c3abc132ecc759461 Mon Sep 17 00:00:00 2001 From: Thomas Pointhuber Date: Sun, 14 Mar 2021 16:40:36 +0100 Subject: [PATCH] altium: Handle special strings and convert them into KiCad variables. Use Comment for VALUE. Fixes: https://gitlab.com/kicad/code/kicad/-/issues/6256 Fixes: https://gitlab.com/kicad/code/kicad/-/issues/7736 --- common/CMakeLists.txt | 1 + common/plugins/altium/altium_parser_utils.cpp | 80 +++++++++++++ common/plugins/altium/altium_parser_utils.h | 21 ++-- .../sch_plugins/altium/sch_altium_plugin.cpp | 18 +-- qa/common/CMakeLists.txt | 1 + .../altium/test_altium_parser_utils.cpp | 113 ++++++++++++++++++ 6 files changed, 213 insertions(+), 21 deletions(-) create mode 100644 common/plugins/altium/altium_parser_utils.cpp create mode 100644 qa/common/plugins/altium/test_altium_parser_utils.cpp diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 2ee448fbfe..f5939ea63f 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -284,6 +284,7 @@ set( PLOTTERS_CONTROL_SRCS set( PLUGINS_ALTIUM_SRCS plugins/altium/altium_parser.cpp + plugins/altium/altium_parser_utils.cpp ) set( PLUGINS_CADSTAR_SRCS diff --git a/common/plugins/altium/altium_parser_utils.cpp b/common/plugins/altium/altium_parser_utils.cpp new file mode 100644 index 0000000000..3739fba190 --- /dev/null +++ b/common/plugins/altium/altium_parser_utils.cpp @@ -0,0 +1,80 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2021 Thomas Pointhuber + * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "altium_parser_utils.h" + +#include +#include + + +LIB_ID AltiumToKiCadLibID( wxString aLibName, wxString aLibReference ) +{ + ReplaceIllegalFileNameChars( aLibName, '_' ); + ReplaceIllegalFileNameChars( aLibReference, '_' ); + + wxString key = !aLibName.empty() ? ( aLibName + ":" + aLibReference ) : aLibReference; + + LIB_ID libId; + libId.Parse( key, true ); + + return libId; +} + +// https://www.altium.com/documentation/altium-designer/sch-obj-textstringtext-string-ad#!special-strings +wxString AltiumSpecialStringsToKiCadVariables( const wxString& aString, + const std::map& aOverride ) +{ + if( aString.IsEmpty() || aString.at( 0 ) != '=' ) + { + return aString; + } + + wxString result; + + size_t start = 1; + size_t delemiter = 0; + do + { + delemiter = aString.find( "+", start ); + + wxString specialString = aString.substr( start, delemiter - start ).Trim( true ); + + if( !specialString.IsEmpty() ) + { + auto variableOverride = aOverride.find( specialString ); + if( variableOverride == aOverride.end() ) + { + result += wxString::Format( wxT( "${%s}" ), specialString ); + } + else + { + result += variableOverride->second; + } + } + + start = delemiter + 1; + } while( delemiter != wxString::npos ); + + return result; +} \ No newline at end of file diff --git a/common/plugins/altium/altium_parser_utils.h b/common/plugins/altium/altium_parser_utils.h index a9290c0b06..9714edd2a5 100644 --- a/common/plugins/altium/altium_parser_utils.h +++ b/common/plugins/altium/altium_parser_utils.h @@ -1,8 +1,8 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2020 Thomas Pointhuber - * Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2020-2021 Thomas Pointhuber + * Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -25,22 +25,15 @@ #ifndef ALTIUM_PARSER_UTILS_H #define ALTIUM_PARSER_UTILS_H +#include + #include #include -LIB_ID AltiumToKiCadLibID( wxString aLibName, wxString aLibReference ) -{ - ReplaceIllegalFileNameChars( aLibName, '_' ); - ReplaceIllegalFileNameChars( aLibReference, '_' ); - - wxString key = !aLibName.empty() ? ( aLibName + ":" + aLibReference ) : aLibReference; - - LIB_ID libId; - libId.Parse( key, true ); - - return libId; -} +LIB_ID AltiumToKiCadLibID( wxString aLibName, wxString aLibReference ); +wxString AltiumSpecialStringsToKiCadVariables( const wxString& aString, + const std::map& aOverride ); #endif //ALTIUM_PARSER_UTILS_H diff --git a/eeschema/sch_plugins/altium/sch_altium_plugin.cpp b/eeschema/sch_plugins/altium/sch_altium_plugin.cpp index d210ea6545..352bc0a0cd 100644 --- a/eeschema/sch_plugins/altium/sch_altium_plugin.cpp +++ b/eeschema/sch_plugins/altium/sch_altium_plugin.cpp @@ -2051,6 +2051,12 @@ void SCH_ALTIUM_PLUGIN::ParseParameter( const std::map& aPro { ASCH_PARAMETER elem( aProperties ); + // TODO: fill in replacements from variant, sheet and project + std::map stringReplacement = { + { "Comment", "${VALUE}" }, + { "Value", "${Altium_Value}" }, + }; + if( elem.ownerindex <= 0 && elem.ownerpartid == ALTIUM_COMPONENT_NONE ) { // This is some sheet parameter @@ -2088,7 +2094,7 @@ void SCH_ALTIUM_PLUGIN::ParseParameter( const std::map& aPro const wxPoint position = elem.location + m_sheetOffset; SCH_FIELD* field = nullptr; - if( elem.name == "Value" ) + if( elem.name == "Comment" ) { field = component->GetField( VALUE_FIELD ); field->SetPosition( position ); @@ -2096,14 +2102,12 @@ void SCH_ALTIUM_PLUGIN::ParseParameter( const std::map& aPro else { int fieldIdx = component->GetFieldCount(); - field = component->AddField( { position, fieldIdx, component, elem.name } ); + wxString fieldName = elem.name == "Value" ? "Altium_Value" : elem.name; + field = component->AddField( { position, fieldIdx, component, fieldName } ); } - // TODO: improve text replacement (https://gitlab.com/kicad/code/kicad/-/issues/6256) - if( elem.text == "=Value" && field->GetId() != VALUE_FIELD ) - field->SetText( "${VALUE}" ); - else - field->SetText( elem.text ); + wxString kicadText = AltiumSpecialStringsToKiCadVariables( elem.text, stringReplacement ); + field->SetText( kicadText ); field->SetVisible( !elem.isHidden ); field->SetHorizJustify( EDA_TEXT_HJUSTIFY_T::GR_TEXT_HJUSTIFY_LEFT ); diff --git a/qa/common/CMakeLists.txt b/qa/common/CMakeLists.txt index 54a6d3fb73..f11464a0b5 100644 --- a/qa/common/CMakeLists.txt +++ b/qa/common/CMakeLists.txt @@ -46,6 +46,7 @@ set( common_srcs libeval/test_numeric_evaluator.cpp plugins/altium/test_altium_parser.cpp + plugins/altium/test_altium_parser_utils.cpp view/test_zoom_controller.cpp ) diff --git a/qa/common/plugins/altium/test_altium_parser_utils.cpp b/qa/common/plugins/altium/test_altium_parser_utils.cpp new file mode 100644 index 0000000000..d18eb88f78 --- /dev/null +++ b/qa/common/plugins/altium/test_altium_parser_utils.cpp @@ -0,0 +1,113 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2021 KiCad Developers, see CHANGELOG.TXT for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file test_altium_parser_utils.cpp + * Test suite for #ALTIUM_PARSER + */ + +#include + +#include + +struct ALTIUM_PARSER_UTILS_FIXTURE +{ + ALTIUM_PARSER_UTILS_FIXTURE() {} +}; + + +/** + * Declares the struct as the Boost test fixture. + */ +BOOST_FIXTURE_TEST_SUITE( AltiumParserUtils, ALTIUM_PARSER_UTILS_FIXTURE ) + + +struct SPECIAL_STRINGS_TO_KICAD +{ + wxString input; + wxString exp_result; + std::map override; +}; + +/** + * A list of valid test strings and the expected results + */ +static const std::vector special_string_to_kicad_property = { + // Empty + { "", "", {} }, + // No Special Strings + { "A", "A", {} }, + { " A", " A", {} }, + { "A ", "A ", {} }, + { "A=B", "A=B", {} }, + { "A=B+C", "A=B+C", {} }, + { "A\nB", "A\nB", {} }, + { "A\tB", "A\tB", {} }, + { "This is a long text with spaces", "This is a long text with spaces", {} }, + // Text format (underscore,...), TODO: add + // Escaping, TODO: add + { "A=B", "A=B", {} }, + // Simple special strings + { "=A", "${A}", {} }, + { "=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" } } }, + // Some special cases we do not know yet how to handle correctly. But we should not crash ;) + { "=+", "", {} }, + { "=++", "", {} }, + { "=+++", "", {} }, + { "=B+", "${B}", {} }, + { "=+B", "${B}", {} }, + { "=B++", "${B}", {} }, + { "=+B+", "${B}", {} }, + { "=++B", "${B}", {} }, + { " =", " =", {} }, + { "= ", "", {} }, + { "= A", "${ A}", {} }, + { "=A ", "${A}", {} }, +}; + + +/** + * Test conversation from Altium Special String to a KiCad String with variables + */ +BOOST_AUTO_TEST_CASE( AltiumSpecialStringsToKiCadVariablesProperties ) +{ + for( const auto& c : special_string_to_kicad_property ) + { + BOOST_TEST_CONTEXT( wxString::Format( wxT( "'%s' -> '%s'" ), c.input, c.exp_result ) ) + { + wxString result = AltiumSpecialStringsToKiCadVariables( c.input, c.override ); + + // These are all valid + BOOST_CHECK_EQUAL( result, c.exp_result ); + } + } +} + +BOOST_AUTO_TEST_SUITE_END()