QuasarAppLib/params.cpp

422 lines
10 KiB
C++
Raw Normal View History

2018-09-29 15:56:04 +03:00
/*
2022-03-03 19:00:49 +03:00
* Copyright (C) 2018-2022 QuasarApp.
2018-09-29 15:56:04 +03:00
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "params.h"
#include <QVariantMap>
#include <QDebug>
2019-01-16 22:17:05 +03:00
#include <QFileInfo>
#include <iostream>
2019-08-23 21:14:32 +03:00
#include <QDateTime>
2020-04-04 15:42:56 +03:00
#include <QCoreApplication>
#include "qaglobalutils.h"
2019-08-23 21:14:32 +03:00
2019-01-27 19:45:30 +03:00
#ifdef Q_OS_WIN
#include "windows.h"
#else
#include <unistd.h>
2019-01-27 20:14:06 +03:00
#include <limits.h>
2019-01-27 19:45:30 +03:00
#endif
2018-09-29 15:56:04 +03:00
using namespace QuasarAppUtils;
2021-04-26 11:46:52 +03:00
QMap<QString, QString> Params::params = QMap<QString, QString>();
QString Params::appPath = "";
QString Params::appName = "";
2021-07-26 13:17:06 +03:00
Help::Section Params::userHelp = {};
2021-07-28 12:38:44 +03:00
OptionsDataList Params::inputOptions = {};
2018-09-29 15:56:04 +03:00
2018-09-29 15:56:04 +03:00
bool Params::isEndable(const QString& key) {
return params.contains(key);
}
2020-04-04 15:42:56 +03:00
void Params::log(const QString &log, VerboseLvl vLvl) {
2019-08-23 23:55:28 +03:00
writeLoginFile(log, vLvl);
2020-04-14 17:57:54 +03:00
auto lvl = getVerboseLvl();
2020-04-04 15:42:56 +03:00
if (vLvl <= lvl) {
2019-03-28 18:58:36 +03:00
2020-04-04 15:42:56 +03:00
switch (vLvl) {
2019-03-28 18:58:36 +03:00
2020-04-04 15:42:56 +03:00
case VerboseLvl::Error:
2022-01-08 12:23:46 +03:00
qCritical() << lvlToString(vLvl) + ": " + log;
#ifdef QA_ASSERT_ON_ERROR
debug_assert(false, "You requested to throw assert in every error message."
" See The ASSERT_ON_ERROR option in cmake config.");
#endif
2022-02-13 18:44:02 +03:00
break;
2020-04-04 15:42:56 +03:00
case VerboseLvl::Warning: {
2022-01-08 12:23:46 +03:00
qWarning() << lvlToString(vLvl) + ": " + log;
#ifdef QA_ASSERT_ON_WARN
debug_assert(false, "You requested to throw assert in every warning message."
" See The ASSERT_ON_ERROR option in cmake config.");
#endif
2022-01-08 12:23:46 +03:00
break;
}
case VerboseLvl::Debug: {
qDebug() << lvlToString(vLvl) + ": " + log;
break;
}
case VerboseLvl::Info: {
qInfo() << lvlToString(vLvl) + ": " + log;
2020-04-04 15:42:56 +03:00
break;
}
2019-03-28 18:58:36 +03:00
2020-04-04 15:42:56 +03:00
default: {
2022-01-08 12:23:46 +03:00
qInfo() << lvlToString(vLvl) + ": " + log;
2020-04-04 15:42:56 +03:00
break;
2019-03-28 18:58:36 +03:00
}
2020-04-04 15:42:56 +03:00
}
2019-01-02 13:42:51 +03:00
}
}
2020-04-14 17:57:54 +03:00
VerboseLvl Params::getVerboseLvl() {
return static_cast<VerboseLvl>(getArg("verbose", DEFAULT_VERBOSE_LVL).toInt());
}
bool Params::isDebug() {
return getVerboseLvl() >= VerboseLvl::Debug;
}
2021-01-24 14:04:31 +03:00
bool Params::isDebugBuild() {
#ifdef QT_DEBUG
return true;
#else
return false;
#endif
}
2021-07-28 13:17:26 +03:00
void Params::showHelp() {
if (inputOptions.size() > 1) {
showHelpForInputOptions();
} else {
2021-07-28 12:38:44 +03:00
Help::print(userHelp);
2021-07-28 13:17:26 +03:00
}
2021-07-28 12:38:44 +03:00
}
void Params::showHelpForInputOptions() {
Help::print(getHelpOfInputOptions());
}
Help::Section Params::getHelpOfInputOptions() {
if (inputOptions.size() <= 1 ) {
return {};
}
Help::Options help;
for (const auto &optionData: qAsConst(inputOptions) ) {
help.unite(optionData.toHelp());
}
return Help::Section{{"Information about using options", help}};
}
const Help::Section &Params::getHelp() {
return userHelp;
2020-02-18 22:28:17 +03:00
}
const QMap<QString, QString>& Params::getUserParamsMap() {
return params;
}
2020-05-17 23:21:12 +03:00
void Params::clearParsedData() {
params.clear();
appPath = "";
appName = "";
2020-05-17 23:21:12 +03:00
}
QString Params::getCurrentExecutable() {
return getCurrentExecutableDir() + "/" + appName;
2020-09-28 23:42:54 +03:00
}
QString Params::getCurrentExecutableDir() {
return appPath;
2020-05-17 23:21:12 +03:00
}
2021-07-27 17:24:43 +03:00
OptionsDataList Params::availableArguments() {
return OptionsDataList{
{
"Base Options",
OptionData{
{"-verbose"}, "(level 1 - 3)", "Shows debug log"
}
2021-07-28 12:38:44 +03:00
2021-07-27 17:24:43 +03:00
},
{
"Base Options",
OptionData{
{"-fileLog"}, "(path to file)", "Sets path of log file. Default it is path to executable file with suffix '.log'"
}
}
};
}
2019-09-16 12:38:10 +03:00
int Params::size() {
return params.size();
}
2019-08-23 20:41:13 +03:00
QString Params::timeString() {
return QDateTime::currentDateTime().toString();
}
2022-01-08 12:23:46 +03:00
QString Params::lvlToString(VerboseLvl vLvl) {
switch (vLvl) {
case VerboseLvl::Error: {
return "Error";
}
case VerboseLvl::Warning: {
return "Warning";
}
case VerboseLvl::Info: {
return "Info";
}
case VerboseLvl::Debug: {
return "Verbose log";
}
2020-04-04 15:42:56 +03:00
default: return "";
}
return "";
}
bool Params::writeLoginFile(const QString &log, VerboseLvl vLvl) {
2020-04-04 15:42:56 +03:00
if (isEndable("fileLog")) {
2020-05-17 23:21:12 +03:00
QString path = getCurrentExecutable() + ".log";
2021-03-26 17:18:29 +03:00
auto file = getArg("fileLog");
2020-04-04 15:42:56 +03:00
if (file.size()) {
2021-03-26 17:18:29 +03:00
path = file;
}
QFile logFile(path);
2019-08-22 17:48:23 +03:00
if (logFile.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
QTextStream stream(&logFile);
2020-09-07 09:54:25 +03:00
#if QT_VERSION > QT_VERSION_CHECK(5, 14, 0)
2022-01-08 12:23:46 +03:00
stream << timeString() <<"| " << lvlToString(vLvl) + ": " + log << Qt::endl;
2020-09-07 09:54:25 +03:00
#else
2022-01-08 12:23:46 +03:00
stream << timeString() <<"| " << lvlToString(vLvl) + ": " + log << endl;
2020-09-07 09:54:25 +03:00
#endif
logFile.close();
} else {
return false;
}
2019-11-01 20:28:17 +03:00
}
return true;
}
bool Params::optionsForEach(const QStringList &paramsArray,
const OptionsDataList& availableOptions) {
for (int i = 0 ; i < paramsArray.size(); ++i) {
QStringList virtualOptionsList = paramsArray[i].split('=');
if (virtualOptionsList.size() > 1) {
return optionsForEach(virtualOptionsList, availableOptions);
}
auto optionData = availableOptions.value(paramsArray[i], {{}});
if (!checkOption(optionData, paramsArray[i])) {
return false;
}
inputOptions.insert(paramsArray[i], optionData);
if (paramsArray[i][0] == '-') {
if (i < (paramsArray.size() - 1) && paramsArray[i + 1][0] != '-') {
params[paramsArray[i].mid(1)] = paramsArray[i + 1];
i++;
} else {
QuasarAppUtils::Params::log("Missing argument for " + paramsArray[i],
QuasarAppUtils::Error);
return false;
}
} else {
params[paramsArray[i]] = "";
}
}
return true;
}
2021-07-26 13:17:06 +03:00
bool Params::parseParams(const int argc, const char *argv[], const OptionsDataList& options) {
2019-09-10 18:22:13 +03:00
QStringList params;
for (int i = 1; i < argc; i++) {
params.push_back(argv[i]);
}
2021-07-26 13:17:06 +03:00
return parseParams(params, options);
2019-09-10 18:22:13 +03:00
}
2021-07-26 13:17:06 +03:00
bool Params::parseParams(int argc, char *argv[], const OptionsDataList& options) {
return parseParams(argc, const_cast<const char**>(argv), options);
2019-11-21 18:03:13 +03:00
}
2021-07-26 13:17:06 +03:00
bool Params::parseParams(const QStringList &paramsArray, const OptionsDataList &options) {
2018-09-29 15:56:04 +03:00
params.clear();
2021-07-26 13:17:06 +03:00
OptionsDataList availableOptions;
2021-07-27 17:24:43 +03:00
parseAvailableOptions(OptionsDataList{}.unite(options).unite(availableArguments()),
&availableOptions,
&userHelp);
2019-01-27 19:45:30 +03:00
#ifdef Q_OS_WIN
char buffer[MAX_PATH];
2019-11-01 20:39:44 +03:00
memset(buffer, 0, sizeof buffer);
2019-11-01 20:28:17 +03:00
2019-01-27 19:45:30 +03:00
GetModuleFileNameA(nullptr, buffer, MAX_PATH);
appPath = QFileInfo(buffer).absolutePath();
appName = QFileInfo(buffer).fileName();
2022-02-09 09:57:01 +03:00
#endif
2022-02-09 09:57:01 +03:00
#ifdef Q_OS_LINUX
2019-01-27 20:14:06 +03:00
char path[2048];
2019-11-01 20:28:17 +03:00
memset(path, 0, sizeof path);
2019-05-10 09:56:07 +03:00
if (readlink("/proc/self/exe", path, 2048) < 0) {
2020-04-04 15:42:56 +03:00
QuasarAppUtils::Params::log("parseParams can't get self path!",
QuasarAppUtils::Error);
2019-05-10 09:56:07 +03:00
return false;
}
appPath = QFileInfo(path).absolutePath();
appName = QFileInfo(path).fileName();
2022-02-09 09:57:01 +03:00
#endif
#ifdef Q_OS_DARWIN
appPath = QCoreApplication::applicationDirPath();
appName = QCoreApplication::applicationName();
2019-01-27 19:45:30 +03:00
#endif
if (!appPath.size()) {
2019-01-27 19:45:30 +03:00
return false;
}
2018-09-29 15:56:04 +03:00
if (!optionsForEach(paramsArray, availableOptions)) {
return false;
2018-09-29 15:56:04 +03:00
}
printWorkingOptions();
2018-09-29 15:56:04 +03:00
return true;
}
void Params::printWorkingOptions() {
QuasarAppUtils::Params::log("--- Working options table start ---",
QuasarAppUtils::Debug);
2021-03-26 17:18:29 +03:00
QMap<QString, QString>::const_iterator iter = params.constBegin();
while (iter != params.constEnd()) {
QString row = QString{"Option[%0]"}.arg(iter.key());
2021-03-26 17:18:29 +03:00
QString value = iter.value();
if (!value.isEmpty()) {
row += QString{": %1"}.arg(value);
}
QuasarAppUtils::Params::log(row, QuasarAppUtils::Debug);
++iter;
}
QuasarAppUtils::Params::log("--- Working options table end ---",
QuasarAppUtils::Debug);
}
2021-07-28 12:38:44 +03:00
bool Params::checkOption(const OptionData& optionData, const QString& rawOptionName) {
#ifndef QA_ALLOW_NOT_SUPPORTED_OPTIONS
2021-07-28 12:38:44 +03:00
if (!optionData.isValid()) {
QuasarAppUtils::Params::log(QString("The '%0' option not exists!"
" You use wrong option name, please check the help before run your commnad.").arg(
rawOptionName),
2021-07-28 12:38:44 +03:00
QuasarAppUtils::Error);
return false;
}
#else
Q_UNUSED(rawOptionName);
#endif
2021-07-28 12:38:44 +03:00
if (optionData.isDepricated()) {
if (optionData.isRemoved()) {
QuasarAppUtils::Params::log(optionData.depricatedMsg(),
QuasarAppUtils::Error);
return false;
}
QuasarAppUtils::Params::log(optionData.depricatedMsg(),
QuasarAppUtils::Warning);
}
return true;
}
2021-07-26 13:17:06 +03:00
void Params::parseAvailableOptions(const OptionsDataList &availableOptionsListIn,
OptionsDataList *availableOptionsListOut,
Help::Section *helpOut) {
if (!(availableOptionsListOut && helpOut))
return;
2021-07-28 12:38:44 +03:00
helpOut->clear();
2021-07-27 17:24:43 +03:00
QHash<QString, Help::Options> options;
2021-07-26 13:17:06 +03:00
for (auto it = availableOptionsListIn.begin(); it != availableOptionsListIn.end(); ++it) {
if (availableOptionsListOut) {
2021-07-27 17:24:43 +03:00
for (const auto &name : qAsConst(it.value().names())) {
availableOptionsListOut->insert(name, it.value());
}
2021-07-26 13:17:06 +03:00
}
if (helpOut) {
2021-07-27 17:24:43 +03:00
options[it.key()].unite(it.value().toHelp());
2021-07-26 13:17:06 +03:00
}
}
2021-07-27 17:24:43 +03:00
for (auto it = options.begin(); it != options.end(); ++it) {
helpOut->insert(it.key(), it.value());
}
2021-07-26 13:17:06 +03:00
}
2021-03-26 17:18:29 +03:00
QString Params::getArg(const QString& key,const QString& def) {
2019-08-26 21:15:34 +03:00
return params.value(key, def);
2018-09-29 15:56:04 +03:00
}
2019-02-02 16:01:28 +03:00
2021-03-26 17:18:29 +03:00
void Params::setArg(const QString &key, const QString &val) {
2019-02-02 16:01:28 +03:00
params.insert(key, val);
}
void Params::setEnable(const QString &key, bool enable) {
if (enable) {
params.insert(key, "");
} else {
params.remove(key);
}
}