Skip to content
Snippets Groups Projects
Commit 0e08abec authored by Jaron Emmenegger's avatar Jaron Emmenegger
Browse files

ConfigParser: parse APIs

parent 37d20f9a
No related branches found
No related tags found
No related merge requests found
......@@ -3,18 +3,17 @@
#include "ceaapp.h"
//-------------------------------------------------------------------------------------------------
CeaApp::CeaApp()
{
connect(&mStorage, &ConfigStorage::requestAppExit, this, &CeaApp::requestAppExit);
}
//-------------------------------------------------------------------------------------------------
void CeaApp::init()
{
if (!mStorage.init()) {
emit requestExit("Failed to initialize/read configfile", true);
emit requestAppExit("Failed to initialize/read configfile", true);
return;
}
qDebug() << "juhuu";
}
......@@ -14,7 +14,7 @@ public:
void init();
signals:
void requestExit(const QString &reason, bool fatal);
void requestAppExit(const QString &reason, bool fatal);
private:
ConfigStorage mStorage;
......
......@@ -3,7 +3,12 @@
namespace ConfigKeys
{
const QString apis = "apis";
const QString apiURl = "url";
const QString apiName = "name";
const QString apiUrl = "url";
const QString apiEnabled = "enabled";
}
namespace Apis
{
const QString binanceApi = "binance";
}
......@@ -6,8 +6,13 @@
namespace ConfigKeys
{
extern const QString apis;
extern const QString apiName;
extern const QString apiUrl;
extern const QString apiEnabled;
}
namespace Apis
{
extern const QString binanceApi;
}
......
......@@ -10,6 +10,7 @@ SOURCES += \
abstractapi.cc \
ceaapp.cc \
ceaconstants.cc \
configparser.cc \
configstorage.cc \
main.cc
......@@ -17,7 +18,9 @@ HEADERS += \
abstractapi.h \
ceaapp.h \
ceaconstants.h \
configstorage.h
configparser.h \
configstorage.h \
types.h
RESOURCES += \
cearesources.qrc
#include <QJsonDocument>
#include <QJsonArray>
#include <QDebug>
#include "configparser.h"
#include "ceaconstants.h"
//-------------------------------------------------------------------------------------------------
ConfigParser::ConfigParser()
{
}
//-------------------------------------------------------------------------------------------------
QJsonParseError ConfigParser::setConfig(const QByteArray &newConfig)
{
QJsonParseError error;
mConfig = QJsonDocument::fromJson(newConfig, &error).object();
return error;
}
//-------------------------------------------------------------------------------------------------
ApiCfgs ConfigParser::allApiCfgs() const
{
if (!mConfig[ConfigKeys::apis].isArray()) {
qWarning() << "Config parser error:" << ConfigKeys::apis << "must be of type array";
return ApiCfgs();
}
ApiCfgs cfgs;
for (const QJsonValue &v : mConfig.value(ConfigKeys::apis).toArray()) {
if (!v.isObject()) {
qWarning() << "Config parser: Ignoring non-object in" << ConfigKeys::apis;
continue;
}
QJsonObject api = v.toObject();
ApiCfg apiCfg;
apiCfg.name = api.value(ConfigKeys::apiName).toString();
apiCfg.enabled = api.value(ConfigKeys::apiEnabled).toBool();
apiCfg.url = api.value(ConfigKeys::apiUrl).toString();
cfgs << apiCfg;
}
return cfgs;
}
#ifndef CONFIGPARSER_H
#define CONFIGPARSER_H
#include <QByteArray>
#include <QJsonObject>
#include <QJsonParseError>
#include "types.h"
class ConfigParser
{
public:
ConfigParser();
QJsonParseError setConfig(const QByteArray &newConfig);
ApiCfgs allApiCfgs() const;
private:
QJsonObject mConfig;
};
#endif // CONFIGPARSER_H
......@@ -2,6 +2,7 @@
#include <QStandardPaths>
#include <QCoreApplication>
#include <QDir>
#include <QJsonParseError>
#include "configstorage.h"
......@@ -9,7 +10,8 @@
//-------------------------------------------------------------------------------------------------
ConfigStorage::ConfigStorage()
: mConfigFile(nullptr)
: mConfigFileName(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation)
+ "/" + qApp->applicationName() + "/config.json")
{
connect(&mWatchTimer, &QTimer::timeout, this, &ConfigStorage::checkConfigUpdate);
}
......@@ -17,27 +19,8 @@ ConfigStorage::ConfigStorage()
//-------------------------------------------------------------------------------------------------
bool ConfigStorage::init()
{
Q_ASSERT(!mConfigFile); // call init only once
QString cfgPath = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation)
+ "/" + qApp->applicationName();
if (!QDir(cfgPath).mkpath(cfgPath)) {
qWarning() << "Failed to create path" << cfgPath;
return false;
}
cfgPath.append("/config.json");
mConfigFile = new QFile(cfgPath);
bool useDefaults = !mConfigFile->exists() || mConfigFile->size() == 0;
if (!mConfigFile->open(QIODevice::ReadWrite)) {
qWarning() << "Could not open" << cfgPath << "with read/write mode";
if (!resetConfigEnv())
return false;
}
if (useDefaults)
revertToDefaults();
updateConfig();
mWatchTimer.start(CHECK_INTERVAL);
......@@ -48,31 +31,68 @@ bool ConfigStorage::init()
//-------------------------------------------------------------------------------------------------
void ConfigStorage::checkConfigUpdate()
{
Q_ASSERT(mConfigFile);
QDateTime lastModification = QFileInfo(mConfigFileName).lastModified();
if (QFileInfo(*mConfigFile).lastModified() > mLastUpdate)
if (!lastModification.isValid()) {
emit requestAppExit("Configuration file removed");
return;
}
if (QFileInfo(mConfigFileName).lastModified() > mLastUpdate)
updateConfig();
}
//-------------------------------------------------------------------------------------------------
void ConfigStorage::updateConfig()
bool ConfigStorage::resetConfigEnv()
{
Q_ASSERT(mConfigFile->isOpen());
QDir configDir = QFileInfo(mConfigFileName).absoluteDir();
if (!configDir.exists() && ! configDir.mkpath(".")) {
qWarning() << "Failed to create path" << configDir.absolutePath();
return false;
}
mLastUpdate = QDateTime::currentDateTime();
qDebug() << "update config";
QFileInfo config(mConfigFileName);
// create default configuration file
if ((!config.exists() || config.size() == 0) && !revertToDefaults()) {
qWarning() << "Failed to create default configuration";
return false;
}
return true;
}
//-------------------------------------------------------------------------------------------------
void ConfigStorage::revertToDefaults()
void ConfigStorage::updateConfig()
{
Q_ASSERT(mConfigFile && mConfigFile->isOpen()); // call init first
mLastUpdate = QDateTime::currentDateTime();
QFile file(mConfigFileName);
bool open = file.open(QIODevice::ReadOnly);
Q_ASSERT(open);
QJsonParseError err = mParser.setConfig(file.readAll());
if (err.error != QJsonParseError::NoError) {
qWarning() << "Invalid Json configuration:" << err.errorString() << ". Keeping old configuration";
return;
}
mApis = mParser.allApiCfgs();
emit configUpdate();
}
//-------------------------------------------------------------------------------------------------
bool ConfigStorage::revertToDefaults()
{
QFile defaults(":/config/install/default.json");
Q_ASSERT(defaults.exists());
bool open = defaults.open(QIODevice::ReadOnly);
Q_ASSERT(open);
mConfigFile->write(defaults.readAll());
mConfigFile->flush();
QFile config(mConfigFileName);
if (!config.open(QIODevice::WriteOnly))
return false;
config.write(defaults.readAll());
return true;
}
......@@ -5,6 +5,9 @@
#include <QTimer>
#include <QDateTime>
#include "types.h"
#include "configparser.h"
class QFile;
class ConfigStorage : public QObject
......@@ -15,16 +18,26 @@ public:
bool init();
inline ApiCfgs apis() const { return mApis; }
signals:
void configUpdate();
void requestAppExit(const QString &reason, bool fatal = true);
private slots:
void checkConfigUpdate();
private:
void revertToDefaults();
bool resetConfigEnv();
bool revertToDefaults();
void updateConfig();
QFile *mConfigFile;
QTimer mWatchTimer;
QDateTime mLastUpdate;
QString mConfigFileName;
QTimer mWatchTimer;
QDateTime mLastUpdate;
ConfigParser mParser;
ApiCfgs mApis;
};
#endif // CONFIGSTORAGE_H
{
"apis" :
{
"binance" :
[
{
"name" : "binance",
"enabled" : true,
"url" : "wss://stream.binance.com:9443"
}
}
]
}
\ No newline at end of file
......@@ -11,12 +11,12 @@ int main(int argc, char *argv[])
CeaApp app;
QObject::connect(&app, &CeaApp::requestExit, [](const QString &reason, bool fatal) {
QObject::connect(&app, &CeaApp::requestAppExit, [](const QString &reason, bool fatal) {
if (fatal)
qFatal("%s", reason.toUtf8().constData());
qFatal("Fatal: %s", reason.toUtf8().constData());
else {
qDebug() << reason;
qApp->exit(0);
qApp->quit();
}
});
......
types.h 0 → 100644
#ifndef TYPES_H
#define TYPES_H
#include <QString>
#include <QList>
struct ApiCfg
{
QString name;
QString url;
bool enabled;
};
typedef QList<ApiCfg> ApiCfgs;
#endif // TYPES_H
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment