From f87e6207d273d16da9079e8f47ae913d456058d7 Mon Sep 17 00:00:00 2001 From: Andrey Astafyev Date: Sat, 4 Apr 2020 00:04:02 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=BF=D0=B8=D1=81?= =?UTF-8?q?=D0=B0=D0=BD=20=D0=BA=D0=BE=D0=B4=20=D0=B4=D0=BB=D1=8F=20=D1=84?= =?UTF-8?q?=D0=BE=D1=80=D0=BC=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=BF=D1=83=D1=82=D0=B5=D0=B9=20=D0=BA=20=D1=81=D1=82?= =?UTF-8?q?=D0=B0=D0=BD=D0=B4=D0=B0=D1=80=D1=82=D0=BD=D1=8B=D0=BC=20=D0=BA?= =?UTF-8?q?=D0=B0=D1=82=D0=B0=D0=BB=D0=BE=D0=B3=D0=B0=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 4 + cmake/cmlib | 2 +- examples/filesystem/01_minimal/CMakeLists.txt | 2 + examples/filesystem/01_minimal/minimal.cpp | 15 +- examples/qt/01_translators/CMakeLists.txt | 2 +- src/myx/filesystem/current_executable.cpp | 24 +- src/myx/filesystem/current_executable.hpp | 21 +- src/myx/filesystem/paths.cpp | 279 +++++++++--------- src/myx/filesystem/paths.hpp | 111 ++++--- 9 files changed, 244 insertions(+), 216 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index de7f42b..7ea3497 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,10 @@ option(BUILD_EXAMPLES "Build examples" OFF) # Поиск библиотек с помощью pkgconfig find_package(PkgConfig) +# Потоки +set(THREADS_PREFER_PTHREAD_FLAG ON) +find_package(Threads REQUIRED) + # Qt5 find_package(Qt5 COMPONENTS Core Network Gui Widgets DBus Concurrent Sql REQUIRED) diff --git a/cmake/cmlib b/cmake/cmlib index 873e295..47581bd 160000 --- a/cmake/cmlib +++ b/cmake/cmlib @@ -1 +1 @@ -Subproject commit 873e29592cf2c79986e358482fb5df67878c76b8 +Subproject commit 47581bd7b7b8249dbd2854bf6bb4705d9612ba28 diff --git a/examples/filesystem/01_minimal/CMakeLists.txt b/examples/filesystem/01_minimal/CMakeLists.txt index d54eddc..44fd888 100644 --- a/examples/filesystem/01_minimal/CMakeLists.txt +++ b/examples/filesystem/01_minimal/CMakeLists.txt @@ -32,6 +32,8 @@ target_compile_options(${current_target} PUBLIC "${Qt5Core_EXECUTABLE_COMPILE_FL target_link_libraries(${current_target} myx-filesystem) target_link_libraries(${current_target} Qt5::Core) +target_link_libraries(${current_target} Threads::Threads) + # Имя выходного файла для цели set_target_properties(${current_target} diff --git a/examples/filesystem/01_minimal/minimal.cpp b/examples/filesystem/01_minimal/minimal.cpp index deb06ef..de3ba58 100644 --- a/examples/filesystem/01_minimal/minimal.cpp +++ b/examples/filesystem/01_minimal/minimal.cpp @@ -1,3 +1,5 @@ +#include "cmlib_private_config.hpp" + #include #include @@ -6,17 +8,20 @@ namespace MF = myx::filesystem; +// Переменные для защиты экземпляра класса MF::Paths +std::atomic< MF::Paths* > MF::Paths::m_instance; +std::mutex MF::Paths::m_mutex; int main( int argc, char** argv ) { (void)argc; (void)argv; - QCoreApplication::setApplicationName( PROJECT_NAME ); - MF::Paths paths; + QCoreApplication::setApplicationName( CMLIB_PROJECT_NAME ); + MF::Paths* paths = MF::Paths::getInstance(); - paths.updatePaths(); - paths.makeDefaultDirectories(); - paths.findConfigFile( "test" ); + paths->init( CMLIB_PROJECT_NAME, "conf" ); + paths->makeDefaultDirectories(); + paths->findConfigFile( "test" ); return( 0 ); } diff --git a/examples/qt/01_translators/CMakeLists.txt b/examples/qt/01_translators/CMakeLists.txt index ab401fd..6b449dc 100644 --- a/examples/qt/01_translators/CMakeLists.txt +++ b/examples/qt/01_translators/CMakeLists.txt @@ -25,7 +25,7 @@ add_dependencies(${current_target} base) add_dependencies(${current_target} qt) # Qt5 -qt_translation(TARGET ${current_target} TS_DIR ${CMAKE_SOURCE_DIR}/l10n LANGUAGES ru_RU) +qt5_translation(TARGET ${current_target} TS_DIR ${CMAKE_SOURCE_DIR}/l10n LANGUAGES ru_RU) target_include_directories(${current_target} PRIVATE ${CMAKE_SOURCE_DIR}/src) target_include_directories(${current_target} SYSTEM PUBLIC ${Qt5Core_INCLUDE_DIRS}) target_compile_options(${current_target} PUBLIC "${Qt5Core_EXECUTABLE_COMPILE_FLAGS}") diff --git a/src/myx/filesystem/current_executable.cpp b/src/myx/filesystem/current_executable.cpp index 1775326..7664499 100644 --- a/src/myx/filesystem/current_executable.cpp +++ b/src/myx/filesystem/current_executable.cpp @@ -9,34 +9,22 @@ namespace myx { namespace filesystem { +#if !defined ( __linux__ ) +error "Class CurrentExecutable is supported only in Linux" +#endif + CurrentExecutable::CurrentExecutable() : m_procFilePath( QStringLiteral( "/proc/self/exe" ) ) { - auto canonicalFilePath = m_procFilePath.canonicalFilePath(); - auto canonicalPath = m_procFilePath.canonicalPath(); - m_fileName = canonicalFilePath.remove( canonicalPath ).remove( '/' ); - m_canonicalFilePath = canonicalFilePath; - m_canonicalPath = canonicalPath; + m_canonicalFilePath = m_procFilePath.canonicalFilePath(); } -QFileInfo CurrentExecutable::canonicalFilePath() const +const QFileInfo& CurrentExecutable::canonicalFilePath() const { return( m_canonicalFilePath ); } - -QDir CurrentExecutable::canonicalPath() const -{ - return( m_canonicalPath ); -} - - -QString CurrentExecutable::fileName() const -{ - return( m_fileName ); -} - } // namespace filesystem } // namespace myx diff --git a/src/myx/filesystem/current_executable.hpp b/src/myx/filesystem/current_executable.hpp index 4ddd16b..2c24283 100644 --- a/src/myx/filesystem/current_executable.hpp +++ b/src/myx/filesystem/current_executable.hpp @@ -19,34 +19,23 @@ namespace filesystem { class CurrentExecutable { - /// Путь к символической ссылке, указывающей на текущий исполняемый файл + /// @brief Путь к символической ссылке, указывающей на текущий исполняемый файл QFileInfo m_procFilePath; - /// Канонический путь к текущему исполняемому файлу + + /// @brief Канонический путь к текущему исполняемому файлу QFileInfo m_canonicalFilePath; - /// Канонический путь к каталогу с текущим исполняемым файлом - QDir m_canonicalPath; - /// Имя текущего исполняемого файла - QString m_fileName; friend class Paths; public: /** * @brief Конструктор, собирающий информацию о текущем исполняемом файле. - * Иницализируются все внутренние переменные. */ CurrentExecutable(); + /** * @brief Канонический путь к текущему исполняемому файлу */ - QFileInfo canonicalFilePath() const; - /** - * @brief Канонический путь к каталогу с текущим исполняемым файлом - */ - QDir canonicalPath() const; - /** - * @brief Имя текущего исполняемого файла - */ - QString fileName() const; + const QFileInfo& canonicalFilePath() const; }; // class CurrentExecutable } // namespace filesystem diff --git a/src/myx/filesystem/paths.cpp b/src/myx/filesystem/paths.cpp index b6fedfd..2f6c4e2 100644 --- a/src/myx/filesystem/paths.cpp +++ b/src/myx/filesystem/paths.cpp @@ -10,77 +10,152 @@ namespace myx { namespace filesystem { -Paths::Paths( QString configFileExtension ) : - m_prefixDirectory ( "/opt/" + QCoreApplication::organizationName().toLower() + - "/" + QCoreApplication::applicationName().toLower() ), - m_configFileExtension ( std::move( configFileExtension ) ), - m_projectDirectoryName( QCoreApplication::applicationName().toLower() ) +Paths::Paths() { - auto pd = m_prefixDirectory.absolutePath(); - m_binaryDirectory = pd + "/bin"; -// m_systemConfigDirectory = pd + "/etc/" + m_projectDirectoryName; -// m_userCacheDirectory = pd + "/var/lib/" + m_projectDirectoryName; -// m_logDirectory = pd + "/var/log/" + m_projectDirectoryName; -// m_dataDirectory = pd + "/share/" + m_projectDirectoryName; -// m_tempDirectory = QString::fromLocal8Bit( qgetenv( qPrintable( "TMPDIR" ) ) ); -// m_homeDirectory = QString::fromLocal8Bit( qgetenv( qPrintable( "HOME" ) ) ); -// m_configFileName = m_projectDirectoryName + "." + m_configFileExtension; -// m_configFilePath = m_systemConfigDirectory.absolutePath() + "/" + m_configFileName; - -// if ( m_tempDirectory.absolutePath().isEmpty() || ( m_tempDirectory.path() == "." ) ) -// { -// m_tempDirectory = QStringLiteral( _PATH_TMP ); -// } } -bool Paths::updatePaths() +Paths::HierarchyType Paths::getHierarchyType() { - m_binaryDirectory = m_currentExecutable.canonicalPath(); + QRegExp binRegexp( "/s*bin$" ); + auto binaryDir = m_currentExecutable.m_canonicalFilePath.canonicalPath(); -// if ( m_binaryDirectory.absolutePath().endsWith( "/bin" ) ) -// { -// m_prefixDirectory = m_binaryDirectory.absolutePath().remove( QRegExp( "/bin$" ) ); -// m_systemConfigDirectory = m_prefixDirectory.absolutePath() + "/etc/" + m_projectDirectoryName; -// m_userCacheDirectory = m_prefixDirectory.absolutePath() + "/var/lib/" + m_projectDirectoryName; -// m_logDirectory = m_prefixDirectory.absolutePath() + "/var/log/" + m_projectDirectoryName; -// m_dataDirectory = m_prefixDirectory.absolutePath() + "/share/" + m_projectDirectoryName; -// m_configFilePath = QFile( m_systemConfigDirectory.absolutePath() + -// "/" + QCoreApplication::applicationName() + -// "." + m_configFileExtension ); -// } + if ( binRegexp.indexIn( binaryDir ) == -1 ) + { + return ( HierarchyType::kFlat ); + } -// if ( m_prefixDirectory.absolutePath().startsWith( "/opt" ) || -// m_prefixDirectory.absolutePath().startsWith( "/usr" ) ) -// { -// QString dataDirectory = QString::fromLocal8Bit( qgetenv( qPrintable( "XDG_DATA_HOME" ) ) ); -// if ( dataDirectory.isEmpty() ) -// { -// dataDirectory = m_homeDirectory.absolutePath() + ".local/share"; -// } -// m_dataDirectory = dataDirectory + "/" + -// QCoreApplication::organizationName().toLower() + "/" + -// QCoreApplication::applicationName().toLower(); + if ( binaryDir.startsWith( "/opt" ) ) + { + QFileInfo etcDirInfo { "/opt/" + m_projectName + "/etc" }; + if ( !etcDirInfo.isDir() || !etcDirInfo.isReadable() ) { return( HierarchyType::kFlat ); } -// QString configDirectory = QString::fromLocal8Bit( qgetenv( qPrintable( "XDG_CONFIG_HOME" ) ) ); -// if ( configDirectory.isEmpty() ) -// { -// configDirectory = m_homeDirectory.absolutePath() + ".config"; -// } -// m_systemConfigDirectory = configDirectory + "/" + -// QCoreApplication::organizationName().toLower() + "/" + -// QCoreApplication::applicationName().toLower(); + QFileInfo constDataDirInfo { "/opt/" + m_projectName + "/files/data" }; + if ( !constDataDirInfo.isDir() || !constDataDirInfo.isReadable() ) { return( HierarchyType::kFlat ); } -// QString cacheDirectory = QString::fromLocal8Bit( qgetenv( qPrintable( "XDG_CACHE_HOME" ) ) ); -// if ( cacheDirectory.isEmpty() ) -// { -// cacheDirectory = m_homeDirectory.absolutePath() + ".cache"; -// } -// m_userCacheDirectory = cacheDirectory + "/" + -// QCoreApplication::organizationName().toLower() + "/" + -// QCoreApplication::applicationName().toLower(); -// m_logDirectory = m_userCacheDirectory.absolutePath() + "/log"; -// } + QFileInfo varDataDirInfo { "/opt/" + m_projectName + "/files/lib" }; + if ( !varDataDirInfo.isDir() || !varDataDirInfo.isWritable() ) { return( HierarchyType::kFlat ); } + + QFileInfo logDirInfo { "/opt/" + m_projectName + "/files/log" }; + if ( !logDirInfo.isDir() || !logDirInfo.isWritable() ) { return( HierarchyType::kFlat ); } + + m_systemConfigDirectory = etcDirInfo.canonicalFilePath(); + m_systemConstDataDirectory = constDataDirInfo.canonicalFilePath(); + m_systemVarDataDirectory = varDataDirInfo.canonicalFilePath(); + m_systemLogDirectory = logDirInfo.canonicalFilePath(); + + return ( HierarchyType::kOpt ); + } + + if ( binaryDir.startsWith( "/usr" ) ) + { + QFileInfo etcDirInfo { "/etc/" + m_projectName }; + if ( !etcDirInfo.isDir() || !etcDirInfo.isReadable() ) { return( HierarchyType::kFlat ); } + + QFileInfo constDataDirInfo { "/usr/share/" + m_projectName }; + if ( !constDataDirInfo.isDir() || !constDataDirInfo.isReadable() ) { return( HierarchyType::kFlat ); } + + QFileInfo varDataDirInfo { "/var/lib/" + m_projectName }; + if ( !varDataDirInfo.isDir() || !varDataDirInfo.isWritable() ) { return( HierarchyType::kFlat ); } + + QFileInfo logDirInfo { "/var/log/" + m_projectName }; + if ( !logDirInfo.isDir() || !logDirInfo.isWritable() ) { return( HierarchyType::kFlat ); } + + m_systemConfigDirectory = etcDirInfo.canonicalFilePath(); + m_systemConstDataDirectory = constDataDirInfo.canonicalFilePath(); + m_systemVarDataDirectory = varDataDirInfo.canonicalFilePath(); + m_systemLogDirectory = logDirInfo.canonicalFilePath(); + + return ( HierarchyType::kStandard ); + } + + if ( binaryDir.startsWith( m_homeDirectory.canonicalPath() + "/.local/bin" ) || + binaryDir.startsWith( m_homeDirectory.canonicalPath() + "/bin" ) ) + { + QFileInfo etcDirInfo { m_userConfigDirectory.canonicalPath() }; + if ( !etcDirInfo.isDir() || !etcDirInfo.isReadable() ) { return( HierarchyType::kFlat ); } + + QFileInfo constDataDirInfo { m_userConstDataDirectory.canonicalPath() }; + if ( !constDataDirInfo.isDir() || !constDataDirInfo.isReadable() ) { return( HierarchyType::kFlat ); } + + QFileInfo varDataDirInfo { m_userVarDataDirectory.canonicalPath() }; + if ( !varDataDirInfo.isDir() || !varDataDirInfo.isWritable() ) { return( HierarchyType::kFlat ); } + + QFileInfo logDirInfo { m_userLogDirectory.canonicalPath() }; + if ( !logDirInfo.isDir() || !logDirInfo.isWritable() ) { return( HierarchyType::kFlat ); } + + m_systemConfigDirectory = etcDirInfo.canonicalFilePath(); + m_systemConstDataDirectory = constDataDirInfo.canonicalFilePath(); + m_systemVarDataDirectory = varDataDirInfo.canonicalFilePath(); + m_systemLogDirectory = logDirInfo.canonicalFilePath(); + + return( HierarchyType::kHome ); + } + + binaryDir.remove( binRegexp ); + + QFileInfo etcDirInfo { binaryDir + "/etc" }; + if ( !etcDirInfo.isDir() || !etcDirInfo.isReadable() ) { return( HierarchyType::kFlat ); } + + QFileInfo constDataDirInfo { binaryDir + "/files/data" }; + if ( !constDataDirInfo.isDir() || !constDataDirInfo.isReadable() ) { return( HierarchyType::kFlat ); } + + QFileInfo varDataDirInfo { binaryDir + "/files/lib" }; + if ( !varDataDirInfo.isDir() || !varDataDirInfo.isWritable() ) { return( HierarchyType::kFlat ); } + + QFileInfo logDirInfo { binaryDir + "/files/log" }; + if ( !logDirInfo.isDir() || !logDirInfo.isWritable() ) { return( HierarchyType::kFlat ); } + + m_systemConfigDirectory = etcDirInfo.canonicalFilePath(); + m_systemConstDataDirectory = constDataDirInfo.canonicalFilePath(); + m_systemVarDataDirectory = varDataDirInfo.canonicalFilePath(); + m_systemLogDirectory = logDirInfo.canonicalFilePath(); + + return ( HierarchyType::kUser ); +} // Paths::getHierarchyType + + +bool Paths::init( const QString& projectDir, const QString& configFileExtension ) +{ + m_projectName = projectDir.isEmpty() ? m_currentExecutable.m_canonicalFilePath.fileName() + : projectDir; + m_configFileExtension = configFileExtension.isEmpty() ? "conf" + : configFileExtension; + m_configFileName = m_projectName + "." + m_configFileExtension; + + m_homeDirectory = QString::fromLocal8Bit( qgetenv( qPrintable( "HOME" ) ) ); + m_tempDirectory = QString::fromLocal8Bit( qgetenv( qPrintable( "TMPDIR" ) ) ); + if ( m_tempDirectory.canonicalPath().isEmpty() || ( m_tempDirectory.path() == "." ) ) + { + m_tempDirectory = QStringLiteral( _PATH_TMP ); + } + + auto configHome { QString::fromLocal8Bit( qgetenv( qPrintable( "XDG_CONFIG_HOME" ) ) ) }; + if ( configHome.isEmpty() ) + { + configHome = m_homeDirectory.canonicalPath() + "/.config"; + } + m_userConfigDirectory = configHome + "/" + m_projectName; + + auto dataHome { QString::fromLocal8Bit( qgetenv( qPrintable( "XDG_DATA_HOME" ) ) ) }; + if ( dataHome.isEmpty() ) + { + dataHome = m_homeDirectory.canonicalPath() + "/.local/share"; + } + dataHome += "/" + m_projectName; + m_userConstDataDirectory = dataHome + "/data"; + m_userVarDataDirectory = dataHome + "/lib"; + m_userLogDirectory = dataHome + "/log"; + + m_hierarchyType = getHierarchyType(); + + if ( m_hierarchyType == HierarchyType::kFlat ) + { + m_systemConstDataDirectory = m_currentExecutable.m_canonicalFilePath.canonicalPath(); + m_systemVarDataDirectory = m_currentExecutable.m_canonicalFilePath.canonicalPath(); + m_systemConfigDirectory = m_currentExecutable.m_canonicalFilePath.canonicalPath(); + m_systemLogDirectory = m_currentExecutable.m_canonicalFilePath.canonicalPath(); + } return( true ); } // Paths::updatePaths @@ -100,7 +175,7 @@ bool Paths::makeDefaultDirectories() QString Paths::findConfigFile( const QString& defaultConfigFile ) { - if ( QFileInfo( defaultConfigFile ).isReadable() ) + if ( !defaultConfigFile.isEmpty() && QFileInfo( defaultConfigFile ).isReadable() ) { m_configFilePath = defaultConfigFile; return( defaultConfigFile ); @@ -123,27 +198,9 @@ QString Paths::findConfigFile( const QString& defaultConfigFile ) } // Paths::findConfigFile -const QDir& Paths::prefixDirectory() const +QDir Paths::binaryDirectory() const { - return( m_prefixDirectory ); -} - - -void Paths::setPrefixDirectory( const QString& prefixDirectory ) -{ - m_prefixDirectory = prefixDirectory; -} - - -const QDir& Paths::binaryDirectory() const -{ - return( m_binaryDirectory ); -} - - -void Paths::setBinaryDirectory( const QString& binaryDirectory ) -{ - m_binaryDirectory = binaryDirectory; + return( m_currentExecutable.m_canonicalFilePath.dir() ); } @@ -171,18 +228,6 @@ void Paths::setSystemConfigDirectory( const QString& systemConfigDirectory ) } -const QDir& Paths::localConfigDirectory() const -{ - return( m_localConfigDirectory ); -} - - -void Paths::setLocalConfigDirectory( const QString& localConfigDirectory ) -{ - m_localConfigDirectory = localConfigDirectory; -} - - const QFileInfo& Paths::configFilePath() const { return( m_configFilePath ); @@ -243,18 +288,6 @@ void Paths::setSystemVarDataDirectory( const QString& systemVarDataDirectory ) } -const QDir& Paths::localVarDataDirectory() const -{ - return( m_localVarDataDirectory ); -} - - -void Paths::setLocalVarDataDirectory( const QString& localVarDataDirectory ) -{ - m_localVarDataDirectory = localVarDataDirectory; -} - - const QDir& Paths::userConstDataDirectory() const { return( m_userConstDataDirectory ); @@ -279,18 +312,6 @@ void Paths::setSystemConstDataDirectory( const QString& systemConstDataDirectory } -const QDir& Paths::localConstDataDirectory() const -{ - return( m_localConstDataDirectory ); -} - - -void Paths::setLocalConstDataDirectory( const QString& localConstDataDirectory ) -{ - m_localConstDataDirectory = localConstDataDirectory; -} - - const QDir& Paths::userLogDirectory() const { return( m_userLogDirectory ); @@ -315,18 +336,6 @@ void Paths::setSystemLogDirectory( const QString& systemLogDirectory ) } -const QDir& Paths::localLogDirectory() const -{ - return( m_localLogDirectory ); -} - - -void Paths::setLocalLogDirectory( const QString& localLogDirectory ) -{ - m_localLogDirectory = localLogDirectory; -} - - const QDir& Paths::tempDirectory() const { return( m_tempDirectory ); @@ -347,19 +356,19 @@ const QDir& Paths::homeDirectory() const const QString& Paths::projectDirectoryName() const { - return( m_projectDirectoryName ); + return( m_projectName ); } void Paths::setProjectDirectoryName( const QString& projectDirectoryName ) { - m_projectDirectoryName = projectDirectoryName; + m_projectName = projectDirectoryName; } -const QString& Paths::executableFileName() const +QString Paths::executableFileName() const { - return( m_currentExecutable.m_fileName ); + return( m_currentExecutable.m_canonicalFilePath.fileName() ); } diff --git a/src/myx/filesystem/paths.hpp b/src/myx/filesystem/paths.hpp index 65dc542..4a374a2 100644 --- a/src/myx/filesystem/paths.hpp +++ b/src/myx/filesystem/paths.hpp @@ -14,6 +14,10 @@ #include #include +#include +#include +#include +#include namespace myx { @@ -21,17 +25,50 @@ namespace filesystem { class Paths { - /// @brief Путь к базовому каталогу - QDir m_prefixDirectory; - /// @brief Путь к каталогу с исполняемым файлом - QDir m_binaryDirectory; + enum class HierarchyType : intptr_t + { + kSplit = 0x00, + kFlat = 0x01, + kOpt = 0x02, + kStandard = 0x04, + kUser = 0x08, + kHome = 0x10, + }; + + /// @brief Тип расположения файлов по каталогам + HierarchyType m_hierarchyType { HierarchyType::kFlat }; + + /// @brief Параметры текущего исполняемого файла + CurrentExecutable m_currentExecutable; + + /// @brief Имя проекта, которое используется при формировании имён файлов и каталогов + QString m_projectName; + + /// @brief Путь к каталогу с временными файлами + QDir m_tempDirectory; + /// @brief Путь к домашнему каталогу текущего пользователя + QDir m_homeDirectory; + + /// @brief Путь к пользовательскому каталогу с изменяемыми файлами + QDir m_userVarDataDirectory; + /// @brief Путь к системному каталогу с изменяемыми файлами + QDir m_systemVarDataDirectory; + + /// @brief Путь к пользовательскому каталогу с неизменяемыми файлами + QDir m_userConstDataDirectory; + /// @brief Путь к системному каталогу с неизменяемыми файлами + QDir m_systemConstDataDirectory; + + /// @brief Путь к пользовательскому каталогу с журналами работы + QDir m_userLogDirectory; + /// @brief Путь к системному каталогу с журналами работы + QDir m_systemLogDirectory; /// @brief Путь к пользовательскому каталогу с файлами настройки QDir m_userConfigDirectory; /// @brief Путь к системному каталогу с файлами настройки QDir m_systemConfigDirectory; - /// @brief Путь к локальному каталогу с файлами настройки - QDir m_localConfigDirectory; + /// @brief Полный путь к файлу настройки QFileInfo m_configFilePath; /// @brief Имя файла настройки @@ -39,48 +76,42 @@ class Paths /// @brief Расширение для файла настройки QString m_configFileExtension; - /// @brief Путь к пользовательскому каталогу с изменяемыми файлами - QDir m_userVarDataDirectory; - /// @brief Путь к системному каталогу с изменяемыми файлами - QDir m_systemVarDataDirectory; - /// @brief Путь к локальному каталогу с изменяемыми файлами - QDir m_localVarDataDirectory; + Paths(); + ~Paths() = default; + Paths( const Paths& ) = delete; + Paths& operator=( const Paths& ) = delete; - /// @brief Путь к пользовательскому каталогу с неизменяемыми файлами - QDir m_userConstDataDirectory; - /// @brief Путь к системному каталогу с неизменяемыми файлами - QDir m_systemConstDataDirectory; - /// @brief Путь к локальному каталогу с неизменяемыми файлами - QDir m_localConstDataDirectory; + HierarchyType getHierarchyType(); - /// @brief Путь к пользовательскому каталогу с журналами работы - QDir m_userLogDirectory; - /// @brief Путь к системному каталогу с журналами работы - QDir m_systemLogDirectory; - /// @brief Путь к локальному каталогу с журналами работы - QDir m_localLogDirectory; - - /// @brief Путь к каталогу с временными файлами - QDir m_tempDirectory; - /// @brief Путь к домашнему каталогу текущего пользователя - QDir m_homeDirectory; - /// @brief Имя подкаталога для проекта - QString m_projectDirectoryName; - - /// Параметры текущего исполняемого файла - CurrentExecutable m_currentExecutable; + static std::atomic< Paths* > m_instance; + static std::mutex m_mutex; public: /** - * @brief Конструктор - * @param configFileExtension Расширение для файла настройки + * @brief getInstance + * @return Уникальный экземпляр класса Paths */ - Paths( QString configFileExtension = "conf" ); + static Paths* getInstance() + { + Paths* localInstance = m_instance.load( std::memory_order_acquire ); + if ( !localInstance ) + { + std::lock_guard< std::mutex > myLock( m_mutex ); + localInstance = m_instance.load( std::memory_order_relaxed ); + if ( !localInstance ) + { + localInstance = new Paths(); + m_instance.store( localInstance, std::memory_order_release ); + } + } + return( localInstance ); + } + /** * @brief Обновление путей с учётом расположения исполняемого файла */ - bool updatePaths(); + bool init( const QString& projectDir, const QString& configFileExtension = "conf" ); /** * @brief Создание стандартных каталогов @@ -109,7 +140,7 @@ public: /** * @brief Получение пути к каталогу с исполняемым файлом */ - const QDir& binaryDirectory() const; + QDir binaryDirectory() const; /** * @brief Установка пути к каталогу с исполняемым файлом */ @@ -276,7 +307,7 @@ public: /** * @brief Имя исполняемого файла */ - const QString& executableFileName() const; + QString executableFileName() const; /** * @brief Полный путь к исполняемому файлу */