From 5d4b4f39ecbe85cec0adec808f5b905dad4894a1 Mon Sep 17 00:00:00 2001 From: Jeff Young <jeff@rokeby.ie> Date: Wed, 31 Jan 2024 14:09:00 +0000 Subject: [PATCH] Allow PARAM_WXSTRING_MAP to behave as an array. In particular, overwrite file contents with current contents of map rather than merging. Fixes https://gitlab.com/kicad/code/kicad/-/issues/16801 --- common/project/project_file.cpp | 3 ++- common/settings/json_settings.cpp | 10 ++++++++++ include/settings/parameters.h | 18 +++++++++++++++--- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/common/project/project_file.cpp b/common/project/project_file.cpp index 4fb682cafe..90f05bb2ed 100644 --- a/common/project/project_file.cpp +++ b/common/project/project_file.cpp @@ -50,7 +50,8 @@ PROJECT_FILE::PROJECT_FILE( const wxString& aFullPath ) : m_params.emplace_back( new PARAM_LIST<FILE_INFO_PAIR>( "boards", &m_boards, {} ) ); - m_params.emplace_back( new PARAM_WXSTRING_MAP( "text_variables", &m_TextVars, {} ) ); + m_params.emplace_back( new PARAM_WXSTRING_MAP( "text_variables", + &m_TextVars, {}, false, true /* array behavior, even though stored as a map */ ) ); m_params.emplace_back( new PARAM_LIST<wxString>( "libraries.pinned_symbol_libs", &m_PinnedSymbolLibs, {} ) ); diff --git a/common/settings/json_settings.cpp b/common/settings/json_settings.cpp index f29b8d9150..3846ab78e5 100644 --- a/common/settings/json_settings.cpp +++ b/common/settings/json_settings.cpp @@ -466,6 +466,16 @@ bool JSON_SETTINGS::SaveToFile( const wxString& aDirectory, bool aForce ) nlohmann::json toSave = m_internals->m_original; + + for( PARAM_BASE* param : m_params ) + { + if( PARAM_WXSTRING_MAP* stringMap = dynamic_cast<PARAM_WXSTRING_MAP*>( param ) ) + { + if( stringMap->ClearUnknownKeys() ) + toSave[ stringMap->GetJsonPath() ] = nlohmann::json( {} ); + } + } + toSave.update( m_internals->begin(), m_internals->end(), /* merge_objects = */ true ); try diff --git a/include/settings/parameters.h b/include/settings/parameters.h index 785e6bfd11..931e08edde 100644 --- a/include/settings/parameters.h +++ b/include/settings/parameters.h @@ -35,7 +35,8 @@ class PARAM_BASE public: PARAM_BASE( std::string aJsonPath, bool aReadOnly ) : m_path( std::move( aJsonPath ) ), - m_readOnly( aReadOnly ) + m_readOnly( aReadOnly ), + m_clearUnknownKeys( false ) {} virtual ~PARAM_BASE() = default; @@ -68,9 +69,18 @@ public: */ const std::string& GetJsonPath() const { return m_path; } + /** + * @return true if keys should be cleared from source file rather than merged. Useful for + * things such as text variables that are semantically an array but stored as a map. + */ + bool ClearUnknownKeys() const { return m_clearUnknownKeys; } + protected: std::string m_path; ///< Address of the param in the json files bool m_readOnly; ///< Indicates param pointer should never be overwritten + bool m_clearUnknownKeys; ///< Keys should be cleared from source rather than merged. + ///< This is useful for things that are semantically an + ///< array but stored as a map, such as textVars. }; @@ -575,11 +585,13 @@ class PARAM_WXSTRING_MAP : public PARAM_BASE public: PARAM_WXSTRING_MAP( const std::string& aJsonPath, std::map<wxString, wxString>* aPtr, std::initializer_list<std::pair<const wxString, wxString>> aDefault, - bool aReadOnly = false ) : + bool aReadOnly = false, bool aArrayBehavior = false ) : PARAM_BASE( aJsonPath, aReadOnly ), m_ptr( aPtr ), m_default( aDefault ) - { } + { + m_clearUnknownKeys = aArrayBehavior; + } void Load( JSON_SETTINGS* aSettings, bool aResetIfMissing = true ) const override;