From 2f009db53c237b043e79a9d3d2111dd7a9c503b2 Mon Sep 17 00:00:00 2001
From: Alexander <aleksandr.martynov@demlabs.net>
Date: Wed, 16 Oct 2019 06:19:56 -0400
Subject: [PATCH] [*] update class DapSettings

- fix arguments according to inner code style
- add guard for geetting/setting group/value
- delete useless temporary objects
- delete useless virtual methods encrypt/decrypt. This method will added
to future in special class
---
 CellFrameDashboard.pro                        |   3 +-
 .../CellFrameDashboardGUI.pro                 |   1 +
 .../DapServiceController.cpp                  |  28 +++
 CellFrameDashboardGUI/DapServiceController.h  |  11 +
 .../DapChainDashboardService.cpp              |   3 +
 .../DapChainDashboardService.h                |   3 +
 .../DapChainNodeNetworkHandler.cpp            |   5 +
 .../DapChainNodeNetworkHandler.h              |   5 +
 CellFrameDashboardService/main.cpp            |   2 +
 CellFrameDashboardTests/.gitignore            |  73 ++++++
 .../CellFrameDashboardTests.pro               |  18 ++
 CellFrameDashboardTests/DapSettingsTests.cpp  | 158 ++++++++++++
 CellFrameDashboardTests/gtest_dependency.pri  |  32 +++
 CellFrameDashboardTests/main.cpp              |   9 +
 libCellFrameDashboardCommon/DapSettings.cpp   | 232 ++++++++++--------
 libCellFrameDashboardCommon/DapSettings.h     |  53 ++--
 .../DapSettingsCipher.cpp                     |   6 +-
 .../DapSettingsCipher.h                       |   4 +-
 18 files changed, 510 insertions(+), 136 deletions(-)
 create mode 100644 CellFrameDashboardTests/.gitignore
 create mode 100644 CellFrameDashboardTests/CellFrameDashboardTests.pro
 create mode 100644 CellFrameDashboardTests/DapSettingsTests.cpp
 create mode 100644 CellFrameDashboardTests/gtest_dependency.pri
 create mode 100644 CellFrameDashboardTests/main.cpp

diff --git a/CellFrameDashboard.pro b/CellFrameDashboard.pro
index 14df6c1..c8b3e54 100755
--- a/CellFrameDashboard.pro
+++ b/CellFrameDashboard.pro
@@ -1,5 +1,6 @@
 TEMPLATE = subdirs
-SUBDIRS = CellFrameDashboardGUI CellFrameDashboardService
+SUBDIRS = CellFrameDashboardGUI CellFrameDashboardService \
+    CellFrameDashboardTests
 
 CellFrameDashboardGUI.subdir = CellFrameDashboardGUI
 CellFrameDashboardService.subdir = CellFrameDashboardService
diff --git a/CellFrameDashboardGUI/CellFrameDashboardGUI.pro b/CellFrameDashboardGUI/CellFrameDashboardGUI.pro
index f59cc93..733747a 100755
--- a/CellFrameDashboardGUI/CellFrameDashboardGUI.pro
+++ b/CellFrameDashboardGUI/CellFrameDashboardGUI.pro
@@ -33,6 +33,7 @@ DEFINES += QT_DEPRECATED_WARNINGS
 DEFINES += DAP_BRAND=\\\"$$BRAND\\\"
 DEFINES += DAP_SERVICE_NAME=\\\"CellFrameDashboardService\\\"
 DEFINES += DAP_VERSION=\\\"$$VERSION\\\"
+DEFINES += DAP_SETTINGS_FILE=\\\"settings.json\\\"
 ICON = icon.ico
 # You can also make your code fail to compile if you use deprecated APIs.
 # In order to do so, uncomment the following line.
diff --git a/CellFrameDashboardGUI/DapServiceController.cpp b/CellFrameDashboardGUI/DapServiceController.cpp
index 3792b81..25aece1 100755
--- a/CellFrameDashboardGUI/DapServiceController.cpp
+++ b/CellFrameDashboardGUI/DapServiceController.cpp
@@ -2,6 +2,7 @@
 #include "DapUiQmlWidgetModel.h"
 #include "DapLogMessage.h"
 #include "DapChainWallet.h"
+#include "DapSettings.h"
 
 #include <QRegularExpression>
 
@@ -33,6 +34,7 @@ void DapServiceController::init(DapServiceClient *apDapServiceClient)
     m_pDapServiceClient = apDapServiceClient;
 
     connect(m_pDapServiceClient, SIGNAL(sigDisconnected()), SLOT(clearLogModel()));
+    connect(m_pDapServiceClient, SIGNAL(sigConnected()), SLOT(loadUserSettings()));
     
     // Creating rpc controller
     m_pDapCommandController = new DapCommandController(apDapServiceClient->getClientSocket(), this);
@@ -84,6 +86,11 @@ QString DapServiceController::getVersion() const
     return m_sVersion;
 }
 
+QString DapServiceController::getSettingFile() const
+{
+    return m_sSettingFile;
+}
+
 QString DapServiceController::getResult()
 {
     return m_sResult;
@@ -238,6 +245,27 @@ void DapServiceController::getNetworkList()
     m_pDapCommandController->getNetworkList();
 }
 
