diff --git a/common/database/database_lib_settings.cpp b/common/database/database_lib_settings.cpp index 4b1e091258..af579ef6fe 100644 --- a/common/database/database_lib_settings.cpp +++ b/common/database/database_lib_settings.cpp @@ -78,29 +78,18 @@ DATABASE_LIB_SETTINGS::DATABASE_LIB_SETTINGS( const std::string& aFilename ) : { const nlohmann::json& pj = entry["properties"]; - if( pj.contains( "description" ) ) - table.properties.description = pj["description"].get(); + table.properties.description = fetchOrDefault( pj, "description" ); - if( pj.contains( "footprint_filters" ) ) - { - table.properties.footprint_filters = - pj["footprint_filters"].get(); - } + table.properties.footprint_filters = + fetchOrDefault( pj, "footprint_filters" ); - if( pj.contains( "keywords" ) ) - table.properties.keywords = pj["keywords"].get(); + table.properties.keywords = fetchOrDefault( pj, "keywords" ); - if( pj.contains( "exclude_from_bom" ) ) - { - table.properties.exclude_from_bom = - pj["exclude_from_bom"].get(); - } + table.properties.exclude_from_bom = + fetchOrDefault( pj, "exclude_from_bom" ); - if( pj.contains( "exclude_from_board" ) ) - { - table.properties.exclude_from_board = - pj["exclude_from_board"].get(); - } + table.properties.exclude_from_board = + fetchOrDefault( pj, "exclude_from_board" ); } if( entry.contains( "fields" ) && entry["fields"].is_array() ) @@ -110,26 +99,19 @@ DATABASE_LIB_SETTINGS::DATABASE_LIB_SETTINGS( const std::string& aFilename ) : if( fieldJson.empty() || !fieldJson.is_object() ) continue; - std::string column = fieldJson.contains( "column" ) - ? fieldJson["column"].get() : ""; - - std::string name = fieldJson.contains( "name" ) - ? fieldJson["name"].get() : ""; - - bool visible_on_add = !fieldJson.contains( "visible_on_add" ) - || fieldJson["visible_on_add"].get(); - + std::string column = fetchOrDefault( fieldJson, "column" ); + std::string name = fetchOrDefault( fieldJson, "name" ); + bool visible_on_add = fetchOrDefault( fieldJson, "visible_on_add" ); bool visible_in_chooser = - !fieldJson.contains( "visible_in_chooser" ) - || fieldJson["visible_in_chooser"].get(); - - bool show_name = fieldJson.contains( "show_name" ) - && fieldJson["show_name"].get(); + fetchOrDefault( fieldJson, "visible_in_chooser" ); + bool show_name = fetchOrDefault( fieldJson, "show_name" ); + bool inherit = fetchOrDefault( fieldJson, "inherit_properties" ); table.fields.emplace_back( DATABASE_FIELD_MAPPING( { - column, name, visible_on_add, visible_in_chooser, show_name + column, name, visible_on_add, visible_in_chooser, show_name, + inherit } ) ); } } diff --git a/common/settings/json_settings.cpp b/common/settings/json_settings.cpp index 761c623183..6a4c01d083 100644 --- a/common/settings/json_settings.cpp +++ b/common/settings/json_settings.cpp @@ -836,3 +836,29 @@ void from_json( const nlohmann::json& aJson, wxString& aString ) { aString = wxString( aJson.get().c_str(), wxConvUTF8 ); } + + +template +ResultType JSON_SETTINGS::fetchOrDefault( const nlohmann::json& aJson, const std::string& aKey, + ResultType aDefault ) +{ + ResultType ret = aDefault; + + try + { + if( aJson.contains( aKey ) ) + ret = aJson.at( aKey ).get(); + } + catch( ... ) + { + } + + return ret; +} + + +template std::string JSON_SETTINGS::fetchOrDefault( const nlohmann::json& aJson, + const std::string& aKey, std::string aDefault ); + +template bool JSON_SETTINGS::fetchOrDefault( const nlohmann::json& aJson, const std::string& aKey, + bool aDefault ); diff --git a/eeschema/sch_plugins/database/sch_database_plugin.cpp b/eeschema/sch_plugins/database/sch_database_plugin.cpp index 4a25172b34..8b4b703041 100644 --- a/eeschema/sch_plugins/database/sch_database_plugin.cpp +++ b/eeschema/sch_plugins/database/sch_database_plugin.cpp @@ -19,6 +19,7 @@ */ #include +#include #include @@ -349,6 +350,14 @@ LIB_SYMBOL* SCH_DATABASE_PLUGIN::loadSymbolFromRow( const wxString& aSymbolName, symbol->SetIncludeInBom( !exclude ); } + std::vector fields; + symbol->GetFields( fields ); + + std::unordered_map fieldsMap; + + for( LIB_FIELD* field : fields ) + fieldsMap[field->GetName()] = field; + for( const DATABASE_FIELD_MAPPING& mapping : aTable.fields ) { if( !aRow.count( mapping.column ) ) @@ -382,14 +391,32 @@ LIB_SYMBOL* SCH_DATABASE_PLUGIN::loadSymbolFromRow( const wxString& aSymbolName, continue; } - LIB_FIELD* field = new LIB_FIELD( symbol->GetNextAvailableFieldId() ); - field->SetName( mapping.name ); - field->SetText( value ); - field->SetVisible( mapping.visible_on_add ); - field->SetAutoAdded( true ); - field->SetNameShown( mapping.show_name ); + LIB_FIELD* field; + bool isNew = false; - symbol->AddField( field ); + if( fieldsMap.count( mapping.name ) ) + { + field = fieldsMap[mapping.name]; + } + else + { + field = new LIB_FIELD( symbol->GetNextAvailableFieldId() ); + field->SetName( mapping.name ); + isNew = true; + fieldsMap[mapping.name] = field; + } + + if( !mapping.inherit_properties || isNew ) + { + field->SetVisible( mapping.visible_on_add ); + field->SetAutoAdded( true ); + field->SetNameShown( mapping.show_name ); + } + + field->SetText( value ); + + if( isNew ) + symbol->AddField( field ); m_customFields.insert( mapping.name ); diff --git a/include/database/database_lib_settings.h b/include/database/database_lib_settings.h index 60b42ff059..520bd72290 100644 --- a/include/database/database_lib_settings.h +++ b/include/database/database_lib_settings.h @@ -49,6 +49,7 @@ struct DATABASE_FIELD_MAPPING bool visible_on_add; ///< Whether to show the field when placing the symbol bool visible_in_chooser; ///< Whether the column is shown by default in the chooser bool show_name; ///< Whether or not to show the field name as well as its value + bool inherit_properties; ///< Whether or not to inherit properties from symbol field }; diff --git a/include/settings/json_settings.h b/include/settings/json_settings.h index 0241c182ae..d8890a550f 100644 --- a/include/settings/json_settings.h +++ b/include/settings/json_settings.h @@ -282,6 +282,17 @@ protected: return wxEmptyString; } + /** + * Helper to retrieve a value from a JSON object (dictionary) as a certain result type + * @tparam ResultType is the type of the retrieved value. + * @param aJson is the object to act on . + * @param aKey is the object key to retrieve the value for. + * @return the result, or aDefault if aKey is not found. + */ + template + static ResultType fetchOrDefault( const nlohmann::json& aJson, const std::string& aKey, + ResultType aDefault = ResultType() ); + /// The filename (not including path) of this settings file (inicode) wxString m_filename;