KiCad PCB EDA Suite
Loading...
Searching...
No Matches
nested_settings.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 (C) 2020 Jon Evans <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <wx/log.h>
22
25#include <settings/parameters.h>
26#include <locale_io.h>
27
28
29NESTED_SETTINGS::NESTED_SETTINGS( const std::string& aName, int aVersion, JSON_SETTINGS* aParent,
30 const std::string& aPath, bool aLoadFromFile ) :
31 JSON_SETTINGS( aName, SETTINGS_LOC::NESTED, aVersion ),
32 m_parent( aParent ), m_path( aPath )
33{
34 SetParent( aParent, aLoadFromFile );
35}
36
37
39{
40 if( m_parent )
41 m_parent->ReleaseNestedSettings( this );
42}
43
44
45bool NESTED_SETTINGS::LoadFromFile( const wxString& aDirectory )
46{
47 m_internals->clear();
48 bool success = false;
49
50 if( m_parent )
51 {
52 nlohmann::json::json_pointer ptr = m_internals->PointerFromString( m_path );
53
54 if( m_parent->m_internals->contains( ptr ) )
55 {
56 try
57 {
58 m_internals->update( m_parent->m_internals->at( ptr ) );
59
60 wxLogTrace( traceSettings, wxT( "Loaded NESTED_SETTINGS %s" ), GetFilename() );
61
62 success = true;
63 }
64 catch( ... )
65 {
66 wxLogTrace( traceSettings, wxT( "NESTED_SETTINGS %s: Could not load from "
67 "%s at %s" ),
68 m_filename, m_parent->GetFilename(), m_path );
69 }
70 }
71 }
72
73 if( success )
74 {
75 int filever = -1;
76
77 try
78 {
79 filever = m_internals->Get<int>( "meta.version" );
80 }
81 catch( ... )
82 {
83 wxLogTrace( traceSettings, wxT( "%s: nested settings version could not be read!" ),
84 m_filename );
85 success = false;
86 }
87
88 if( filever >= 0 && filever < m_schemaVersion )
89 {
90 wxLogTrace( traceSettings, wxT( "%s: attempting migration from version %d to %d" ),
91 m_filename, filever, m_schemaVersion );
92
93 bool migrated = false;
94
95 try
96 {
97 migrated = Migrate();
98 }
99 catch( ... )
100 {
101 success = false;
102 }
103
104 if( !migrated )
105 {
106 wxLogTrace( traceSettings, wxT( "%s: migration failed!" ), GetFullFilename() );
107 success = false;
108 }
109 }
110 else if( filever > m_schemaVersion )
111 {
112 wxLogTrace( traceSettings,
113 wxT( "%s: warning: nested settings version %d is newer than latest (%d)" ),
114 m_filename, filever, m_schemaVersion );
115 }
116 else if( filever >= 0 )
117 {
118 wxLogTrace( traceSettings, wxT( "%s: schema version %d is current" ),
119 m_filename, filever );
120 }
121 }
122
123 Load();
124
125 return success;
126}
127
128
129bool NESTED_SETTINGS::SaveToFile( const wxString& aDirectory, bool aForce )
130{
131 if( !m_parent )
132 return false;
133
135
136 try
137 {
138 // Diff our still-loaded internals against the parent's copy before Store() materializes
139 // params. Comparing here keeps default-fill of params absent from an older file from
140 // counting as a change and churning the parent on editor close (see #24402).
141 auto jsonObjectInParent = m_parent->GetJson( m_path );
142
143 bool modified = !jsonObjectInParent
144 || !nlohmann::json::diff( *m_internals, jsonObjectInParent.value() ).empty();
145
146 // Store() additionally reports user edits to registered params, not yet reflected above.
147 modified |= Store();
148
149 // Params that own their subtree need to be able to delete keys. The parent
150 // merge only adds and updates, so clear the old copy from the baseline first.
151 for( const PARAM_BASE* param : m_params )
152 {
153 if( !param->ClearUnknownKeys() )
154 continue;
155
156 nlohmann::json::json_pointer ptr =
157 JSON_SETTINGS_INTERNALS::PointerFromString( m_path + "." + param->GetJsonPath() );
158
159 if( m_parent->m_internals->m_original.contains( ptr ) )
160 m_parent->m_internals->m_original[ptr] = nlohmann::json::object();
161 }
162
163 if( modified || aForce )
164 {
165 ( *m_parent->m_internals )[m_path].update( *m_internals );
166
167 wxLogTrace( traceSettings, wxS( "Stored NESTED_SETTINGS %s with schema %d" ),
168 GetFilename(),
170 }
171
172 return modified;
173 }
174 catch( ... )
175 {
176 wxLogTrace( traceSettings, wxS( "NESTED_SETTINGS %s: Could not store to %s at %s" ),
178 m_parent->GetFilename(),
179 m_path );
180
181 return false;
182 }
183}
184
185
186void NESTED_SETTINGS::SetParent( JSON_SETTINGS* aParent, bool aLoadFromFile )
187{
188 m_parent = aParent;
189
190 if( m_parent )
191 {
192 m_parent->AddNestedSettings( this );
193
194 // In case we were created after the parent's ctor
195 if( aLoadFromFile )
196 LoadFromFile();
197 }
198}
static nlohmann::json::json_pointer PointerFromString(std::string aPath)
Builds a JSON pointer based on a given string.
wxString m_filename
The filename (not including path) of this settings file (inicode)
virtual void Load()
Updates the parameters of this object based on the current JSON document contents.
wxString GetFullFilename() const
bool Migrate()
Migrates the schema of this settings from the version in the file to the latest version.
std::vector< PARAM_BASE * > m_params
The list of parameters (owned by this object)
JSON_SETTINGS(const wxString &aFilename, SETTINGS_LOC aLocation, int aSchemaVersion)
std::unique_ptr< JSON_SETTINGS_INTERNALS > m_internals
friend class NESTED_SETTINGS
int m_schemaVersion
Version of this settings schema.
virtual bool Store()
Stores the current parameters into the JSON document represented by this object Note: this doesn't do...
wxString GetFilename() const
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition locale_io.h:37
void SetParent(JSON_SETTINGS *aParent, bool aLoadFromFile=true)
std::string m_path
The path (in pointer format) of where to store this document in the parent.
JSON_SETTINGS * m_parent
A pointer to the parent object to load and store from.
virtual ~NESTED_SETTINGS()
bool SaveToFile(const wxString &aDirectory="", bool aForce=false) override
Calls Store() and then saves the JSON document contents into the parent JSON_SETTINGS.
bool LoadFromFile(const wxString &aDirectory="") override
Loads the JSON document from the parent and then calls Load()
SETTINGS_LOC
@ NESTED
Not stored in a file, but inside another JSON_SETTINGS.
#define traceSettings
std::vector< FAB_LAYER_COLOR > dummy