+void DapServiceController::loadUserSettings()
+{
+    const QString networkName = DapSettings::getInstance(m_sSettingFile)
+            .getKeyValue("network").toString();
+    qInfo() << "get settings name: " << networkName;
+    int currentIndex = DapSettingsNetworkModel::getInstance().getCurrentIndex();
+    qInfo() << "current index is " << currentIndex;
+    DapSettingsNetworkModel::getInstance().setCurrentNetwork(networkName, ++currentIndex);
+    qInfo() << "change Current Network: " << DapSettingsNetworkModel::getInstance().getCurrentNetwork();
+    emit userSettingsLoaded();
+}
+
+void DapServiceController::saveUserSettings()
+{
+    DapSettings::getInstance().setFileName(m_sSettingFile);
+    QJsonObject networkObject;
+    networkObject["network"] = DapSettingsNetworkModel::getInstance().getCurrentNetwork();
+    qInfo() << "Save to file: " << networkObject;
+    DapSettings::getInstance().writeFile(QJsonDocument(networkObject));
+    emit userSettingsSaved();
+}
 
 /// Get an instance of a class.
 /// @return Instance of a class.
diff --git a/CellFrameDashboardGUI/DapServiceController.h b/CellFrameDashboardGUI/DapServiceController.h
index e93daea..a7bf7ae 100755
--- a/CellFrameDashboardGUI/DapServiceController.h
+++ b/CellFrameDashboardGUI/DapServiceController.h
@@ -26,6 +26,8 @@ class DapServiceController : public QObject
     QString m_sBrand {DAP_BRAND};
     /// Application version.
     QString m_sVersion {DAP_VERSION};
+    /// Settings file.
+    QString m_sSettingFile {DAP_SETTINGS_FILE};
     /// Result execute.
     QString m_sResult;
 
@@ -62,6 +64,9 @@ public:
     /// Get app version.
     /// @return Application version.
     QString getVersion() const;
+    /// Get setting file name.
+    /// @return Setting file name
+    QString getSettingFile() const;
     /// Get result command execute.
     /// @return Result execute.
     QString getResult();
@@ -101,6 +106,8 @@ signals:
     void sendToQML(QString);
 	void logCompleted();
     void sendNodeNetwork(const QVariant& aData);
+    void userSettingsLoaded();
+    void userSettingsSaved();
 
 private slots:
     /// Handling service response for receiving node logs.
@@ -140,6 +147,10 @@ public slots:
     void activateClient(bool aIsActivated);
     /// Shut down client.
     void closeClient();
+    /// Load user settings from settings file
+    void loadUserSettings();
+    /// Save user settings to file
+    void saveUserSettings();
     /// Method that implements the singleton pattern for the qml layer.
     /// @param engine QML application.
     /// @param scriptEngine The QJSEngine class provides an environment for evaluating JavaScript code.
diff --git a/CellFrameDashboardService/DapChainDashboardService.cpp b/CellFrameDashboardService/DapChainDashboardService.cpp
index d12ef45..42f1493 100755
--- a/CellFrameDashboardService/DapChainDashboardService.cpp
+++ b/CellFrameDashboardService/DapChainDashboardService.cpp
@@ -1,5 +1,7 @@
 #include "DapChainDashboardService.h"
 
+#include "DapSettings.h"
+
 DapChainDashboardService::DapChainDashboardService() : DapRpcService(nullptr)
 {
     // Log reader
@@ -20,6 +22,7 @@ DapChainDashboardService::DapChainDashboardService() : DapRpcService(nullptr)
 
     m_pDapChainConsoleHandler = new DapChainConsoleHandler(this);
 
+
 }
 
 bool DapChainDashboardService::start()
diff --git a/CellFrameDashboardService/DapChainDashboardService.h b/CellFrameDashboardService/DapChainDashboardService.h
index 85144bd..5b3ce78 100755
--- a/CellFrameDashboardService/DapChainDashboardService.h
+++ b/CellFrameDashboardService/DapChainDashboardService.h
@@ -64,6 +64,9 @@ public:
 signals:
     /// The signal is emitted in case of successful connection of a new client.
     void onNewClientConnected();
+    // TODO get structure Settings which has method fill from jsonDocument
+    /// The signal is emitted in case of need to save setting
+    void onSaveSetting();
     
 public slots:
     void changedLogModel();
diff --git a/CellFrameDashboardService/DapChainNodeNetworkHandler.cpp b/CellFrameDashboardService/DapChainNodeNetworkHandler.cpp
index 52fda11..88edcd2 100644
--- a/CellFrameDashboardService/DapChainNodeNetworkHandler.cpp
+++ b/CellFrameDashboardService/DapChainNodeNetworkHandler.cpp
@@ -6,6 +6,11 @@ DapChainNodeNetworkHandler::DapChainNodeNetworkHandler(QObject *parent) : QObjec
 
 }
 
