Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

@@ -0,0 +1,33 @@
#
# $Id: CMakeLists.txt 51804 2020-07-31 04:47:28Z fritsche_h $
# $HeadURL: svn://slssvn/TDS/branches/product/iterations/21_03_salted_caramel/Lts/Plugins/TakeHomePackageManager/CMakeLists.txt $
# $Author: fritsche_h $
#
# Created by Mike Wille, SLTE, 2024-01-11
#
SET(src
#logger.cpp
#logger.h
tpm_js_parser.cpp
tpm_js_parser.h
tpm_tools.cpp
tpm_tools.h
)
NGL_ADD_LIBRARY2(WS SV Thp2CommonCore SHARED ${src}) # SV because FLM Service (httq server) uses Thp2CommonCore, too
NGL_TARGET_COMPILE_DEFINITIONS(Thp2CommonCore PRIVATE L=QStringLiteral)
NGL_TARGET_INCLUDE_DIRECTORIES(Thp2CommonCore
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
${CMAKE_CURRENT_BINARY_DIR}/../ # export file
)
NGL_TARGET_LINK_LIBRARIES(Thp2CommonCore
PRIVATE
Qt5::Core
#NGLLogger
LtsUtilsCoreHeaderOnly
)
NGL_INSTALL_TARGET(Thp2CommonCore)
@@ -0,0 +1,39 @@
/**
* @RDE_HEADER@
* Building Config - logging facility
* $Id: logger.cpp 46225 2019-03-25 13:59:56Z rudolphus_g $
* $HeadURL: svn://slssvn/TDS/branches/product/iterations/21_03_salted_caramel/Lts/Plugins/TakeHomePackageManager/logger.cpp $
* $Author: rudolphus_g $
*
* Created by Mike Wille, SLTE, 2024-01-11
*/
#include "logger.h"
#include <NGLLogger/NGLLoggerBootstrap.h>
namespace TakeHomePackageManager
{
LOGGER_T getLogger(const char *name)
{
static const char ns[] = "TPM2.CommonCore.";
std::string loggerName;
const size_t len = strlen(name);
loggerName.reserve(sizeof(ns) + len);
loggerName.append(ns, sizeof(ns) - 1);
loggerName.append(name, len);
try
{
return NGL::NGLLoggerBootstrap::getNGLRootLogger().
getNGLLogger(loggerName);
}
catch (const std::exception &ex)
{
fprintf(stderr, "Error retrieving logger: %s", ex.what());
abort();
}
}
} // namespace TakeHomePackageManager
@@ -0,0 +1,24 @@
/**
* @RDE_HEADER@
* Logging for CentralEffectSimulation
* $Id: logger.h 46225 2019-03-25 13:59:56Z rudolphus_g $
* $HeadURL: svn://slssvn/TDS/branches/product/iterations/21_03_salted_caramel/Lts/Plugins/TakeHomePackageManager/logger.h $
* $Author: rudolphus_g $
*
* Created by Mike Wille, SLTE, 2024-01-11
*/
#pragma once
#include <NGLLogger/INGLLogger.h>
namespace TakeHomePackageManager
{
typedef NGL::INGLLogger &LOGGER_T;
LOGGER_T getLogger(const char *name);
inline LOGGER_T getLogger(const QString &loggerName)
{
return getLogger(loggerName.toUtf8().constData());
}
} // namespace TakeHomePackageManager
@@ -0,0 +1,544 @@
/**
* @RDE_HEADER@
* topics.js parser
* $Id: tpm_exported_scripts_model.h 53111 2021-03-22 08:21:29Z wille_m $
* $HeadURL: svn://slssvn/TDS/branches/product/iterations/21_03_salted_caramel/Lts/Plugins/TakeHomePackageManager/tpm_exported_scripts_model.h $
* $Author: wille_m $
*
* Created by Mike Wille, EZSZ, 2024-02-12
*/
#include "tpm_js_parser.h"
//#include <logger.h>
#include <tpm_tools.h>
#include <LtsUtilsCore/json.h>
#include <QMapIterator>
#include <utility>
#include <QDebug>
std::string error(const QString &msg) { return msg.toStdString(); }
using namespace std;
#ifndef DLOG
#define DLOG DEBUG_LOG(m_logger)
#endif
using namespace LtsUtils;
namespace TakeHomePackageManager
{
/// JsObjectParser
template<>
/*static*/ JsonObject JsParser<JsonObject, QJsonObject>::parse(const QByteArray &data) noexcept(false)
{
return JsonObject::fromJsonSafe(_parse(data, true).toUtf8());
}
template<>
JsParser<JsonObject, QJsonObject>::JsParser(const QString &globalThisName, const QString &filePath, bool mustExist) noexcept(false)
: m_globalThisName(globalThisName)
, m_filePath(filePath)
, m_json(load(mustExist))
//, m_logger(getLogger("JsObjectParser"))
{
qWarning() << "OBJECT - m_globalThisName" << m_globalThisName << "m_filePath" << m_filePath << "m_json" << m_json.object().count();
}
template<>
QJsonDocument JsParser<JsonObject, QJsonObject>::document() const
{
return QJsonDocument(static_cast<const QJsonObject &>(m_json));
}
template<>
/*static*/ const QJsonObject &JsParser<JsonObject, QJsonObject>::get() const
{
return m_json;
}
///// JsArrayParser
template<>
/*static*/ JsonArray JsParser<JsonArray, QJsonArray>::parse(const QByteArray &data) noexcept(false)
{
return JsonArray::fromJsonSafe(_parse(data, false).toUtf8());
}
template<>
JsParser<JsonArray, QJsonArray>::JsParser(const QString &globalThisName, const QString &filePath, bool mustExist) noexcept(false)
: m_globalThisName(globalThisName)
, m_filePath(filePath)
, m_json(load(mustExist))
//, m_logger(getLogger("JsArrayParser"))
{
qWarning() << "ARRAY - m_globalThisName" << m_globalThisName << "m_filePath" << m_filePath << "m_json" << m_json.size();
}
template<>
QJsonDocument JsParser<JsonArray, QJsonArray>::document() const
{
return QJsonDocument(m_json());
}
template<>
/*static*/ const QJsonArray &JsParser<JsonArray, QJsonArray>::get() const
{
return m_json();
}
/// JsParser
template<typename LtsJsonType, typename QJsonType>
void JsParser<LtsJsonType, QJsonType>::save() noexcept(false)
{
if (!m_dataChanged)
{
return;
}
auto file(openSaveFile(m_filePath)); // throws (incl. dtor)
file->write(L("globalThis.%1 = \n").arg(m_globalThisName).toUtf8());
file->write(document().toJson(QJsonDocument::JsonFormat::Indented /* adds \n to the end */));
file->write(";");
}
template<typename LtsJsonType, typename QJsonType>
/*static*/ QByteArray JsParser<LtsJsonType, QJsonType>:: _load(bool mustExist) const noexcept(false)
{
const auto data(readFile(m_filePath, mustExist));
qWarning() << "JsParser: file" << m_filePath << "######################## content:" << data;
if (data.isEmpty())
{
return {};
}
return data;
}
template<typename LtsJsonType, typename QJsonType>
/*static*/ QString JsParser<LtsJsonType, QJsonType>::_parse(const QByteArray &data, bool isObject) noexcept(false)
{
const QString opener((isObject) ? L("{") : L("["));
const QString closer((isObject) ? L("}") : L("]"));
const QRegExp regexp(L(R"RRR(\%1[\S\s]*\%2)RRR").arg(opener, closer));
const QString topicsJsText(QString::fromUtf8(data));
//DLOG << "topicsJsText: " << topicsJsText;
if (regexp.indexIn(topicsJsText) < 0)
{
//throw runtime_error(L("no %1 with name '%2' in js-file '%3' found").arg(isObject ? L("object") : L("array").arg(globalThisName, filePath).toStdString());
throw runtime_error(L("no %1 in js-file found").arg(isObject ? L("object") : L("array")).toStdString());
}
// js file, not a json file, so get the first '[' and the last ']' to get the pure json compatible data structure from the incompatible javascript (see regexp pattern above)
const QString jsonString(regexp.cap());
//DLOG << "jsonString: " << jsonString;
qWarning() << "jsonString" << jsonString;
return jsonString;
}
template<typename LtsJsonType, typename QJsonType>
/*static*/ LtsJsonType JsParser<LtsJsonType, QJsonType>::load(bool mustExist) const noexcept(false)
{
auto data = _load(mustExist);
if (data.isEmpty())
{
if (mustExist)
{
throw runtime_error("js-file is missing content");
}
qWarning() << ":(";
return {};
}
return parse(data);
}
template<typename LtsJsonType, typename QJsonType>
/*static*/ void JsParser<LtsJsonType, QJsonType>::write(const QString &globalThisName, const QJsonType &json, const QString &filePath, bool mustExist) noexcept(false)
{
auto parser = JsParser<LtsJsonType, QJsonType>(globalThisName, filePath, mustExist);
parser.set(json);
parser.save();
}
template void JsParser<JsonObject, QJsonObject>::write(const QString &globalThisName, const QJsonObject &json, const QString &filePath, bool mustExist) noexcept(false);
template void JsParser<JsonArray, QJsonArray>::write(const QString &globalThisName, const QJsonArray &json, const QString &filePath, bool mustExist) noexcept(false);
template<typename LtsJsonType, typename QJsonType>
void JsParser<LtsJsonType, QJsonType>::set(const QJsonType &json)
{
m_json = LtsJsonType(json);
m_dataChanged = true;
}
template void JsParser<JsonObject, QJsonObject>::set(const QJsonObject &json);
template void JsParser<JsonArray, QJsonArray>::set(const QJsonArray &json);
template<typename LtsJsonType, typename QJsonType>
/*static*/ QJsonType JsParser<LtsJsonType, QJsonType>::read(const QString &globalThisName, const QString &filePath, bool mustExist) noexcept(false)
{
return JsParser(globalThisName, filePath, mustExist).get();
}
template QJsonObject JsParser<JsonObject, QJsonObject>::read(const QString &globalThisName, const QString &filePath, bool mustExist) noexcept(false);
template QJsonArray JsParser<JsonArray, QJsonArray>::read(const QString &globalThisName, const QString &filePath, bool mustExist) noexcept(false);
/// ScriptsJsParser
ScriptsJsParser::ScriptsJsParser(const QString &root, bool mustExist) noexcept(false)
: JsObjectParser(L("scriptsJs"), scriptsJsLocation(root), mustExist)
{
const QJsonObject obj(get());
qWarning() << "ScriptsJsParser" << obj;
for (auto it = obj.constBegin(); it != obj.constEnd(); ++it)
{
const auto esi(ExportedScriptInformation::fromJson(it.value(), true /* local */, ExportedScriptInformation::UploadState::ThpUnknownUploadState));
qWarning() << "adding" << esi.id();
//DEBUG_LOG(m_logger) << "obj=" << QJsonDocument(obj).toJson(QJsonDocument::Compact);
//esi.rootDirectory = rootDirectoryToScan; // to determine if this script is from THP-Download or THP-Export directory (for USB Management, which can copy from both dirs)
m_esis.insert(esi.id(), esi);
}
}
//ScriptsJsParser::~ScriptsJsParser() noexcept(false)
void ScriptsJsParser::save() noexcept(false)
{
QJsonObject obj;
QMapIterator<QString, ExportedScriptInformation> it(m_esis);
while (it.hasNext())
{
auto &esi = it.next().value();
obj.insert(esi.id(), esi.toJson());
}
set(obj);
JsParser::save();
}
const QMap<QString, ExportedScriptInformation> &ScriptsJsParser::getExportedScriptInformations() const
{
return m_esis;
}
const ExportedScriptInformation &ScriptsJsParser::getExportedScriptInformation(const QString &scriptId) const noexcept(false)
{
auto it = m_esis.constFind(scriptId);
if (it == m_esis.constEnd())
{
throw L("getExportedScriptInformation: script with id '%1' not found").arg(scriptId);
}
return it.value();
}
bool ScriptsJsParser::hasExportedScriptInformation(const QString &scriptId) const
{
return m_esis.contains(scriptId);
}
void ScriptsJsParser::setExportedScriptInformations(const QVector<ExportedScriptInformation> &esis) noexcept(false)
{
m_esis.clear();
addExportedScriptInformations(esis);
}
void ScriptsJsParser::addExportedScriptInformations(const QVector<ExportedScriptInformation> &esis) noexcept(false)
{
for (const ExportedScriptInformation &esi : esis)
addExportedScriptInformation(esi);
}
void ScriptsJsParser::addExportedScriptInformation(const ExportedScriptInformation &esi) noexcept(false)
{
m_esis.insert(esi.id(), esi);
m_dataChanged = true;
}
void ScriptsJsParser::removeExportedScriptInformation(const QString &scriptId) noexcept(false)
{
if (m_esis.remove(scriptId) != 1)
{
throw L("removeExportedScriptInformation: unable to remove script with id '%1' because it was not found").arg(scriptId);
}
m_dataChanged = true;
}
///// TopicsJsParser
//TopicsJsParser::TopicsJsParser(const QString &root, bool mustExist) noexcept(false)
// : JsArrayParser(L("topicsJs"), scriptsJsLocation(root), mustExist)
//{
// const auto topics = Topic::topicsFromJson(get());
// qWarning() << "TopicsJsParser: topics " << topics.count();
// for (const auto &topic : topics)
// {
// qWarning() << "adding" << topic.id;
// m_topics.insert(topic.id, topic);
// }
//}
//void TopicsJsParser::save() noexcept(false)
//{
// QJsonArray arr;
// QMapIterator<int, Topic> it(m_topics);
// while (it.hasNext())
// {
// auto &topic = it.next().value();
// arr += topic.toJson();
// }
// set(arr);
// JsParser::save();
//}
//const QMap<int, Topic> &TopicsJsParser::getTopics() const
//{
// return m_topics;
//}
//const Topic &TopicsJsParser::getTopic(const int topicId) const noexcept(false)
//{
// auto it = m_topics.constFind(topicId);
// if (it == m_topics.constEnd())
// {
// throw L("getTopic: topic with id '%1' not found").arg(topicId);
// }
// return it.value();
//}
//bool TopicsJsParser::hasTopic(const int topicId) const
//{
// return m_topics.contains(topicId);
//}
//void TopicsJsParser::setTopics(const QVector<Topic> &topics) noexcept(false)
//{
// m_topics.clear();
// addTopics(topics);
//}
//void TopicsJsParser::addTopics(const QVector<Topic> &topics) noexcept(false)
//{
// for (const Topic &topic : topics)
// addTopic(topic);
//}
//void TopicsJsParser::addTopic(const Topic &topic) noexcept(false)
//{
// m_topics.insert(topic.id, topic);
// m_dataChanged = true;
//}
//void TopicsJsParser::removeTopic(const int topicId) noexcept(false)
//{
// if (m_topics.remove(topicId) != 1)
// {
// throw L("removeTopic: unable to remove topic with id '%1' because it was not found").arg(topicId);
// }
// m_dataChanged = true;
//}
/// ExportedScriptInformation
QJsonObject dateTimeToJson(const QDateTime &dt)
{
return { { L("iso"), dt.toUTC().toString(Qt::DateFormat::ISODate) }, { L("secsSinceEpoch"), dt.toSecsSinceEpoch() } };
}
QDateTime jsonToDateTime(const QJsonValue &val) noexcept(false)
{
bool k = false;
auto ret = QDateTime::fromSecsSinceEpoch(val.toObject()[L("secsSinceEpoch")].toVariant().toULongLong(&k));
if (!k)
{
throw std::runtime_error("jsonToDateTime: !k");
}
if (!ret.isValid())
{
throw std::runtime_error("jsonToDateTime: !ret.isValid()");
}
return ret;
}
QString ExportedScriptInformation::id() const
{
return L("%1.%2%3").arg(exercise.id).arg(script.id).arg(script.customName.isEmpty() ? QString() : L("-%1").arg(script.customName));
}
QJsonValue ExportedScriptInformation::toJson() const
{
QJsonObject ret({
{ L("createdAt"), dateTimeToJson(createdAt) },
{ L("exerciseId"), exercise.id },
{ L("exerciseName"), exercise.name },
{ L("scriptId"), script.id },
{ L("scriptName"), script.name }
});
if (!script.customName.isEmpty()) // js's '...' operator would be very handy here
{
ret[L("scriptCustomName")] = script.customName; // optional, needed for usb exports where some topics were unselected by the user
}
// if (uploadedAt.isValid())
// ret[L("uploadedAt")] = dateTimeToJson(uploadedAt);
// if (downloadedAt.isValid())
// ret[L("downloadedAt")] = dateTimeToJson(downloadedAt);
return ret;
}
ExportedScriptInformation ExportedScriptInformation::fromJson(const QJsonValue &val,
const bool local,
const UploadState uploadState) noexcept(false)
{
const QJsonObject obj(val.toObject());
ExportedScriptInformation esi;
const auto createdAt = jsonToDateTime(obj[L("createdAt")]);
if (local)
{
esi.createdAt = createdAt;
}
if (uploadState == UploadState::ThpAlreadyUploaded)
{
esi.createdAtServer = createdAt;
}
esi.script.id = obj[L("scriptId")].toInt();
esi.script.name = obj[L("scriptName")].toString();
auto scriptCustomNameValIt = obj.constFind(L("scriptCustomName")); // optional
if (scriptCustomNameValIt != obj.constEnd())
{
esi.script.customName = scriptCustomNameValIt->toString();
}
esi.exercise.id = obj[L("exerciseId")].toInt();
esi.exercise.name = obj[L("exerciseName")].toString();
if (esi.script.id < 1 || esi.script.name.isEmpty() || esi.exercise.id < 1 || esi.exercise.name.isEmpty())
{
throw std::runtime_error("one or more of (script id / script name / exc id / exc name) missing");
}
esi.local = local;
esi.uploaded = uploadState;
return esi;
}
/// Topic
//QJsonObject Topic::toJson() const
//{
// every topic type is different.....
//}
/*static*/ Topic Topic::topicFromJson(const QJsonObject &obj) noexcept(false)
{
const JsonObject o(obj);
// no optional :(
const auto filterKey = JsonObject::Key(L("filter"));
Topic t; // initializer list too nice for 42.3 :'(
t.id = o.value<int>(L("id"));
t.channel = o.value<int>(L("channel"));
t.description = o.value<QString>(L("description"));
t.type = o.value<int>(L("type"));
t.start = o.value<int>(L("start"));
t.duration = o.value<int>(L("duration"));
t.filename = o.valueOr<QString>(L("filename"), o.valueOr<QString>(L("src"), {}));
t.filter = (o.isNull(filterKey) ? -1 : o.value<int>(filterKey));
t.filterSet = o.contains<int>(filterKey);
return t;
}
/*static*/ QVector<Topic> Topic::topicsFromJson(const QJsonArray &arr) noexcept(false)
{
QVector<Topic> ret;
for (const auto &val : arr)
{
const QJsonObject obj(val.toObject());
ret += topicFromJson(obj);
}
return ret;
}
} // namespace TakeHomePackageManager
@@ -0,0 +1,190 @@
#pragma once
/**
* @RDE_HEADER@
* js-file parsers & specific script.js & topics.js parsers
* $Id: tpm_exported_scripts_model.h 53111 2021-03-22 08:21:29Z wille_m $
* $HeadURL: svn://slssvn/TDS/branches/product/iterations/21_03_salted_caramel/Lts/Plugins/TakeHomePackageManager/tpm_exported_scripts_model.h $
* $Author: wille_m $
*
* Created by Mike Wille, EZSZ, 2024-02-12
*/
#include <Common2Core/thp2commoncore_export.h>
//#include <NGLLogger/INGLLogger.h>
#include <LtsUtilsCore/json.h>
#include <Common2Core/tpm_tools.h>
#include <QJsonArray>
#include <QFile>
#include <QMap>
using namespace LtsUtils;
namespace TakeHomePackageManager
{
/// JsParser
template <typename LtsJsonType, typename QJsonType>
class THP2COMMONCORE_EXPORT JsParser
{
public:
explicit JsParser(const QString &globalThisName, const QString &filePath, bool mustExist = false) noexcept(false);
void save() noexcept(false);
static QJsonType read(const QString &globalThisName, const QString &filePath, bool mustExist = false) noexcept(false);
static void write(const QString &globalThisName, const QJsonType &json, const QString &filePath, bool mustExist = false) noexcept(false);
static LtsJsonType parse(const QByteArray &data) noexcept(false);
QJsonDocument document() const;
const QJsonType &get() const;
void set(const QJsonType &json);
protected:
LtsJsonType load(bool mustExist) const noexcept(false);
static QString _parse(const QByteArray &data, bool isObject) noexcept(false);
QByteArray _load(bool mustExist) const noexcept(false);
const QString m_globalThisName;
const QString m_filePath;
LtsJsonType m_json;
bool m_dataChanged { false };
};
template class THP2COMMONCORE_EXPORT JsParser<JsonObject, QJsonObject>;
using JsObjectParser = JsParser<JsonObject, QJsonObject>;
template class THP2COMMONCORE_EXPORT JsParser<JsonArray, QJsonArray>;
using JsArrayParser = JsParser<JsonArray, QJsonArray>;
/// ExportedScriptInformation
struct THP2COMMONCORE_EXPORT ExportedScriptInformation
{
enum class UploadState
{
ThpUnknownUploadState,
ThpNotUploaded,
ThpAlreadyUploaded,
};
struct Exercise
{
int id;
QString name;
};
struct Script
{
int id;
QString name;
QString customName;
};
bool operator==(const ExportedScriptInformation &other) const
{
return (id() == other.id());
}
QString id() const;
QDateTime createdAt; // NOTE: invalid if script only on server
Exercise exercise;
Script script;
// things not saved to json - only informational
QDateTime createdAtServer = {};
bool local = true; // only set to false if it's from setServerContent and NOT locally available!
UploadState uploaded = UploadState::ThpUnknownUploadState;
void setLocal(const QDateTime &_createdAt) { local = true; createdAt = _createdAt; }
void unsetLocal() { local = false; createdAt = {}; }
bool isUploaded() const { return (uploaded == UploadState::ThpAlreadyUploaded); }
void setUploaded(const QDateTime &_createdAtServer) { uploaded = UploadState::ThpAlreadyUploaded; createdAtServer = _createdAtServer; }
void unsetUploaded() { uploaded = UploadState::ThpNotUploaded; createdAtServer= {}; }
QJsonValue toJson() const;
static ExportedScriptInformation fromJson(const QJsonValue &val,
const bool local = true,
const UploadState uploadState = UploadState::ThpUnknownUploadState);
};
/// ScriptsJsParser
class THP2COMMONCORE_EXPORT ScriptsJsParser : /*protected*/ public JsObjectParser
{
public:
ScriptsJsParser(const QString &root, bool mustExist = false) noexcept(false);
void save() noexcept(false);
const QMap<QString, ExportedScriptInformation> &getExportedScriptInformations() const;
const ExportedScriptInformation &getExportedScriptInformation(const QString &scriptId) const noexcept(false);
bool hasExportedScriptInformation(const QString &scriptId) const;
void setExportedScriptInformations(const QVector<ExportedScriptInformation> &esis) noexcept(false);
void addExportedScriptInformation(const ExportedScriptInformation &esi) noexcept(false);
void addExportedScriptInformations(const QVector<ExportedScriptInformation> &esis) noexcept(false);
void removeExportedScriptInformation(const QString &scriptId) noexcept(false);
private:
QMap<QString /*scriptId*/, ExportedScriptInformation> m_esis;
bool m_dataChanged { false };
};
/// Topic
struct THP2COMMONCORE_EXPORT Topic
{
int id;
int channel;
QString description; // user given description
int type;
int start;
int duration;
QString filename;
// bool getFilter(int &_filter) // TODO: optional Ò_ó
// {
// if (filterSet)
// _filter = filter;
// return filterSet;
// }
//private:
int filter;
bool filterSet = false;
static Topic topicFromJson(const QJsonObject &obj) noexcept(false);
static QVector<Topic> topicsFromJson(const QJsonArray &arr) noexcept(false);
//QJsonObject toJson() const;
};
///// TopicsJsParser
//class THP2COMMONCORE_EXPORT TopicsJsParser : /*protected*/ public JsArrayParser
//{
//public:
// TopicsJsParser(const QString &root, bool mustExist = false) noexcept(false);
// void save() noexcept(false);
// const QMap<int, Topic> &getTopics() const;
// const Topic &getTopic(const int topicId) const noexcept(false);
// bool hasTopic(const int topicId) const;
// void setTopics(const QVector<Topic> &topics) noexcept(false);
// void addTopic(const Topic &topic) noexcept(false);
// void addTopics(const QVector<Topic> &topics) noexcept(false);
// void removeTopic(const int topicId) noexcept(false);
//private:
// QMap<int /*topicId*/, Topic> m_topics;
// bool m_dataChanged { false };
//};
} // namespace TakeHomePackageManager
@@ -0,0 +1,159 @@
/**
* @RDE_HEADER@
* Some useful tools to be shared
* $Id: tpm_exported_scripts_model.h 53111 2021-03-22 08:21:29Z wille_m $
* $HeadURL: svn://slssvn/TDS/branches/product/iterations/21_03_salted_caramel/Lts/Plugins/TakeHomePackageManager/tpm_exported_scripts_model.h $
* $Author: wille_m $
*
* Created by Mike Wille, EZSZ, 2024-02-12
*/
#include "tpm_tools.h"
#include "tpm_js_parser.h"
#include <QFile>
#include <QSaveFile>
#include <QDir>
#include <memory>
using namespace std;
//std::string error(const QString &msg) { return msg.toStdString(); }
namespace TakeHomePackageManager
{
/// SaveFile
SaveFile::SaveFile(SaveFile &&other)
{
m_saveFile.swap(other.m_saveFile);
}
SaveFile::SaveFile(const QString &filePath) noexcept(false)
: m_saveFile(new QSaveFile(filePath))
{}
SaveFile::~SaveFile() noexcept(false)
{
if (!m_saveFile->isOpen())
{
return;
}
if (!m_saveFile->commit())
{
throw std::runtime_error("Commit on temporary save file '" + m_saveFile->fileName().toStdString() + "' failed: " + m_saveFile->errorString().toStdString());
}
}
SaveFile SaveFile::open(const QString &filePath) noexcept(false)
{
SaveFile f(filePath);
if (!f->open(QIODevice::OpenModeFlag::WriteOnly /* implies truncate */))
{
throw runtime_error("Failed to create temporary save file '" + filePath.toStdString() + "': " + f->errorString().toStdString());
}
return f;
}
/// etc.
QString localThpDir() { return (QDir::homePath() + QDir::separator() + L("THP2")); } // e.g. /shd/CTC/WS/THP2
QString serverThpDir() { return (QDir::homePath() + QDir::separator() + L("THP2-Uploads")); } // e.g. /shd/CTC/SV/THP2-Uploads
QString thpOverviewLocation() { return L("/shd/CTC/WS/share/Lts/THP-overview"); }
QString scriptsLocation(const QString &root) { return root + QDir::separator() + L("scripts"); } // e.g. /shd/CTC/WS/THP2/scripts
QString scriptsJsLocation(const QString &root) { return scriptsLocation(root) + QDir::separator() + L("scripts.js"); } // e.g. /shd/CTC/WS/THP2/scripts/scripts.js
QString scriptLocation(const QString &root, const QString &scriptId) { return scriptsLocation(root) + QDir::separator() + scriptId; } // NOTE: counterpart of scriptArchiveLocation
QString scriptHtmlLocation(const QString &root, const QString &scriptId) { return scriptLocation(root, scriptId) + QDir::separator() + L("index.html"); }
QString scriptArchiveLocation(const QString &root, const QString &scriptId) { return scriptLocation(root, scriptId) + L(".tar.bz2"); } // NOTE: FLM only! client uploads as archive - server stores as archive (use instead of scriptLocation)
QString topicsLocation(const QString &root, const QString &scriptId) { return scriptLocation(root, scriptId) + QDir::separator() + L("topics"); }
QString topicsJsLocation(const QString &root, const QString &scriptId) { return topicsLocation(root, scriptId) + QDir::separator() + L("topics.js"); }
QString topicLocation(const QString &root, const QString &scriptId, const QString &topicFilename) { return topicsLocation(root, scriptId) + QDir::separator() + topicFilename; }
//QVector<ExportedScriptInformation> esisFromScriptsJs(const QString &thpRoot) noexcept(false)
//{
// const QJsonObject obj(JsObjectParser::read(L("scriptsJs"), scriptsJsLocation(thpRoot), false));
// QVector<ExportedScriptInformation> esis;
// esis.reserve(obj.count());
// for (auto it = obj.constBegin(); it != obj.constEnd(); ++it)
// {
// const auto esi(ExportedScriptInformation::fromJson(it.value(), true /* local */, ExportedScriptInformation::UploadState::ThpUnknownUploadState));
// //DEBUG_LOG(m_logger) << "obj=" << QJsonDocument(obj).toJson(QJsonDocument::Compact);
// //esi.rootDirectory = rootDirectoryToScan; // to determine if this script is from THP-Download or THP-Export directory (for USB Management, which can copy from both dirs)
// esis.push_back(esi);
// }
// return esis;
//}
SaveFile openSaveFile(const QString &filePath) noexcept(false)
{
return SaveFile::open(filePath);
}
void writeSaveFile(const QString &filePath, const QByteArray &content) noexcept(false)
{
SaveFile f(openSaveFile(filePath));
f->write(content);
}
QByteArray readFile(const QString &filename, bool mustExist) noexcept(false)
{
QFile f(filename);
if (!f.exists())
{
if (mustExist)
{
throw runtime_error("File '" + filename.toStdString() + "' doesn't exist");
}
return {};
}
if (!f.open(QIODevice::ReadOnly))
{
throw runtime_error("Unable to read file at " + filename.toStdString() + ": " + f.errorString().toStdString());
}
return f.readAll();
}
void openFile(QFile &file, bool readOnly, bool existingOnly) noexcept(false)
{
QFlags<QIODevice::OpenModeFlag> flags(QIODevice::ReadWrite);
if (readOnly)
{
flags.setFlag(QIODevice::ReadOnly);
}
// if (existingOnly)
// {
// flags.setFlag(QIODevice::ExistingOnly); 42.3 is missing this flag -.-
// }
// polyfill for above ^
if (!file.exists() && existingOnly)
{
throw runtime_error("Unable to open file '" + file.fileName().toStdString() + "' for " + (readOnly ? "reading" : "r/w") + ": <file does not exist!>");
}
if (!file.open(flags))
{
throw runtime_error("Unable to open file '" + file.fileName().toStdString() + "' for " + (readOnly ? "reading" : "r/w") + ": " + file.errorString().toStdString());
}
}
} // namespace TakeHomePackageManager
@@ -0,0 +1,174 @@
#pragma once
/**
* @RDE_HEADER@
* Some useful tools to be shared
* $Id: tpm_exported_scripts_model.h 53111 2021-03-22 08:21:29Z wille_m $
* $HeadURL: svn://slssvn/TDS/branches/product/iterations/21_03_salted_caramel/Lts/Plugins/TakeHomePackageManager/tpm_exported_scripts_model.h $
* $Author: wille_m $
*
* Created by Mike Wille, EZSZ, 2024-02-12
*/
//#include <logger.h>
#include <Common2Core/thp2commoncore_export.h>
#include <memory>
#include <QSaveFile>
#include <QEventLoop>
#include <QTimer>
#include <QDateTime>
#include <QDebug>
#ifdef Q_OS_UNIX
#define _compiler_warning(x) _Pragma(#x)
#define compiler_warning(x) _compiler_warning(GCC warning x)
#else
#define compiler_warning(x)
#endif
class QFile;
namespace TakeHomePackageManager
{
/// SaveFile
class THP2COMMONCORE_EXPORT SaveFile // NOTE: auto-commits - call `->cancelWriting()` to not commit the file
{
public:
SaveFile() = delete;
SaveFile(SaveFile &&other);
~SaveFile() noexcept(false);
static SaveFile open(const QString &filePath) noexcept(false);
QSaveFile *get() { return m_saveFile.get(); }
QSaveFile *operator->() { return m_saveFile.get(); }
private:
explicit SaveFile(const QString &filePath) noexcept(false);
std::unique_ptr<QSaveFile> m_saveFile;
};
/// etc.
THP2COMMONCORE_EXPORT void writeSaveFile(const QString &filePath, const QByteArray &content) noexcept(false);
THP2COMMONCORE_EXPORT QByteArray readFile(const QString &filename, bool mustExist = false) noexcept(false);
THP2COMMONCORE_EXPORT void openFile(QFile &file, bool readOnly = false, bool existingOnly = false) noexcept(false);
THP2COMMONCORE_EXPORT void writeToFileOrRollback(QFile &file, const QByteArray &data) noexcept(false);
THP2COMMONCORE_EXPORT void writeToFileOrRollback(QFile &file, const QString &string) noexcept(false);
THP2COMMONCORE_EXPORT SaveFile openSaveFile(const QString &filePath) noexcept(false);
//THP2COMMONCORE_EXPORT QVector<ExportedScriptInformation> esisFromScriptsJs(const QString &thpRoot) noexcept(false);
THP2COMMONCORE_EXPORT QString localThpDir();
THP2COMMONCORE_EXPORT QString serverThpDir();
THP2COMMONCORE_EXPORT QString thpOverviewLocation();
THP2COMMONCORE_EXPORT QString scriptsLocation(const QString &root);
THP2COMMONCORE_EXPORT QString scriptsJsLocation(const QString &root);
THP2COMMONCORE_EXPORT QString scriptLocation(const QString &root, const QString &scriptId);
THP2COMMONCORE_EXPORT QString scriptHtmlLocation(const QString &root, const QString &scriptId);
THP2COMMONCORE_EXPORT QString scriptArchiveLocation(const QString &root, const QString &scriptId);
THP2COMMONCORE_EXPORT QString topicsJsLocation(const QString &root, const QString &scriptId);
THP2COMMONCORE_EXPORT QString topicsLocation(const QString &root, const QString &scriptId);
THP2COMMONCORE_EXPORT QString topicLocation(const QString &root, const QString &scriptId, const QString &topicFilename);
// NOTE: DeferedDelete (deleteLater) will not trigger deletions while inside any of the await functions (nested event loops)!
template <typename Func1>
void awaitx(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
const int timeoutMs = 0)
{
QEventLoop x;
QObject::connect(sender, signal, &x, &QEventLoop::quit);
std::unique_ptr<QTimer> t(new QTimer); // NOTE: do not use make_unique because of 42.3!
bool timeout = false;
if (timeoutMs > 0)
{
t->setInterval(timeoutMs);
t->setSingleShot(true);
QObject::connect(t.get(), &QTimer::timeout, &x, [&timeout](){ timeout = true; });
QObject::connect(t.get(), &QTimer::timeout, &x, &QEventLoop::quit);
}
x.exec();
if (timeout)
{
throw std::runtime_error("Timeout.");
}
}
template <typename Func1, typename Func2>
void awaitWithCancelationSignalx(const typename QtPrivate::FunctionPointer<Func1>::Object *sender1, Func1 signal1,
const typename QtPrivate::FunctionPointer<Func2>::Object *sender2, Func2 signal2,
const int timeoutMs = 0)
{
QEventLoop x;
bool success = false;
QObject::connect(sender1, signal1, &x, [&success](){ success = true; /*qWarning() << "=> SUCCESS";*/});
QObject::connect(sender1, signal1, &x, &QEventLoop::quit, Qt::QueuedConnection);
// bool cancel = false;
// QObject::connect(sender2, signal2, &x, [/*&cancel*/](){ /*cancel = true;*/ qWarning() << "=> cancel....";});
QObject::connect(sender2, signal2, &x, &QEventLoop::quit, Qt::QueuedConnection);
std::unique_ptr<QTimer> t(new QTimer); // NOTE: do not use make_unique because of 42.3!
bool timeout = false;
if (timeoutMs > 0)
{
t->setInterval(timeoutMs);
t->setSingleShot(true);
QObject::connect(t.get(), &QTimer::timeout, &x, [&timeout](){ timeout = true; });
QObject::connect(t.get(), &QTimer::timeout, &x, &QEventLoop::quit, Qt::QueuedConnection);
}
//qWarning() << "## STARTING AWAIT NOW!";
x.exec();
//qWarning() << "## AWAIT DONE!";
if (timeout && !success)
{
throw std::runtime_error("Timeout.");
}
if (!success)
{
throw std::runtime_error("Canceled.");
}
}
}