23 #include <wx/filename.h> 24 #include <wx/stdpaths.h> 46 #define PROJECT_BACKUPS_DIR_SUFFIX wxT( "-backups" ) 50 m_headless( aHeadless ),
52 m_common_settings( nullptr ),
54 m_migrateLibraryTables( true )
82 std::unique_ptr<JSON_SETTINGS> ptr( aSettings );
84 ptr->SetManager(
this );
86 wxLogTrace(
traceSettings,
"Registered new settings object <%s>", ptr->GetFullFilename() );
109 [&aSettings](
const std::unique_ptr<JSON_SETTINGS>& aPtr )
111 return aPtr.get() == aSettings;
124 if( dynamic_cast<COLOR_SETTINGS*>( settings.get() ) )
135 [&aSettings](
const std::unique_ptr<JSON_SETTINGS>& aPtr )
137 return aPtr.get() == aSettings;
142 wxLogTrace(
traceSettings,
"Saving %s", ( *it )->GetFullFilename() );
151 [&aSettings](
const std::unique_ptr<JSON_SETTINGS>& aPtr )
153 return aPtr.get() == aSettings;
158 wxLogTrace(
traceSettings,
"Flush and release %s", ( *it )->GetFullFilename() );
188 wxLogTrace(
traceSettings,
"Attempting to load color theme %s", aName );
192 if( !fn.IsOk() || !fn.Exists() )
194 wxLogTrace(
traceSettings,
"Theme file %s.json not found, falling back to user", aName );
198 auto cs = static_cast<COLOR_SETTINGS*>(
201 if( cs->GetFilename() != aName.ToStdString() )
203 wxLogTrace(
traceSettings,
"Warning: stored filename is actually %s, ", cs->GetFilename() );
223 wxDirTraverseResult
OnFile(
const wxString& aFilePath )
override 225 wxFileName file( aFilePath );
227 if( file.GetExt() !=
"json" )
228 return wxDIR_CONTINUE;
232 return wxDIR_CONTINUE;
235 wxDirTraverseResult
OnDir(
const wxString& dirPath )
override 254 wxString filename = aFilename;
256 if( filename.EndsWith( wxT(
".json" ) ) )
257 filename = filename.BeforeLast(
'.' );
294 if( colors_dir.IsOpened() )
295 colors_dir.Traverse( loader );
310 [aSettings] (
const std::pair<wxString, COLOR_SETTINGS*>& el )
312 return el.second->GetFilename() == aSettings->
GetFilename();
318 if( !aSettings->
Store() )
320 wxLogTrace(
traceSettings,
"Color scheme %s not modified; skipping save",
325 wxASSERT( aSettings->contains( ptr ) );
335 ( *aSettings )[ptr].update( backup );
344 wxASSERT( aSettings );
361 wxASSERT_MSG(
false,
"Unknown settings location!" );
386 wxDirTraverseResult
OnFile(
const wxString& aSrcFilePath )
override 388 wxFileName file( aSrcFilePath );
391 file.GetName() == wxT(
"fp-lib-table" ) ) )
393 return wxDIR_CONTINUE;
396 wxString path = file.GetPath();
399 file.SetPath( path );
401 wxLogTrace(
traceSettings,
"Copying %s to %s", aSrcFilePath, file.GetFullPath() );
406 return wxDIR_CONTINUE;
409 wxDirTraverseResult
OnDir(
const wxString& dirPath )
override 411 wxFileName dir( dirPath );
414 if( dir.GetName() ==
"colors" ||
415 dir.GetName() ==
"3d" )
418 wxString path = dir.GetPath();
423 wxMkdir( dir.GetFullPath() );
425 return wxDIR_CONTINUE;
439 wxLogTrace(
traceSettings,
"Settings migration not checked; running headless" );
444 wxLogTrace(
traceSettings,
"Using settings path %s", path.GetFullPath() );
446 if( path.DirExists() )
448 wxFileName common = path;
449 common.SetName(
"kicad_common" );
450 common.SetExt(
"json" );
452 if( common.Exists() )
454 wxLogTrace(
traceSettings,
"Path exists and has a kicad_common, continuing!" );
462 if( dlg.ShowModal() != wxID_OK )
464 wxLogTrace(
traceSettings,
"Migration dialog canceled; exiting" );
468 if( !path.DirExists() )
470 wxLogTrace(
traceSettings,
"Path didn't exist; creating it" );
471 path.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
476 wxLogTrace(
traceSettings,
"No migration source given; starting with defaults" );
483 source_dir.Traverse( traverser );
485 if( !traverser.GetErrors().empty() )
499 std::vector<wxFileName> base_paths;
504 if( wxGetEnv( wxT(
"KICAD_CONFIG_HOME" ),
nullptr ) )
510 auto check_dir = [&] (
const wxString& aSubDir )
515 wxString sub_path = dir.GetNameWithSep() + aSubDir;
519 aPaths->push_back( sub_path );
520 wxLogTrace(
traceSettings,
"GetPreviousVersionName: %s is valid", sub_path );
525 for(
auto base_path : base_paths )
527 if( !dir.Open( base_path.GetFullPath() ) )
529 wxLogTrace(
traceSettings,
"GetPreviousVersionName: could not open base path %s",
530 base_path.GetFullPath() );
534 wxLogTrace(
traceSettings,
"GetPreviousVersionName: checking base path %s",
535 base_path.GetFullPath() );
537 if( dir.GetFirst( &subdir, wxEmptyString, wxDIR_DIRS ) )
542 while( dir.GetNext( &subdir ) )
553 "GetPreviousVersionName: root path %s is valid", dir.GetName() );
554 aPaths->push_back( dir.GetName() );
558 return aPaths->size() > 0;
564 wxFileName
test( aPath,
"kicad_common" );
565 return test.Exists();
574 path.AppendDir(
"colors" );
576 if( !path.DirExists() )
578 if( !wxMkdir( path.GetPath() ) )
581 "GetColorSettingsPath(): Path %s missing and could not be created!",
586 return path.GetPath();
592 static wxString user_settings_path;
594 if( user_settings_path.empty() )
597 return user_settings_path;
606 cfgpath.AssignDir( wxStandardPaths::Get().GetUserConfigDir() );
610 #if !defined( __WXMSW__ ) && !defined( __WXMAC__ ) 611 wxArrayString dirs = cfgpath.GetDirs();
613 if( dirs.Last() !=
".config" )
614 cfgpath.AppendDir(
".config" );
620 if( wxGetEnv( wxT(
"XDG_CONFIG_HOME" ), &envstr ) && !envstr.IsEmpty() )
623 cfgpath.AssignDir( envstr );
626 cfgpath.AppendDir(
TO_STR( KICAD_CONFIG_DIR ) );
629 if( aUseEnv && wxGetEnv( wxT(
"KICAD_CONFIG_HOME" ), &envstr ) && !envstr.IsEmpty() )
632 cfgpath.AssignDir( envstr );
638 return cfgpath.GetPath();
658 wxLogTrace(
traceSettings,
"compareSettingsVersions: bad input (%s, %s)", aFirst, aSecond );
666 else if( a_maj > b_maj )
676 else if( a_min > b_min )
690 std::regex re_version(
"(\\d+)\\.(\\d+)" );
693 if( std::regex_match( aVersionString, match, re_version ) )
697 *aMajor = std::stoi( match[1].str() );
698 *aMinor = std::stoi( match[2].str() );
715 wxFileName path( aFullPath );
720 wxString fullPath = path.GetFullPath();
738 std::unique_ptr<PROJECT> project = std::make_unique<PROJECT>();
739 project->setProjectFullName( fullPath );
744 project->SetReadOnly( project->GetProjectFile().IsReadOnly() );
749 wxString fn( path.GetName() );
754 settings = static_cast<PROJECT_LOCAL_SETTINGS*>(
RegisterSettings( settings ) );
756 m_projects[fullPath]->setLocalSettings( settings );
774 wxLogTrace(
traceSettings,
"Unload project %s", projectPath );
778 [&](
const std::unique_ptr<PROJECT>& ptr )
780 return ptr.get() == toRemove;
827 std::vector<wxString> ret;
829 for(
const std::pair<const wxString, PROJECT*>& pair :
m_projects )
830 ret.emplace_back( pair.first );
838 wxString path = aFullPath;
844 if(
Prj().IsReadOnly() )
867 wxFileName fn( aFullPath );
887 wxString fn( fullFn.GetName() );
895 file->SetProject( &aProject );
897 wxString path( fullFn.GetPath() );
899 return file->LoadFromFile( path );
916 [&file](
const std::unique_ptr<JSON_SETTINGS>& aPtr )
918 return aPtr.get() == file;
928 ( *it )->SaveToFile( projectPath );
950 wxDateTime timestamp = wxDateTime::Now();
957 target.SetName( fileName );
960 wxDir dir( target.GetPath() );
962 if( !target.DirExists() && !wxMkdir( target.GetPath() ) )
964 wxLogTrace(
traceSettings,
"Could not create project backup path %s", target.GetPath() );
968 if( !target.IsDirWritable() )
970 wxLogTrace(
traceSettings,
"Backup directory %s is not writeable", target.GetPath() );
974 wxLogTrace(
traceSettings,
"Backing up project to %s", target.GetPath() );
978 return archiver.
Archive(
Prj().GetProjectPath(), target.GetFullPath(), aReporter );
986 std::function<
bool(
const wxString& )> aCond ) :
992 wxDirTraverseResult
OnFile(
const wxString& aFile )
override 997 return wxDIR_CONTINUE;
1000 wxDirTraverseResult
OnDir(
const wxString& aDirName )
override 1002 return wxDIR_CONTINUE;
1022 [&prefix](
const wxString& aFile )
1025 wxString fn( wxFileName( aFile ).GetName() );
1026 fn.Replace( prefix,
"" );
1032 if(
Prj().GetProjectPath().
empty() )
1037 if( !wxDirExists( backupPath ) )
1039 wxLogTrace(
traceSettings,
"Backup path %s doesn't exist, creating it", backupPath );
1041 if( !wxMkdir( backupPath ) )
1043 wxLogTrace(
traceSettings,
"Could not create backups path! Skipping backup" );
1048 wxDir dir( backupPath );
1050 if( !dir.IsOpened() )
1052 wxLogTrace(
traceSettings,
"Could not open project backups path %s", dir.GetName() );
1056 std::vector<wxString> files;
1059 [&modTime](
const wxString& aFile )
1061 return modTime( aFile ).IsValid();
1064 dir.Traverse( traverser, wxT(
"*.zip" ) );
1067 std::sort( files.begin(), files.end(),
1068 [&](
const wxString& aFirst,
const wxString& aSecond ) ->
bool 1070 wxDateTime first = modTime( aFirst );
1071 wxDateTime second = modTime( aSecond );
1073 return first.GetTicks() > second.GetTicks();
1077 if( !files.empty() )
1079 wxDateTime lastTime = modTime( files[0] );
1081 if( lastTime.IsValid() )
1083 wxTimeSpan delta = wxDateTime::Now() - modTime( files[0] );
1085 if( delta.IsShorterThan( wxTimeSpan::Seconds( settings.
min_interval ) ) )
1097 wxRemoveFile( files.back() );
1105 wxULongLong totalSize = 0;
1107 for(
const wxString& file : files )
1108 totalSize += wxFileName::GetSize( file );
1110 while( !files.empty() && totalSize > static_cast<wxULongLong>( settings.
limit_total_size ) )
1112 totalSize -= wxFileName::GetSize( files.back() );
1113 wxRemoveFile( files.back() );
1121 wxDateTime day = modTime( files[0] );
1124 wxASSERT( day.IsValid() );
1126 std::vector<wxString> filesToDelete;
1128 for(
size_t i = 1; i < files.size(); i++ )
1130 wxDateTime dt = modTime( files[i] );
1132 if( dt.IsSameDate( day ) )
1137 filesToDelete.emplace_back( files[i] );
1146 for(
const wxString& file : filesToDelete )
1147 wxRemoveFile( file );
static wxString backupDateTimeFormat
virtual bool Store()
Stores the current parameters into the JSON document represented by this object Note: this doesn't do...
PROJECT & Prj() const
A helper while we are not MDI-capable – return the one and only project.
Container for project specific data.
unsigned long long limit_total_size
Maximum total size of backups (bytes), 0 for unlimited.
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
This file is part of the common library TODO brief description.
This file is part of the common library.
void SaveProjectAs(const wxString &aFullPath)
Sets the currently loaded project path and saves it (pointers remain valid)
static bool IsSettingsPathValid(const wxString &aPath)
Checks if a given path is probably a valid KiCad configuration directory.
wxDirTraverseResult OnFile(const wxString &aFilePath) override
const std::string ProjectFileExtension
KIWAY * m_kiway
The kiway this settings manager interacts with.
wxString GetFilename() const
bool m_migrateLibraryTables
If true, the symbol and footprint library tables will be migrated from the previous version.
bool Archive(const wxString &aSrcDir, const wxString &aDestFile, REPORTER &aReporter, bool aVerbose=true)
Creates an archive of the project.
#define PROJECT_VAR_NAME
A variable name whose value holds the current project directory.
bool SaveToFile(const wxString &aDirectory="", bool aForce=false) override
bool enabled
Automatically back up the project when files are saved.
virtual bool LoadFromFile(const wxString &aDirectory="")
Loads the backing file from disk and then calls Load()
The project local settings are things that are attached to a particular project, but also might be pa...
bool SaveToFile(const wxString &aDirectory="", bool aForce=false) override
wxDirTraverseResult OnFile(const wxString &aSrcFilePath) override
void KiCopyFile(const wxString &aSrcPath, const wxString &aDestPath, wxString &aErrors)
#define PROJECT_BACKUPS_DIR_SUFFIX
Project settings path will be <projectname> + this.
Template specialization to enable wxStrings for certain containers (e.g. unordered_map)
VECTOR_INSERT_TRAVERSER(std::vector< wxString > &aVec, std::function< bool(const wxString &)> aCond)
std::map< wxString, PROJECT_FILE * > m_project_files
Loaded project files, mapped according to project full name.
bool MigrateIfNeeded()
Handles the initialization of the user settings directory and migration from previous KiCad versions ...
A pure virtual class used to derive REPORTER objects from.
COLOR_SETTINGS * AddNewColorSettings(const wxString &aFilename)
Registers a new color settings object with the given filename.
static int compareVersions(const std::string &aFirst, const std::string &aSecond)
Compares two settings versions, like "5.99" and "6.0".
bool BackupProject(REPORTER &aReporter) const
Creates a backup archive of the current project.
virtual const wxString GetProjectPath() const
Return the full path of the project.
PROJECT_FILE is the backing store for a PROJECT, in JSON format.
wxString GetMajorMinorVersion()
Get only the major and minor version in a string major.minor.
This file contains miscellaneous commonly used macros and functions.
virtual PROJECT_LOCAL_SETTINGS & GetLocalSettings() const
std::vector< wxString > & m_files
The color scheme directory (e.g. ~/.config/kicad/colors/)
wxString m_migration_source
bool m_ok
True if settings loaded successfully at construction.
bool unloadProjectFile(PROJECT *aProject, bool aSave)
Optionally saves, and then unloads and unregisters the given PROJECT_FILE.
virtual bool SaveToFile(const wxString &aDirectory="", bool aForce=false)
bool IsProjectOpen() const
Helper for checking if we have a project open TODO: This should be deprecated along with Prj() once w...
wxDirTraverseResult OnDir(const wxString &aDirName) override
The settings directory inside a project folder.
bool TriggerBackupIfNeeded(REPORTER &aReporter) const
Calls BackupProject if a new backup is needed according to the current backup policy.
SETTINGS_LOC GetLocation() const
std::function< bool(const wxString &)> m_condition
bool GetPreviousVersionPaths(std::vector< wxString > *aName=nullptr)
Retreives the name of the most recent previous KiCad version that can be found in the user settings d...
COMMON_SETTINGS * GetCommonSettings() const
Retrieves the common settings shared by all applications.
virtual void ProjectChanged()
Calls ProjectChanged() on all KIWAY_PLAYERs.
Definition of file extensions used in Kicad.
static std::vector< COLOR_SETTINGS * > CreateBuiltinColorSettings()
Constructs and returns a list of color settings objects based on the built-in color themes.
bool m_headless
True if running outside a UI context.
wxDirTraverseResult OnFile(const wxString &aFile) override
void registerColorSettings(const wxString &aFilename)
virtual const wxString GetProjectFullName() const
Return the full path and name of the project.
const std::string LegacyProjectFileExtension
No directory prepended, full path in filename (used for PROJECT_FILE)
std::map< wxString, PROJECT * > m_projects
Loaded projects, mapped according to project full name.
SETTINGS_MANAGER(bool aHeadless=false)
virtual void setProjectFullName(const wxString &aFullPathAndName)
Set the full directory, basename, and extension of the project.
static wxString GetColorSettingsPath()
Returns the path where color scheme files are stored; creating it if missing (normally .
wxString GetProjectBackupsPath() const
bool loadProjectFile(PROJECT &aProject)
Registers a PROJECT_FILE and attempts to load it from disk.
static wxString GetUserSettingsPath()
Return the user configuration path used to store KiCad's configuration files.
JSON_SETTINGS * RegisterSettings(JSON_SETTINGS *aSettings, bool aLoadNow=true)
Takes ownership of the pointer passed in.
std::unordered_map< wxString, COLOR_SETTINGS * > m_color_settings
int min_interval
Minimum time, in seconds, between subsequent backups.
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
bool LoadProject(const wxString &aFullPath, bool aSetActive=true)
Loads a project or sets up a new project with a specified path.
COLOR_SETTINGS * loadColorSettingsByName(const wxString &aName)
Attempts to load a color theme by name (the color theme directory and .json ext are assumed)
COLOR_SETTINGS * GetColorSettings(const wxString &aName="user")
Retrieves a color settings object that applications can read colors from.
COLOR_SETTINGS_LOADER(std::function< void(const wxString &)> aAction)
void ReloadColorSettings()
Re-scans the color themes directory, reloading any changes it finds.
std::vector< std::unique_ptr< JSON_SETTINGS > > m_settings
std::vector< wxString > GetOpenProjects() const
static wxString calculateUserSettingsPath(bool aIncludeVer=true, bool aUseEnv=true)
Determines the base path for user settings files.
bool UnloadProject(PROJECT *aProject, bool aSave=true)
Saves, unloads and unregisters the given PROJECT.
The main config directory (e.g. ~/.config/kicad/)
bool SaveProject(const wxString &aFullPath=wxEmptyString)
Saves a loaded project.
wxDirTraverseResult OnDir(const wxString &dirPath) override
void SaveColorSettings(COLOR_SETTINGS *aSettings, const std::string &aNamespace="")
Safely saves a COLOR_SETTINGS to disk, preserving any changes outside the given namespace.
static bool empty(const wxTextEntryBase *aCtrl)
static std::string GetSettingsVersion()
Parses the current KiCad build version and extracts the major and minor revision to use as the name o...
Color settings are a bit different than most of the settings objects in that there can be more than o...
virtual const wxString GetProjectName() const
Return the short name of the project.
int limit_daily_files
Maximum files to keep per day, 0 for unlimited.
wxDirTraverseResult OnDir(const wxString &dirPath) override
const wxChar *const traceSettings
Flag to enable debug output of settings operations and management.
COMMON_SETTINGS * m_common_settings
void SetFilename(const wxString &aFilename)
virtual void setProjectFile(PROJECT_FILE *aFile)
Set the backing store file for this project.
COLOR_SETTINGS * GetMigratedColorSettings()
Returns a color theme for storing colors migrated from legacy (5.x and earlier) settings,...
static nlohmann::json::json_pointer PointerFromString(std::string aPath)
Builds a JSON pointer based on a given string.
std::function< void(const wxString &)> m_action
MIGRATION_TRAVERSER(const wxString &aSrcDir, const wxString &aDestDir, bool aMigrateTables)
void FlushAndRelease(JSON_SETTINGS *aSettings, bool aSave=true)
If the given settings object is registered, save it to disk and unregister it.
std::vector< std::unique_ptr< PROJECT > > m_projects_list
Loaded projects (ownership here)
virtual void Load()
Updates the parameters of this object based on the current JSON document contents.
PROJECT * GetProject(const wxString &aFullPath) const
Retrieves a loaded project by name.
int limit_total_files
Maximum number of backup archives to retain.
static bool extractVersion(const std::string &aVersionString, int *aMajor, int *aMinor)
Extracts the numeric version from a given settings string.
void loadAllColorSettings()
wxString GetPathForSettingsFile(JSON_SETTINGS *aSettings)
Returns the path a given settings file should be loaded from / stored to.
const std::string ArchiveFileExtension