/* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2020 Jon Evans * Copyright (C) 2020 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 3 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, see . */ #ifndef _SETTINGS_MANAGER_H #define _SETTINGS_MANAGER_H #include // for wxString hash #include class COLOR_SETTINGS; class COMMON_SETTINGS; class SETTINGS_MANAGER { public: SETTINGS_MANAGER(); ~SETTINGS_MANAGER(); /** * @return true if settings load was successful */ bool IsOK() { return m_ok; } /** * Takes ownership of the pointer passed in * @param aSettings is a settings object to register * @return a handle to the owned pointer */ JSON_SETTINGS* RegisterSettings( JSON_SETTINGS* aSettings, bool aLoadNow = true ); void Load(); void Load( JSON_SETTINGS* aSettings ); void Save(); void Save( JSON_SETTINGS* aSettings ); /** * If the given settings object is registered, save it to disk and unregister it * @param aSettings is the object to release */ void FlushAndRelease( JSON_SETTINGS* aSettings ); /** * Returns a handle to the a given settings by type * If the settings have already been loaded, returns the existing pointer. * If the settings have not been loaded, creates a new object owned by the * settings manager and returns a pointer to it. * * @tparam AppSettings is a type derived from APP_SETTINGS_BASE * @param aLoadNow is true to load the registered file from disk immediately * @return a pointer to a loaded settings object */ template AppSettings* GetAppSettings( bool aLoadNow = true ) { AppSettings* ret = nullptr; auto it = std::find_if( m_settings.begin(), m_settings.end(), []( const std::unique_ptr& aSettings ) { return dynamic_cast( aSettings.get() ); } ); if( it != m_settings.end() ) ret = dynamic_cast( it->get() ); else ret = static_cast( RegisterSettings( new AppSettings, aLoadNow ) ); return ret; } /** * Retrieves a color settings object that applications can read colors from. * If the given settings file cannot be found, returns the default settings. * * @param aName is the name of the color scheme to load * @return a loaded COLOR_SETTINGS object */ COLOR_SETTINGS* GetColorSettings( const wxString& aName = "user" ); std::vector GetColorSettingsList() { std::vector ret; for( const auto& el : m_color_settings ) ret.push_back( el.second ); std::sort( ret.begin(), ret.end(), []( COLOR_SETTINGS* a, COLOR_SETTINGS* b ) { return a->GetName() < b->GetName(); } ); return ret; } /** * Safely saves a COLOR_SETTINGS to disk, preserving any changes outside the given namespace. * * A color settings namespace is one of the top-level JSON objects like "board", etc. * This will preform a read-modify-write * * @param aSettings is a pointer to a valid COLOR_SETTINGS object managed by SETTINGS_MANAGER * @param aNamespace is the namespace of settings to save */ void SaveColorSettings( COLOR_SETTINGS* aSettings, const std::string& aNamespace = "" ); /** * Registers a new color settings object with the given filename * @param aFilename is the location to store the new settings object * @return a pointer to the new object */ COLOR_SETTINGS* AddNewColorSettings( const wxString& aFilename ); /** * Retrieves the common settings shared by all applications * @return a pointer to a loaded COMMON_SETTINGS */ COMMON_SETTINGS* GetCommonSettings() { return m_common_settings; } /** * Returns the path a given settings file should be loaded from / stored to. * @param aSettings is the settings object * @return a path based on aSettings->m_location */ std::string GetPathForSettingsFile( JSON_SETTINGS* aSettings ); /** * Handles the initialization of the user settings directory and migration from previous * KiCad versions as needed. * * This method will check for the existence of the user settings path for this KiCad version. * If it exists, settings load will proceed normally using that path. * * If that directory is empty or does not exist, the migration wizard will be launched, which * will give users the option to migrate settings from a previous KiCad version (if one is * found), manually specify a directory to migrate fromm, or start with default settings. * * @return true if migration was successful or not necessary, false otherwise */ bool MigrateIfNeeded(); /** * Helper for DIALOG_MIGRATE_SETTINGS to specify a source for migration * @param aSource is a directory containing settings files to migrate from (can be empty) */ void SetMigrationSource( const wxString& aSource ) { m_migration_source = aSource; } /** * Retreives the name of the most recent previous KiCad version that can be found in the * user settings directory. For legacy versions (5.x, and 5.99 builds before this code was * written), this will return "5.x" * * @param aName is filled with the name of the previous version, if one exists * @return true if a previous version to migrate from exists */ bool GetPreviousVersionPaths( std::vector* aName = nullptr ); /** * Re-scans the color themes directory, reloading any changes it finds. */ void ReloadColorSettings(); /** * Checks if a given path is probably a valid KiCad configuration directory. * Actually it just checks if a file called "kicad_common" exists, because that's probably * good enough for now. * * @param aPath is the path to check * @return true if the path contains KiCad settings */ static bool IsSettingsPathValid( const wxString& aPath ); /** * Returns the path where color scheme files are stored * (normally ./colors/ under the user settings path) */ static std::string GetColorSettingsPath(); /** * Return the user configuration path used to store KiCad's configuration files. * * @see calculateUserSettingsPath * * NOTE: The path is cached at startup, it will never change during program lifetime! * * @return A string containing the config path for Kicad */ static std::string GetUserSettingsPath(); /** * Parses the current KiCad build version and extracts the major and minor revision to use * as the name of the settings directory for this KiCad version. * * @return a string such as "5.1" */ static std::string GetSettingsVersion(); private: /** * Determines the base path for user settings files. * * The configuration path order of precedence is determined by the following criteria: * * - The value of the KICAD_CONFIG_HOME environment variable * - The value of the XDG_CONFIG_HOME environment variable. * - The result of the call to wxStandardPaths::GetUserConfigDir() with ".config" appended * as required on Linux builds. * * @param aIncludeVer will append the current KiCad version if true (default) * @param aUseEnv will prefer the base path found in the KICAD_CONFIG_DIR if found (default) * @return A string containing the config path for Kicad */ static std::string calculateUserSettingsPath( bool aIncludeVer = true, bool aUseEnv = true ); /** * Compares two settings versions, like "5.99" and "6.0" * @return -1 if aFirst is older than aSecond, 1 if aFirst is newer than aSecond, 0 otherwise */ static int compareVersions( const std::string& aFirst, const std::string& aSecond ); /** * Extracts the numeric version from a given settings string * @param aVersionString is the string to split at the "." * @param aMajor will store the first part * @param aMinor will store the second part * @return true if extraction succeeded */ static bool extractVersion( const std::string& aVersionString, int* aMajor, int* aMinor ); /** * Attempts to load a color theme by name (the color theme directory and .json ext are assumed) * @param aName is the filename of the color theme (without the extension or path) * @return the loaded settings, or nullptr if load failed */ COLOR_SETTINGS* loadColorSettingsByName( const wxString& aName ); void registerColorSettings( const wxString& aFilename ); void loadAllColorSettings(); std::vector> m_settings; std::unordered_map m_color_settings; // Convenience shortcut COMMON_SETTINGS* m_common_settings; wxString m_migration_source; /// True if settings loaded successfully at construction bool m_ok; }; #endif