/*! * * Copyright (c) 2021-2024 Diality Inc. - All Rights Reserved. * \copyright * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * \file Settings.cpp * \author (last) Behrouz NematiPour * \date (last) 08-Aug-2023 * \author (original) Behrouz NematiPour * \date (original) 29-Mar-2021 * */ // Qt #include #include #include // Project #include "StorageGlobals.h" #include "FileHandler.h" #include "MSettings.h" #include "Logger.h" // namespace using namespace Storage; #include "Settings.h" /*! * \brief Settings::readCategory * \details Reads, parses and adds the read value to the settins. * \param vCategory - the category of the configuration file to read. * \return non-zero, error value on error, and zero on success. */ int Settings::readCategory(Category_Enum vCategory) { int err = Settings::Settings_Error::eError_None; QString msg; QFileInfo mSettingFile; QString mCategory; QString mFileName; Detail mDetail; mCategory = category(vCategory); mFileName = fileName(vCategory); qDebug() << mCategory << mFileName; mSettingFile.setFile(mFileName); QFile mFile(mSettingFile.absoluteFilePath()); if (! mFile.exists() ) { err = Settings::Settings_Error::eError_SettingNotExists ; msg = errorMessage(err, mSettingFile.fileName ()) ; goto lOut; } if (! mFile.open(QIODevice::ReadOnly | QIODevice::Text) ) { err = Settings::Settings_Error::eError_Read ; msg = errorMessage(err, Storage::Settings_Path()) ; goto lOut; } mDetail.content = mFile.readAll().trimmed(); if (mDetail.content.isEmpty() ) { err = Settings::Settings_Error::eError_Empty ; msg = errorMessage(err, mSettingFile.fileName ()) ; goto lOut; } mDetail.location = mSettingFile.absolutePath() + "/"; mDetail.category = mCategory; if ( ! parse(mDetail) ) { err = Settings::Settings_Error::eError_Parse ; msg = errorMessage(err, mSettingFile.fileName ()) ; goto lOut; } else { msg = errorMessage(err, mSettingFile.fileName ()) ; } lOut: LOG_APPED_PO( msg ); return err; } /*! * \brief Settings::readConfigurations * \details Reads all the configuration files * \return non-zero, error value on error, and zero on success. */ int Settings::readConfigurations() { int err = Settings::Settings_Error::eError_None; for ( quint8 i = 0; i <= _configurationsCount; i++ ) { readCategory(static_cast(i)); } return err; } /*! * \brief Settings::readLocale * \return */ int Settings::readLocale() { int err = Settings_Error::eError_None; err = readCategory(eConfigurationsLocale); return err; } /*! * \brief Settings::parse * \details The function to parse the content of the conf file and fill in the Settings model. * \param vDetail - the conf file detail has been read. * \return bool - true on success. */ bool Settings::parse(const Detail &vDetail) { bool enableDuplicateKey = false; QString attribute = QString("%1%2").arg(_config_attribute_tag); QString group = ""; QStringList lines = vDetail.content.split('\n'); for (QString line : lines) { // ----- trim the line line = line.trimmed(); // ----- ignore empty lines if ( line.isEmpty() ) continue; // ----- find comments int commentPosition = line.indexOf('#'); // ----- ignore comment line or find attributes if ( commentPosition == 0 ) { // ----- find the configuration file attribute int attributeTagPosition = line.indexOf(_config_attribute_tag); if ( attributeTagPosition == 0 ) { // ----- find the attribute : duplicate_key_... if ( line == attribute.arg( _duplicate_key_on ) ) { enableDuplicateKey = true ;} else if ( line == attribute.arg(_duplicate_key_off ) ) { enableDuplicateKey = false ;} else { LOG_APPED_PO(( "Unknown '" + line + "' attribute in %1").arg(vDetail.category)); return false; } } // next line continue; } // ----- remove inline comment if ( commentPosition > 0 ) line.truncate(commentPosition); line = line.trimmed(); // ----- find group if (line.startsWith("[") && line.endsWith("]")) { line.replace("[","").replace("]", ""); group = line; } else { if ( group.isEmpty() ) { continue; } else { if ( ! line.isEmpty() ) { QString key = ""; QString value = ""; if ( line.contains('=') ) { QStringList keyValue = line.split('='); key = keyValue[0].trimmed().replace("\\n","\n"); value = keyValue[1].trimmed().replace("\\n","\n"); } else { key = line; } _Settings.add(vDetail.category, group, key, QVariant(value), enableDuplicateKey); // DEBUG: qDebug() << group << key << value << location << category; } } } // DEBUG: qDebug() << group << line; } return true; } /*! * \brief Settings::save * \details Writes the setting in the configuration files * \return */ int Settings::save(const QString &vGroup, const QString &vKey, const QString &vValue, Category_Enum vCategory) { // qDebug() << vCategory // << vGroup // << vKey // << vValue; int err = Settings_Error::eError_None; QString msg; QString mCategory; QString mPath; QString mFileName; QString mContent; if ( ! isCategoryWritable(vCategory) ) { err = Settings_Error::eError_Not_Writable ; msg = errorMessage(err ); goto lOut; } mCategory = category(vCategory); mFileName = fileName(vCategory); // -------------------------------------------------------------------------------------------------------------- //Note: the configuration files which can be saved, are like settings and should not have duplicate values. // as an example the Alarm volume can't have two separate duplicate entry in the settings. // -------------------------------------------------------------------------------------------------------------- _Settings.add(mCategory, vGroup, vKey, vValue, false); mPath = QFileInfo(mFileName).absolutePath(); if ( mPath.trimmed().isEmpty() ) { err = Settings_Error::eError_PathEmpty ; msg = errorMessage(err ); goto lOut; } if ( ! FileHandler::makeFolder(mPath) ) { err = Settings_Error::eError_MkDir ; msg = errorMessage(err, mPath ); goto lOut; } for ( const auto &group : _Settings.groups(mCategory) ) { mContent += QString("\n[%1]\n").arg(group); for ( const auto &key : _Settings.keys(mCategory, group) ) { mContent += QString("%1 = %2\n").arg(key).arg(_Settings.value(mCategory, group, key).toString()); } } if ( ! FileHandler::write(mFileName,mContent, false) ) { err = Settings_Error::eError_Write ; msg = errorMessage(err, mFileName ); goto lOut; } lOut: if ( err ) LOG_DEBUG( msg ); return err; } /*! * \brief Settings::configurationsMove * \details After the encrypted partition is ready the configuration files are moved from the root home to denali home. * \param vMessage * \return */ int Settings::configurationsMove(QString *vMessage, bool vIsUpdate) { int err = Settings_Error::eError_None ; Location_Enum loc = Location_Enum ::eInit ; QString src = Settings::location(Location_Enum ::eInit ); QString dst = Settings::location(Location_Enum ::eSecured ); QString msg = ""; QStringList lstExclude; if ( vIsUpdate ) { lstExclude << QFileInfo( src + Storage::Settings_Category_SettingsSystem ).absolutePath(); } if ( ! Settings ::configurationsPOST(loc )) { err = Settings_Error::eError_Remove; msg = errorMessage(err ); goto lOut; } if ( ! FileHandler ::makeFolder ( dst )) { err = Settings_Error::eError_Copy ; msg = errorMessage(err ); goto lOut; } for( QString dir : FileHandler::subFolders(src)) { QString sub = src + dir; if ( ! lstExclude.contains( sub ) ) { if ( FileHandler ::copyFolder (sub, dst )) { err = Settings_Error::eError_MkDir ; msg = errorMessage(err, dir); goto lOut; } } if ( FileHandler ::removeFolder (sub )) { err = Settings_Error::eError_POST ; msg = errorMessage(err, dir); goto lOut; } } Storage::Settings_Secured(); lOut: if ( err ) LOG_DEBUG ( msg ); if ( vMessage ) { *vMessage = msg; } return err; } /*! * \brief Settings::loadTranslation * \return */ int Settings::loadTranslation(QTranslator &vTranslator) { int err = Settings_Error::eError_None; QString msg; QString translationFile; bool ok = true; QString locale = _Settings.systemLocale(); if( locale.isEmpty() ) { err = Settings_Error::eError_No_SettingsLocale ; msg = errorMessage(err ); goto lOut; } translationFile = fileName(eTranslation); ok = vTranslator.load(translationFile); if ( ! ok ) { err = Settings_Error::eError_TranslationNotExists ; msg = errorMessage(err, translationFile ); goto lOut; } else { msg = errorMessage(err, translationFile ); } QCoreApplication::installTranslator(&vTranslator); lOut: LOG_APPED_PO( msg ); return err; }