+const QString &DapChainNodeNetworkHandler::getCurrentNetwork() const
+{
+    return m_CurrentNetwork;
+}
+
 QVariant DapChainNodeNetworkHandler::getNodeNetwork() const
 {
     QProcess process;
diff --git a/CellFrameDashboardService/DapChainNodeNetworkHandler.h b/CellFrameDashboardService/DapChainNodeNetworkHandler.h
index ab57a37..258ab1e 100644
--- a/CellFrameDashboardService/DapChainNodeNetworkHandler.h
+++ b/CellFrameDashboardService/DapChainNodeNetworkHandler.h
@@ -19,6 +19,11 @@ private:
 public:
     explicit DapChainNodeNetworkHandler(QObject *parent = nullptr);
 
+public:
+    /// Get current network name
+    /// @return name of current network
+    const QString& getCurrentNetwork() const;
+
 public slots:
     /// Change status of a node
     /// @param it is true if a node is online
diff --git a/CellFrameDashboardService/main.cpp b/CellFrameDashboardService/main.cpp
index 29d3122..af8c771 100755
--- a/CellFrameDashboardService/main.cpp
+++ b/CellFrameDashboardService/main.cpp
@@ -9,6 +9,7 @@
 #include "DapChainDashboardService.h"
 #include "DapLogger.h"
 #include "DapChainLogHandler.h"
+#include "DapSettings.h"
 
 void processArgs();
 
@@ -44,6 +45,7 @@ int main(int argc, char *argv[])
     processArgs();
     DapChainDashboardService service;
     service.start();
+
     // Initialization of the application in the system tray
 //    service.initTray();
 
diff --git a/CellFrameDashboardTests/.gitignore b/CellFrameDashboardTests/.gitignore
new file mode 100644
index 0000000..fab7372
--- /dev/null
+++ b/CellFrameDashboardTests/.gitignore
@@ -0,0 +1,73 @@
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+
diff --git a/CellFrameDashboardTests/CellFrameDashboardTests.pro b/CellFrameDashboardTests/CellFrameDashboardTests.pro
new file mode 100644
index 0000000..42b3c41
--- /dev/null
+++ b/CellFrameDashboardTests/CellFrameDashboardTests.pro
@@ -0,0 +1,18 @@
+include(gtest_dependency.pri)
+include (../libCellFrameDashboardCommon/libCellFrameDashboardCommon.pri)
+
+QT += core network
+QT -= gui
+QT += qml
+
+TEMPLATE = app
+CONFIG += console c++11
+CONFIG -= app_bundle
+CONFIG += thread
+CONFIG += qt
+
+SOURCES += \
+        DapSettingsTests.cpp \
+        main.cpp
+
+INCLUDEPATH += $$_PRO_FILE_PWD_/../libCellFrameDashboardCommon/
diff --git a/CellFrameDashboardTests/DapSettingsTests.cpp b/CellFrameDashboardTests/DapSettingsTests.cpp
new file mode 100644
index 0000000..a21c88c
--- /dev/null
+++ b/CellFrameDashboardTests/DapSettingsTests.cpp
@@ -0,0 +1,158 @@
+#include "gtest/gtest.h"
+
+#include "DapSettings.h"
+
+#include <QJsonDocument>
+#include <QJsonObject>
+
+TEST(DapSettingsTest, settingFileName)
+{
+    // set filename to setting file
+    // 1. set filename to settings
+    // 2. check what filename in DapSettings equal
+
+    // 1. set filename to settings
+    const QString filename = "settings.json";
+    DapSettings::getInstance().setFileName(filename);
+
+    // 2. check what filename in DapSettings equal
+    EXPECT_EQ(DapSettings::getInstance().getFileName(), filename);
+}
+
+TEST(DapSettingsTest, writeFile)
+{
+    // test for check write and read data in file
+    // 1. Write to file data
+    // 2. Read from file data
+    // 3. Compare data
+
+    // 1. Write to file data
+    QJsonObject object;
+    const QString networkName = "test";
+    object["network"] = networkName;
+    const QString filename = "settings.json";
+    DapSettings::getInstance(filename).writeFile(QJsonDocument(object));
+
+    // 2. Read from file data
+    const QJsonDocument dataFromFile = DapSettings::getInstance(filename).readFile();
+
+    // 3. Compare data
+    EXPECT_EQ(dataFromFile.object(), object);
+    
+}
+
+TEST(DapSettingsTest, FailedReadFromNotExistingFile)
+{
+    // test for check failed reading when file doesn't exist
+    // 1. Read from empty file. Example: "notexist.json"
+    // 2. Check what readed jsonDocument is null
+
+    // 1. Read from empty file. Example: "notexist.json"
+    const QString filename = "notexist.json";
+    DapSettings::getInstance(filename).setFileName(filename);
+    const QJsonDocument notExistingDocument = DapSettings::getInstance(filename).readFile();
+
+    // 2. Check what readed jsonDocument is empty
+    EXPECT_TRUE(notExistingDocument.isNull());
+}
+
+TEST(DapSettingsTest, FailedReadFromEmptyFile)
+{
+    // test for check failed reading when file is empty
+    // 1. Creating empty file
+    // 2. Read from empty file. Example: "empty.json". Create this file
+    // 3. Check what readed jsonDocument is empty
+
+    // 1. Creating empty file
+    const QString filename = "empty.json";
+    DapSettings::getInstance(filename).writeFile(QJsonDocument());
+
+    // 2. Read from empty file. Example: "empty.json"
+    QJsonDocument emptyDocument = DapSettings::getInstance(filename).readFile();
+
+    // 3. Check what readed jsonDocument is empty
+    EXPECT_TRUE(emptyDocument.isEmpty());
+}
+
+TEST(DapSettingsTest, FailedWriteEmptyData)
+{
+    // test for check failed write empty data
+    // 1. Check what Failed write empty data to file. Example: "emptyData.json"
+
+    // 1. Check what Failed write empty data to file. Example: "emptyData.json"
+    EXPECT_FALSE(DapSettings::getInstance("emptyData.json").writeFile(QJsonDocument()));
+}
+
+TEST(DapSettingsTest, SetKeyValue)
+{
+    // test for check set key value to file
+    // 1. Set key value to file. Example: "keys.json"
+    // 2. Get value from file
+    // 3. Comparing values are equal
+
+    // 1. Set key value to file. Example: "keys.json"
+    const QString filename = "keys.json";
+    DapSettings::getInstance(filename).setFileName(filename);
+    const QString key = "key";
+    const QString value = "value";
+    DapSettings::getInstance(filename).setKeyValue(key, value);
+
+    // 2. Get value from file
+    const QVariant gettingValue = DapSettings::getInstance(filename).getKeyValue(key);
+
+    // 3. Comparing values are equal
+    EXPECT_EQ(value, gettingValue.toString());
+}
+
+TEST(DapSettingsTest, FailedSetKeyValueByEmptyKey)
+{
+    // test for check failed set key value by empty key
+    // 1. Check what value doesn't write to file by empty key. Example: "keys.json"
+
+    // 1. Check what value doesn't write to file by empty key. Example: "keys.json"
+    EXPECT_FALSE(DapSettings::getInstance("keys.json").setKeyValue("", "value"));
+}
+
+TEST(DapSettingsTest, FailedSetEmptyKeyValue)
+{
+    // test for check failed set empty key value
+    // 1. Check what empty value doesn't write to file. Example: "keys.json"
+
+    // 1. Check what empty value doesn't write to file. Example: "keys.json"
+    EXPECT_FALSE(DapSettings::getInstance("keys.json").setKeyValue("key", QVariant()));
+}
+
+TEST(DapSettingsTest, SetGroupValue)
+{
+    // test check for setting group value in file
+    // 1. Set group value in file. Example: "group.json"
+    // 2. Get group value from file
+    // 3. Compare two values
+
+    // 1. Set group value in file. Example: "group.json"
+    const QVariantMap map { {"1", "A"}, {"2", "B"} };
+    QList<QVariantMap> list;
+    list.append(map);
+    const QString filename = "group.json";
+    const QString key = "group";
+    DapSettings::getInstance(filename).setGroupValue(key, list);
+
+    // 2. Get group value from file
+    auto gettingList = DapSettings::getInstance(filename).getGroupValue(key);
+
+    // 3. Compare two values
+    EXPECT_EQ(list, gettingList);
+}
+
+TEST(DapSettingsTest, FailedSetGroupValueByEmptyGroupName)
+{
+    // test check for failed set group value because group name is empty
+    // 1. Check failed set group value by empty group name
+
+    // 1. Check failed set group value by empty group name
+    const QVariantMap map { {"1", "A"}, {"2", "B"} };
+    QList<QVariantMap> list;
+    list.append(map);
+    const QString filename = "group.json";
+    EXPECT_FALSE(DapSettings::getInstance("group.json").setGroupValue(QString(), list));
+}
diff --git a/CellFrameDashboardTests/gtest_dependency.pri b/CellFrameDashboardTests/gtest_dependency.pri
new file mode 100644
index 0000000..b51e665
--- /dev/null
+++ b/CellFrameDashboardTests/gtest_dependency.pri
@@ -0,0 +1,32 @@
+isEmpty(GOOGLETEST_DIR):GOOGLETEST_DIR=$$(GOOGLETEST_DIR)
+
+message("_PRO_FILE_PWD_" = $$_PRO_FILE_PWD_/../../3dparty/googletest)
+
+
+isEmpty(GOOGLETEST_DIR) {
+    warning("Using googletest src dir specified at Qt Creator wizard")
+    message("set GOOGLETEST_DIR as environment variable or qmake variable to get rid of this message")
+    GOOGLETEST_DIR = $$_PRO_FILE_PWD_/../../3dparty/googletest
+}
+
+!isEmpty(GOOGLETEST_DIR): {
+    GTEST_SRCDIR = $$GOOGLETEST_DIR/googletest
+    GMOCK_SRCDIR = $$GOOGLETEST_DIR/googlemock
+}
+
+requires(exists($$GTEST_SRCDIR):exists($$GMOCK_SRCDIR))
+
+!exists($$GOOGLETEST_DIR):message("No googletest src dir found - set GOOGLETEST_DIR to enable.")
+
+DEFINES += \
+    GTEST_LANG_CXX11
+
+INCLUDEPATH *= \
+    $$GTEST_SRCDIR \
+    $$GTEST_SRCDIR/include \
+    $$GMOCK_SRCDIR \
+    $$GMOCK_SRCDIR/include
+
+SOURCES += \
+    $$GTEST_SRCDIR/src/gtest-all.cc \
+    $$GMOCK_SRCDIR/src/gmock-all.cc
diff --git a/CellFrameDashboardTests/main.cpp b/CellFrameDashboardTests/main.cpp
new file mode 100644
index 0000000..09bf49a
--- /dev/null
+++ b/CellFrameDashboardTests/main.cpp
@@ -0,0 +1,9 @@
+#include "tst_settings.h"
+
+#include <gtest/gtest.h>
+
+int main(int argc, char *argv[])
+{
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}
diff --git a/libCellFrameDashboardCommon/DapSettings.cpp b/libCellFrameDashboardCommon/DapSettings.cpp
index 9cbf5b9..aa56b45 100644
--- a/libCellFrameDashboardCommon/DapSettings.cpp
+++ b/libCellFrameDashboardCommon/DapSettings.cpp
@@ -1,5 +1,9 @@
 #include "DapSettings.h"
 
+#include <QJsonObject>
+#include <QJsonArray>
+#include <QIODevice>
+
 /// Standart constructor.
 DapSettings::DapSettings(QObject *parent) : QObject(parent)
 {
@@ -11,33 +15,52 @@ DapSettings::DapSettings(QObject *parent) : QObject(parent)
 /// Overloaded constructor.
 /// @param fileName Settings file name.
 /// @param parent Parent.
-DapSettings::DapSettings(const QString &fileName, QObject *parent)
+DapSettings::DapSettings(const QString &asFileName, QObject *parent)
 {
     Q_UNUSED(parent)
     
     init();
     
-    setFileName(fileName);
+    setFileName(asFileName);
 }
 
 /// Initialize the components.
 void DapSettings::init()
 {
-    connect(this, &DapSettings::fileNameChanged, this, [=] (const QString &fileName)
+    connect(this, &DapSettings::fileNameChanged, this, [=] (const QString &asFileName)
     {
-        m_file.setFileName(fileName);
+        m_file.setFileName(asFileName);
     });
+
+    connect(this, &DapSettings::fileNeedClosed, [=] () { m_file.close(); });
 }
 
 /// Read settings file.
-/// @return Virtual json file.
+/// @return Virtual json file. If failed read return default json document
 QJsonDocument DapSettings::readFile()
 {
-    qDebug() << "File name " << m_file.fileName();
-    m_file.open(QIODevice::ReadOnly | QIODevice::Text);
-    QString textFile = decrypt(m_file.readAll());
-    m_file.close();
-    return QJsonDocument::fromJson(textFile.toUtf8());
+    if(!m_file.exists()) {
+        qWarning() << "File  doesn't exist." << "Creating file with name " << m_fileName;
+        m_file.open(QIODevice::ReadOnly | QIODevice::Text);
+        emit fileNeedClosed();
+        return QJsonDocument();
+    }
+
+    if(!m_file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+        qWarning() << "Failed to read file " << m_file.errorString();
+        emit fileNeedClosed();
+        return QJsonDocument();
+    }
+
+    const QByteArray data = m_file.readAll();
+    if(data.isEmpty()) {
+        qWarning() << "Failed to read data. File " << m_fileName << " is empty";
+        return QJsonDocument();
+    }
+
+    emit fileNeedClosed();
+
+    return QJsonDocument::fromJson(data);
 }
 
 /// Write settings to file.
@@ -45,28 +68,21 @@ QJsonDocument DapSettings::readFile()
 /// @return Returns true if the recording was successful, false if the recording failed.
 bool DapSettings::writeFile(const QJsonDocument &json)
 {
-    if(!m_file.open(QIODevice::WriteOnly))
-    {
-        qDebug() << "Couldn't open write file." << m_file.errorString();
+    if(!m_file.open(QIODevice::WriteOnly)) {
+        qWarning() << "Couldn't open write file." << m_file.errorString();
         return false;
     }
-    else
-    {
-        m_file.open(QIODevice::WriteOnly);
-        m_file.write(encrypt(json.toJson()));
-        m_file.close();
-        return true;
+
+    const qint64 bytes = m_file.write(json.toJson());
+    if(bytes <= 0) {
+        qWarning() << "Failed to write file with error: " << m_file.errorString();
+        return false;
     }
-}
 
-QByteArray DapSettings::encrypt(const QByteArray &byteArray) const
-{
-    return byteArray;
-}
+    qDebug() << "write bytes " << bytes << " to file " << m_fileName;
+    emit fileNeedClosed();
 
-QByteArray DapSettings::decrypt(const QByteArray &byteArray) const
-{
-    return byteArray;
+    return true;
 }
 
 /// Get an instance of a class.
@@ -79,9 +95,9 @@ DapSettings &DapSettings::getInstance()
 
 /// Get an instance of a class.
 /// @return Instance of a class.
-DapSettings &DapSettings::getInstance(const QString &fileName)
+DapSettings &DapSettings::getInstance(const QString &asFileName)
 {
-    static DapSettings instance(fileName);
+    static DapSettings instance(asFileName);
     return instance;
 }
 
@@ -98,19 +114,24 @@ DapSettings &DapSettings::getInstance(const QString &fileName)
 /// @param valueKeyProperty Key property value.
 /// @param property Settable property.
 /// @param valuePropery The value of the property being set.
-void DapSettings::setGroupPropertyValue(const QString &group, const QString &keyProperty, 
-                                        const QVariant &valueKeyProperty, const QString &property, const QVariant &valuePropery)
+bool DapSettings::setGroupPropertyValue(const QString &asGroup, const QString &asKeyProperty,
+                                        const QVariant &aValueKeyProperty, const QString &asProperty,
+                                        const QVariant &aValueProperty)
 {
-    if(group.isEmpty() || group.isNull())
-        return;
-    
-    auto list = getGroupValue(group);
-    
-    for(QMap<QString, QVariant> &map : list)
-        if(map.find(keyProperty) != map.end() && map.value(keyProperty) == valueKeyProperty)
-            map.insert(property, valuePropery);
+    if(asGroup.isEmpty() || asGroup.isNull())
+        return false;
     
-    setGroupValue(group, list);
+    auto list = getGroupValue(asGroup);
+    if(list.empty()) {
+        QVariantMap map { {asProperty, aValueProperty} };
+        list.append(map);
+    } else {
+        for(auto &map : list)
+            if(map.find(asKeyProperty) != map.end() && map.value(asKeyProperty) == aValueKeyProperty)
+                map.insert(asProperty, aValueProperty);
+    }
+
+    return setGroupValue(asGroup, list);
 }
 
 /// Get property value from group by key property value.
@@ -128,118 +149,121 @@ void DapSettings::setGroupPropertyValue(const QString &group, const QString &key
 /// @param property Settable property.
 /// @param defaultValue The key value to be inserted in case the key is not found. 
 /// The default is non-valid value.
-QVariant DapSettings::getGroupPropertyValue(const QString &group, const QString &keyProperty, const QString &valueKeyProperty, const QString &property, const QVariant& defaultValue)
+QVariant DapSettings::getGroupPropertyValue(const QString &asGroup, const QString &aKeyProperty,
+                                            const QString &aValueKeyProperty, const QString &asProperty)
 {
-    for(QMap<QString, QVariant> &map : getGroupValue(group))
-        if(map.find(keyProperty) != map.end() && map.value(keyProperty) == valueKeyProperty)
-            return map.value(property);
-    return defaultValue;
+    for(const QMap<QString, QVariant> &map : getGroupValue(asGroup))
+        if(map.find(aKeyProperty) != map.end() && map.value(aKeyProperty) == aValueKeyProperty)
+            return map.value(asProperty);
+    return QVariant();
 }
 
 /// Get key value.
 /// @details If the key does not exist, the function returns an invalid value.
 /// @param key Key name.
-/// @param defaultValue The key value to be inserted in case the key is not found. 
-/// The default is non-valid value.
-QVariant DapSettings::getKeyValue(const QString &key, const QVariant& defaultValue)
+QVariant DapSettings::getKeyValue(const QString &asKey)
 {
-    QJsonObject root = readFile().object();
-    
-    QJsonValue jv = root.value(key);
-    
-    if(!jv.isArray())
-    {
-        return jv.toVariant();
-    }
-    
-    return defaultValue;
+    const QJsonValue value = readFile().object().value(asKey);
+    if(value.isNull() || value.isUndefined())
+        return QVariant();
+
+    return value.toVariant();
 }
 
 /// Set key value.
 /// @param key Key.
 /// @param value Key value.
-void DapSettings::setKeyValue(const QString &key, const QVariant &value)
+bool DapSettings::setKeyValue(const QString &asKey, const QVariant &aValue)
 {
-    if(key.isEmpty() || key.isNull())
-        return;
+    if(asKey.isEmpty() || asKey.isNull())
+        return false;
     
-    QJsonDocument jsonDocument = readFile();
-    QJsonObject jsonObject = jsonDocument.object();
-    jsonObject.insert(key, value.toJsonValue());
-    QJsonDocument jsonDocumentSave(jsonObject);
-    writeFile(jsonDocumentSave);
+    if(aValue.isNull() || !aValue.isValid())
+        return false;
+
+    QJsonObject jsonObject = readFile().object();
+    jsonObject.insert(asKey, aValue.toJsonValue());
+    return writeFile(QJsonDocument(jsonObject));
 }
 
 /// Get a collection of values by name group.
 /// @details If the group is not found, the function returns an empty list.
 /// @param group Group name.
 /// @return Group values collection.
-QList<QMap<QString, QVariant>> DapSettings::getGroupValue(const QString &group)
+QList<QVariantMap> DapSettings::getGroupValue(const QString &asGroup)
 {
-    QJsonObject root = readFile().object();
-    
-    QJsonValue jv = root.value(group);
-    
-    QList<QMap<QString, QVariant>> arrayValue;
-    
-    if(jv.isArray())
+    if(asGroup.isEmpty() || asGroup.isNull()) {
+        qWarning() << "Failed get group value because group's name is undefined";
+        return QList<QVariantMap>();
+    }
+
+    const QJsonValue jsonGroupValue = readFile().object().value(asGroup);
+    if(jsonGroupValue.isNull() || jsonGroupValue.isUndefined()) {
+        qWarning() << "Failed get group value because group " << asGroup << " doesn't exist";
+        return QList<QVariantMap>();
+    }
+
+    if(!jsonGroupValue.isArray()) {
+        qWarning() << "Failed get group value because group " << asGroup << " isn't array of values";
+        return QList<QVariantMap>();
+    }
+
+    QList<QVariantMap> collection;
+    const QJsonArray jsonGroupArray = jsonGroupValue.toArray();
+    for(const QJsonValue &jsonValue : jsonGroupArray)
     {
-        QJsonArray ja = jv.toArray();
-        for(QJsonValue jsonValue : ja)
-        {
-            QJsonObject jsonObject = jsonValue.toObject();
-            QMap<QString, QVariant> object;
-            for(QString key : jsonObject.keys())
-            {
-                object.insert(key, jsonObject.value(key).toVariant());
-            }
-            arrayValue.push_back(object);
+        const QJsonObject jsonObject = jsonValue.toObject();
+        if(!jsonValue.isObject()) {
+            qDebug() << jsonObject << " isn't object. Read next field...";
+            continue;
         }
+
+        QVariantMap map;
+        for(const QString &key : jsonObject.keys())
+            map.insert(key, jsonObject.value(key).toVariant());
+
+        collection.push_back(map);
     }
-        
-    return arrayValue;
+
+    return collection;
 }
 
 /// Set key values for group.
 /// @param group Group name.
 /// @param values Collection of group values.
-void DapSettings::setGroupValue(const QString &group, const QList<QMap<QString, QVariant> > &values)
+bool DapSettings::setGroupValue(const QString &asGroup, const QList<QVariantMap> &aValues)
 {
-    if(group.isEmpty() || group.isNull())
-        return;
-    
-    QJsonDocument jsonDocument = readFile();
-    QJsonObject jsonObject = jsonDocument.object();
+    if(asGroup.isEmpty() || asGroup.isNull())
+        return false;
     
     QJsonArray groupValues;
-    for(QMap<QString,QVariant> var : values) 
+    for(const auto & map : aValues)
     {
         QJsonObject itemObject;
-        for(auto key : var.keys()) 
-        {
-            itemObject.insert(key, var.value(key).toJsonValue());
-        }
+        for(const auto &key : map.keys())
+            itemObject.insert(key, map.value(key).toJsonValue());
+
         groupValues.append(itemObject);
     }
     
-    jsonObject.insert(group, groupValues);
-    QJsonDocument jsonDocumentSave(jsonObject);
-    writeFile(jsonDocumentSave);
+    return setKeyValue(asGroup, groupValues);
 }
 
 /// Get the name of the settings file.
 /// @return The name of the settings file.
-QString DapSettings::getFileName() const
+const QString &DapSettings::getFileName() const
 {
     return m_fileName;
 }
 
 /// Set the name of the settings file.
 /// @param fileName The name of the settings file.
-void DapSettings::setFileName(const QString &fileName)
+/// @return Reference of changed object DapSettings
+DapSettings &DapSettings::setFileName(const QString &asFileName)
 {
-    m_fileName = fileName;
-    emit fileNameChanged(m_fileName);
+    m_fileName = asFileName;
+    emit fileNameChanged(asFileName);
+    return *this;
 }
 
 /// Method that implements the singleton pattern for the qml layer.
diff --git a/libCellFrameDashboardCommon/DapSettings.h b/libCellFrameDashboardCommon/DapSettings.h
index 4983bf8..7469a25 100644
--- a/libCellFrameDashboardCommon/DapSettings.h
+++ b/libCellFrameDashboardCommon/DapSettings.h
@@ -17,22 +17,18 @@
 #include <QQmlEngine>
 #include <QJSEngine>
 #include <QJsonDocument>
-#include <QJsonObject>
-#include <QJsonArray>
-#include <QIODevice>
 #include <QDebug>
 
 class DapSettings : public QObject
 {
     Q_OBJECT
-    
 protected:
     /// Standart constructor.
     explicit DapSettings(QObject *parent = nullptr);
     /// Overloaded constructor.
-    /// @param fileName Settings file name.
+    /// @param asFileName Settings file name.
     /// @param parent Parent.
-    explicit DapSettings(const QString &fileName, QObject *parent = nullptr);
+    explicit DapSettings(const QString &asFileName, QObject *parent = nullptr);
     
     /// Settings file.
     QFile       m_file;
@@ -41,21 +37,17 @@ protected:
     
     /// Initialize the components.
     virtual void init();
+
+public:
     /// Read settings file.
-    /// @return Virtual json file.
+    /// @return Virtual json file. If failed read return default json document
     virtual QJsonDocument readFile();
     /// Write settings to file.
     /// @param json Virtual json file.
     /// @return Returns true if the recording was successful, false if the recording failed.
     virtual bool writeFile(const QJsonDocument& json);
     
-    
-    
 public:
-    virtual QByteArray encrypt(const QByteArray &byteArray) const;
-    
-    virtual QByteArray decrypt(const QByteArray &byteArray) const;
-    
     /// Removed as part of the implementation of the pattern sington.
     DapSettings(const DapSettings&) = delete;
     DapSettings& operator= (const DapSettings &) = delete;
@@ -64,8 +56,9 @@ public:
     /// @return Instance of a class.
     Q_INVOKABLE static DapSettings &getInstance();
     /// Get an instance of a class.
+    /// @param  asFileName Settings file name
     /// @return Instance of a class.
-    Q_INVOKABLE static DapSettings &getInstance(const QString &fileName);
+    Q_INVOKABLE static DapSettings &getInstance(const QString &asFileName);
     
     ///********************************************
     ///                 Property
@@ -91,7 +84,10 @@ public:
     /// @param valueKeyProperty Key property value.
     /// @param property Settable property.
     /// @param valuePropery The value of the property being set.
-    Q_INVOKABLE void setGroupPropertyValue(const QString &group, const QString &keyProperty, const QVariant &valueKeyProperty, const QString &property, const QVariant &valuePropery);
+    /// @return true if successfull set group value. False is group empty or null
+    Q_INVOKABLE bool setGroupPropertyValue(const QString &asGroup, const QString &asKeyProperty,
+                                           const QVariant &aValueKeyProperty, const QString &asProperty,
+                                           const QVariant &aValuePropery);
     /// Get property value from group by key property value.
     /// @details The search in the group is carried out according to the signs 
     /// defining the object: the name of the key property and its value. 
@@ -105,39 +101,42 @@ public:
     /// @param keyProperty Key property.
     /// @param valueKeyProperty Key property value.
     /// @param property Settable property.
-    /// @param defaultValue The key value to be inserted in case the key is not found. 
     /// The default is non-valid value.
-    Q_INVOKABLE QVariant getGroupPropertyValue(const QString &group, const QString &keyProperty, const QString &valueKeyProperty, const QString &property, const QVariant &defaultValue = QVariant());
+    Q_INVOKABLE QVariant getGroupPropertyValue(const QString &asGroup, const QString &asKeyProperty,
+                                               const QString &aValueKeyProperty, const QString &asProperty);
     /// Get key value.
     /// @details If the key does not exist, the function returns an invalid value.
     /// @param key Key name.
-    /// @param defaultValue The key value to be inserted in case the key is not found. 
-    /// The default is non-valid value.
-    Q_INVOKABLE QVariant getKeyValue(const QString &key, const QVariant &defaultValue = QVariant());
+    Q_INVOKABLE QVariant getKeyValue(const QString &asKey);
     /// Set key value.
     /// @param key Key.
     /// @param value Key value.
-    Q_INVOKABLE void setKeyValue(const QString &key, const QVariant &value);
+    /// @return true if successfull set value. False is key empty or null
+    Q_INVOKABLE bool setKeyValue(const QString &asKey, const QVariant &aValue);
     /// Get a collection of values by name group.
     /// @details If the group is not found, the function returns an empty list.
     /// @param group Group name.
     /// @return Group values collection.
-    Q_INVOKABLE QList<QMap<QString, QVariant> > getGroupValue(const QString &group);
+    Q_INVOKABLE QList<QVariantMap> getGroupValue(const QString &asGroup);
     /// Set key values for group.
     /// @param group Group name.
     /// @param values Collection of group values.
-    Q_INVOKABLE void setGroupValue(const QString &group, const QList<QMap<QString, QVariant>> &values);
+    /// @return true if successfull set group value. False is group empty or null
+    Q_INVOKABLE bool setGroupValue(const QString &asGroup, const QList<QVariantMap> &aValues);
     /// Get the name of the settings file.
     /// @return The name of the settings file.
-    QString getFileName() const;
+    const QString &getFileName() const;
     /// Set the name of the settings file.
     /// @param fileName The name of the settings file.
-    void setFileName(const QString &fileName);
+    /// @return Reference of changed object DapSettings
+    DapSettings &setFileName(const QString &asFileName);
     
 signals:
     /// The signal is emitted when the FileName property changes.
-    /// @param fileName The name of the settings file.
-    void fileNameChanged(const QString &fileName);
+    /// @param asFileName The name of the settings file.
+    void fileNameChanged(const QString &asFileName);
+    /// The signal is emitted when file needs to close;
+    void fileNeedClosed();
     
 public slots:
     /// Method that implements the singleton pattern for the qml layer.
diff --git a/libCellFrameDashboardCommon/DapSettingsCipher.cpp b/libCellFrameDashboardCommon/DapSettingsCipher.cpp
index c0129be..60e8946 100644
--- a/libCellFrameDashboardCommon/DapSettingsCipher.cpp
+++ b/libCellFrameDashboardCommon/DapSettingsCipher.cpp
@@ -8,12 +8,14 @@ DapSettingsCipher::DapSettingsCipher(const DapSettings& settings)
 
 QByteArray DapSettingsCipher::encrypt(const QByteArray &byteArray) const
 {
-    return m_settings.encrypt(byteArray);
+// TODO: implement encryption to next iteration.
+//    return m_settings.encrypt(byteArray);
 }
 
 QByteArray DapSettingsCipher::decrypt(const QByteArray &byteArray) const
 {
-    return m_settings.decrypt(byteArray);
+// TODO: implement decryption to next iteration.
+//    return m_settings.decrypt(byteArray);
 }
 
 DapSettingsCipher &DapSettingsCipher::getInstance(const DapSettings& settings)
diff --git a/libCellFrameDashboardCommon/DapSettingsCipher.h b/libCellFrameDashboardCommon/DapSettingsCipher.h
index b0d9beb..1bc3666 100644
--- a/libCellFrameDashboardCommon/DapSettingsCipher.h
+++ b/libCellFrameDashboardCommon/DapSettingsCipher.h
@@ -16,9 +16,9 @@ protected:
     DapSettingsCipher(const DapSettings& settings);
      
 public:
-    virtual QByteArray encrypt(const QByteArray &byteArray) const override;
+    virtual QByteArray encrypt(const QByteArray &byteArray) const;
     
-    virtual QByteArray decrypt(const QByteArray &byteArray) const override;
+    virtual QByteArray decrypt(const QByteArray &byteArray) const;
     
     /// Removed as part of the implementation of the pattern sington.
     DapSettingsCipher(const DapSettingsCipher&) = delete;
-- 
GitLab