Continues migration with DDS, Common

This commit is contained in:
torsten committed 2026-07-17 12:41:42 +02:00
1 parent 9b15cee841
commit fa48db111e
668 files changed
+111841 -2

No files matched your search

+12
View File
@@ -0,0 +1,12 @@
#
# $Id$
# $HeadURL$
# $Author$
#
# Created by Mike Wille, SLSE, 2016-09-19
#
ADD_SUBDIRECTORY(LtsUtilsCore)
ADD_SUBDIRECTORY(LtsUtilsGui)
ADD_SUBDIRECTORY(LtsUtilsSettings)
+68
View File
@@ -0,0 +1,68 @@
#
# $Id$
# $HeadURL$
# $Author$
#
SET(SRCS_hdr_only
${CMAKE_CURRENT_SOURCE_DIR}/data_modification_enum.h
${CMAKE_CURRENT_SOURCE_DIR}/dds_bitarray.h
${CMAKE_CURRENT_SOURCE_DIR}/dds_vector.h
${CMAKE_CURRENT_SOURCE_DIR}/connection.h
${CMAKE_CURRENT_SOURCE_DIR}/json_object.h
${CMAKE_CURRENT_SOURCE_DIR}/outdated_position.h
${CMAKE_CURRENT_SOURCE_DIR}/qbytearray_byteaccess.h
${CMAKE_CURRENT_SOURCE_DIR}/qpoint3d.h
${CMAKE_CURRENT_SOURCE_DIR}/await.h
)
ADD_LIBRARY(LtsUtilsCoreHeaderOnly INTERFACE)
TARGET_INCLUDE_DIRECTORIES(LtsUtilsCoreHeaderOnly
INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}/../
${CMAKE_CURRENT_BINARY_DIR}/../
)
TARGET_SOURCES(LtsUtilsCoreHeaderOnly INTERFACE ${SRCS_hdr_only})
SET(SRCS
pgarray.cpp
qplane3d.cpp
qpoint3d.cpp
scoped_connection.cpp
sfm_bytemessage_converter.cpp
promise.cpp
lts_translatable_identifier.cpp
lts_portrange.cpp
#variant_operators.h
)
NGL_ADD_LIBRARY2(ALL LtsUtilsCore SHARED ${SRCS})
NGL_TARGET_INCLUDE_DIRECTORIES(LtsUtilsCore
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
${CMAKE_CURRENT_BINARY_DIR}/../
)
NGL_TARGET_LINK_LIBRARIES(LtsUtilsCore
PUBLIC
Qt5::Core
LtsUtilsCoreHeaderOnly
)
#
# --- Tests --------------------------------------------------------------
#
# IF (TARGET ddscore) // does not work, not yet included
IF((BUILD_WS OR BUILD_SV) AND BUILD_TESTING)
ADD_EXECUTABLE(utils_test
UnitTests/utils_test.cpp
UnitTests/utils_test.h
promise_examples.h
promise_examples.cpp
)
TARGET_LINK_LIBRARIES(utils_test
LtsUtilsCore
Qt5::Core
Qt5::Test
ddscore
)
ADD_TEST(NAME utils_test COMMAND $<TARGET_FILE:utils_test>)
ENDIF()
File diff suppressed because it is too large. Load diff
+62
View File
@@ -0,0 +1,62 @@
#pragma once
#include <QObject>
class LtsUtilsTest : public QObject
{
Q_OBJECT
private Q_SLOTS:
void test_toIntArray();
void test_fromIntArray();
void test_toBigintArray();
void test_fromBigintArray();
void test_toIntArray2D();
void test_fromIntArray2D();
void test_toBigintArray2D();
void test_fromBigintArray2D();
void test_QPoint3D();
void test_bitArray();
void test_convert();
void test_connection();
void test_queuedConnection();
void test_signalSignalConnection();
void test_danglingConnection1();
void test_danglingConnection2();
void test_danglingConnection3();
void test_jsonObject_fromJson();
void test_jsonObject_contains();
void test_jsonObject_value();
void test_jsonObject_valueWithError();
void test_jsonObject_valueOr();
void test_jsonObject_integers();
void test_jsonObject_nullValues();
void test_jsonArray_fromJson();
void test_jsonArray();
void test_jsonArray_nullArray();
void test_byteStreamFromSfmMessage();
void test_byteStreamFromSfmMessage2();
void test_byteStreamToSfmMessage();
void test_promise();
void test_promise_example1();
void test_promise_example2();
void test_promise_example3();
void byteAccess();
};
+116
View File
@@ -0,0 +1,116 @@
#pragma once
#include <QObject>
#include <QTimer>
#include <QEventLoop>
#include <memory>
namespace LtsUtils
{
template <typename Func>
void addConnect(QEventLoop &x, bool &success, const typename QtPrivate::FunctionPointer<Func>::Object *sender, Func signal, bool isSuccess)
{
if (isSuccess)
{
QObject::connect(sender, signal, &x, [&success]()
{
success = true;
});
}
QObject::connect(sender, signal, &x, &QEventLoop::quit, Qt::QueuedConnection);
}
template <typename Func, typename... Connect>
void addConnect(QEventLoop &x, bool &success, const typename QtPrivate::FunctionPointer<Func>::Object *sender, Func signal, bool isSuccess, Connect... connects)
{
addConnect(x, success, sender, signal, isSuccess);
addConnect(x, success, connects...);
}
template <typename... Connect>
void await(Connect... connects) noexcept(false)
{
QEventLoop x;
bool success = false;
addConnect(x, success, connects...);
x.exec();
if (!success)
{
throw std::runtime_error("Failed.");
}
}
template <typename... Connect>
void awaitTimeout(const int timeoutMs, Connect... connects) noexcept(false)
{
std::unique_ptr<QTimer> t(new QTimer);
bool timeout = false;
if (timeoutMs > -1)
{
t->setInterval(timeoutMs);
t->setSingleShot(true);
QObject::connect(t.get(), &QTimer::timeout, t.get(), [&timeout](){ fprintf(stderr, "awaitTimeout: timed out!\n"); timeout = true; });
t->start();
}
await(t.get(), &QTimer::timeout, false, connects...);
if (timeout)
{
throw std::runtime_error("Timeout.");
}
}
template <typename Func1, typename Func2>
void awaitWithCancelationSignal(const typename QtPrivate::FunctionPointer<Func1>::Object *sender1, Func1 signal1,
const typename QtPrivate::FunctionPointer<Func2>::Object *sender2, Func2 signal2,
const int timeoutMs = 0) noexcept(false)
{
if (timeoutMs > 0)
{
awaitTimeout(timeoutMs,
sender1, signal1, true,
sender2, signal2, false);
return;
}
await(sender1, signal1, true,
sender2, signal2, false);
}
}
+126
View File
@@ -0,0 +1,126 @@
#pragma once
#include <QObject>
#include <QMetaObject>
#include <QPointer>
#include <QtGlobal>
#include <type_traits>
namespace LtsUtils
{
class IConnection
{
public:
virtual ~IConnection() = default;
virtual void connect(Qt::ConnectionType = Qt::AutoConnection) = 0;
virtual void disconnect() = 0;
};
class DummyConnection : public IConnection
{
public:
void connect(Qt::ConnectionType = Qt::AutoConnection) override {}
void disconnect() override {}
};
namespace detail
{
template<class T>
struct ExtractClass;
template<class T, class Member>
struct ExtractClass<Member T::*>
{
using type = T;
};
}
template<class Signal, class Slot>
class Connection : public IConnection
{
static_assert(std::is_member_function_pointer<Signal>::value, "Must be a pointer to method");
static_assert(std::is_member_function_pointer<Slot>::value, "Must be a pointer to method");
using Emitter = typename detail::ExtractClass<Signal>::type;
using Target = typename detail::ExtractClass<Slot>::type;
static_assert(std::is_base_of<QObject, Emitter>::value, "Must be derived from QObject");
static_assert(std::is_base_of<QObject, Target>::value, "Must be derived from QObject");
public:
Connection(Emitter *emitter, Signal signal, Target *target, Slot slot):
m_emitter(emitter),
m_signal(signal),
m_target(target),
m_slot(slot)
{
Q_ASSERT(emitter);
Q_ASSERT(signal);
Q_ASSERT(target);
Q_ASSERT(slot);
}
void connect(Qt::ConnectionType connectionType = Qt::AutoConnection) override
{
Q_ASSERT(!m_connected);
m_connected = true;
if (!m_emitter || !m_target)
return;
m_conn = QObject::connect(m_emitter.data(), m_signal, m_target.data(), m_slot, connectionType);
Q_ASSERT(m_conn);
}
void disconnect() override
{
Q_ASSERT(m_connected);
if (m_conn)
QObject::disconnect(m_conn);
m_connected = false;
}
private:
bool m_connected{false};
QPointer<Emitter> m_emitter;
Signal m_signal;
QPointer<Target> m_target;
Slot m_slot;
QMetaObject::Connection m_conn;
};
template<class Signal, class Slot>
Connection<Signal, Slot>* createConnection(typename detail::ExtractClass<Signal>::type *emitter, Signal signal,
typename detail::ExtractClass<Slot>::type *target, Slot slot)
{
return new Connection<Signal, Slot>(emitter, signal, target, slot);
}
}
+30
View File
@@ -0,0 +1,30 @@
#pragma once
#include <ostream>
enum class DataModification
{
eAdded,
eModified,
eRemoved
};
inline std::ostream &operator<<(std::ostream &str, DataModification mod)
{
switch(mod)
{
case DataModification::eAdded:
str << "DataModification::eAdded";
break;
case DataModification::eModified:
str << "DataModification::eModified";
break;
case DataModification::eRemoved:
str << "DataModification::eRemoved";
break;
}
return str;
}
+98
View File
@@ -0,0 +1,98 @@
#pragma once
#ifdef SUPPORT_QBITARRAY
# include <QtCore/QBitArray>
#endif
namespace LtsUtils
{
namespace BitArray
{
constexpr inline int bitNumber(int position)
{
return 7 - (position % 8);
}
template<typename T>
inline bool testBit(const T &bitField, int position, bool *oob = nullptr)
{
const size_t byteNum = position / 8;
if (byteNum >= bitField.size())
{
if (oob)
*oob = true;
return false;
}
if (oob)
*oob = false;
const typename T::value_type mask = 1 << bitNumber(position);
return ((bitField.at(byteNum) & mask) == mask);
}
template<typename T>
inline bool setBit(T &bitField, int position, bool set = true)
{
const size_t byteNum = position / 8;
if (byteNum >= bitField.size())
return false;
const typename T::value_type mask = 1 << bitNumber(position);
if (set)
bitField[byteNum] |= mask;
else
bitField[byteNum] &= ~mask;
return true;
}
template<typename T>
inline bool clearBit(T &bitField, int position)
{
return setBit(bitField, position, false);
}
#ifdef SUPPORT_QBITARRAY
template<typename T>
inline T convert(const QBitArray &bitArray)
{
T ret;
ret.resize((bitArray.size() + 7) / 8, 0);
for (int i = 0; i < bitArray.size(); ++i)
{
const size_t byteNum = i / 8;
const typename T::value_type mask = (1 << bitNumber(i));
if (bitArray[i])
ret[byteNum] |= mask;
else
ret[byteNum] &= ~mask;
}
return ret;
}
template<typename T>
inline QBitArray convert(T &bitField, int realSize)
{
QBitArray ba(realSize);
for (int32_t i = 0; i < realSize; ++i)
{
const size_t byteNum = i / 8;
const typename T::value_type mask = (1 << bitNumber(i));
bool bit = ((bitField[byteNum] & mask) == mask);
ba[i] = bit;
}
return ba;
}
#endif
}
}
+43
View File
@@ -0,0 +1,43 @@
#pragma once
#include <QByteArray>
#include <QString>
namespace LtsUtils
{
template <typename T, typename S>
inline void convert(const S &in, T &out)
{
static_assert(!std::is_same<S, T>::value, "Try to convert a type to the same type - is useless");
out.reserve(static_cast<int>(in.size()));
std::copy(in.begin(), in.end(), std::back_inserter(out));
}
template <typename T, typename S>
inline T convert(const S &in)
{
static_assert(!std::is_same<S, T>::value, "Try to convert a type to the same type - is useless");
T out;
convert(in, out);
return out;
}
template <typename T>
inline QByteArray toQByteArray(const T &in)
{
return convert<QByteArray>(in);
}
template <typename T, typename V = typename T::value_type>
bool isInVector(const T &vec, const V &valueToSearch)
{
const auto end = vec.end();
return std::find(vec.begin(), end, valueToSearch) != end;
}
}
+24
View File
@@ -0,0 +1,24 @@
#pragma once
#include <LtsUtilsCore/ltsutilscore_export.h>
#include <cstdint>
#include <vector>
class QByteArray;
class QPixmap;
class QImage;
namespace LtsUtils
{
LTSUTILSCORE_EXPORT QPixmap getPixmap(const std::vector<uint8_t> &data);
LTSUTILSCORE_EXPORT QPixmap getPixmap(const QByteArray &data);
LTSUTILSCORE_EXPORT QImage getImage(const std::vector<uint8_t> &data);
LTSUTILSCORE_EXPORT QImage getImage(const QByteArray &data);
LTSUTILSCORE_EXPORT std::vector<uint8_t> fromPixmap(const QPixmap &pixmap, bool *bIsPng = nullptr);
LTSUTILSCORE_EXPORT std::vector<uint8_t> fromImage(const QImage &image, bool *bIsPng = nullptr);
}
+1
View File
@@ -0,0 +1 @@
#include <LtsUtilsCore/json_object.h>
+696
View File
@@ -0,0 +1,696 @@
#pragma once
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonParseError>
#include <QJsonValue>
#include <QVector>
#include <QMap>
#include <QString>
#include <string>
#include <vector>
#include <map>
#include <exception>
#include <cstdint>
#include <limits>
namespace LtsUtils
{
class JsonParseError : public std::runtime_error
{
public:
JsonParseError(const QJsonParseError &err)
: std::runtime_error("json parse error: " + err.errorString().toStdString() + " - at offset " + std::to_string(err.offset)){}
};
class JsonError : public std::runtime_error
{
public:
using std::runtime_error::runtime_error;
};
class JsonKeyError : public JsonError
{
public:
using JsonError::JsonError;
};
class JsonRangeError : public JsonError
{
public:
using JsonError::JsonError;
};
class JsonTypeError : public JsonError
{
public:
using JsonError::JsonError;
};
class JsonObject
{
public:
class Key;
JsonObject() = default;
explicit JsonObject(const QJsonObject &json)
: m_json(json)
, m_jsonIsSet(true)
{}
explicit JsonObject(QJsonObject &&json)
: m_json(std::move(json))
, m_jsonIsSet(true)
{}
static inline JsonObject fromJson(const char *json, int len = -1);
static inline JsonObject fromJson(const QByteArray &json) { return fromJson(json.data(), json.size()); }
static inline JsonObject fromJson(const std::string &json) { return fromJson(json.c_str(), json.size()); }
static inline JsonObject fromJsonSafe(const char *json, int len = -1) noexcept(false);
static inline JsonObject fromJsonSafe(const QByteArray &json) noexcept(false) { return fromJsonSafe(json.data(), json.size()); }
static inline JsonObject fromJsonSafe(const std::string &json) noexcept(false) { return fromJsonSafe(json.c_str(), json.size()); }
template<class T>
bool contains(const Key &key) const;
bool isNull(const Key &key) const { return contains<void>(key); }
bool isEmpty() const { return m_json.isEmpty(); }
bool isValid() const { return m_jsonIsSet; }
template<class T>
T value(const Key &key) const noexcept(false);
template<class T>
T valueOr(const Key &key, const T &defaultValue) const noexcept(false);
template<class T>
bool isMap() const;
template<class T>
QMap<QString, T> toMap() const noexcept(false);
template<class T>
std::map<std::string, T> toStdMap() const;
bool operator==(const JsonObject &other) const { return m_json == other.m_json; }
bool operator!=(const JsonObject &other) const { return !(*this == other); }
class Key
{
public:
Key(const QString &s)
: m_s(s)
{}
Key(const std::string &s)
: m_s(QString::fromStdString(s))
{}
Key(const char *s)
: m_s(QString::fromUtf8(s))
{}
operator const QString &() const { return m_s; }
private:
const QString m_s;
};
operator const QJsonObject &() const { return m_json; }
const QJsonObject &object() const { return m_json; }
private:
bool containsAny(const QString &key) const { return m_json.contains(key); }
QJsonObject m_json;
bool m_jsonIsSet = false;
};
JsonObject JsonObject::fromJson(const char *json, int len)
{
if (len < 0)
len = strlen(json);
QJsonParseError error;
const auto doc = QJsonDocument::fromJson(QByteArray::fromRawData(json, len), &error);
if (error.error != QJsonParseError::NoError)
return JsonObject();
if (!doc.isObject())
return JsonObject();
return JsonObject(doc.object());
}
JsonObject JsonObject::fromJsonSafe(const char *json, int len) noexcept(false)
{
if (len < 0)
len = strlen(json);
QJsonParseError error;
const auto doc = QJsonDocument::fromJson(QByteArray::fromRawData(json, len), &error);
if (error.error != QJsonParseError::NoError)
throw JsonParseError(error);
if (!doc.isObject())
throw JsonTypeError("JSON root is not an object");
return JsonObject(doc.object());
}
class JsonArray
{
public:
JsonArray() = default;
explicit JsonArray(const QJsonArray &json)
: m_json(json)
, m_jsonIsSet(true)
{}
explicit JsonArray(QJsonArray &&json)
: m_json(std::move(json))
, m_jsonIsSet(true)
{}
static inline JsonArray fromJson(const char *json, int len = -1);
static inline JsonArray fromJson(const QByteArray &json) { return fromJson(json.data(), json.size()); }
static inline JsonArray fromJson(const std::string &json) { return fromJson(json.c_str(), json.size()); }
static inline JsonArray fromJsonSafe(const char *json, int len = -1) noexcept(false);
static inline JsonArray fromJsonSafe(const QByteArray &json) noexcept(false) { return fromJson(json.data(), json.size()); }
static inline JsonArray fromJsonSafe(const std::string &json) noexcept(false) { return fromJson(json.c_str(), json.size()); }
int size() const { return m_json.size(); }
bool isEmpty() const { return m_json.isEmpty(); }
bool isValid() const { return m_jsonIsSet; }
template<class T>
bool contains(int index) const noexcept(false);
bool isNull(int index) const noexcept(false) { return contains<void>(index); }
template<class T>
T at(int index) const noexcept(false);
template<class T>
bool isVector() const;
template<class T>
QVector<T> toVector() const noexcept(false);
template<class T>
std::vector<T> toStdVector() const;
bool operator==(const JsonArray &other) const { return m_json == other.m_json; }
bool operator!=(const JsonArray &other) const { return !(*this == other); }
const QJsonArray &operator()() const { return m_json; }
private:
QJsonArray m_json;
bool m_jsonIsSet = false;
};
JsonArray JsonArray::fromJson(const char *json, int len)
{
if (len < 0)
len = strlen(json);
QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(QByteArray::fromRawData(json, len), &error);
if (error.error != QJsonParseError::NoError)
return JsonArray();
if (!doc.isArray())
return JsonArray();
return JsonArray(doc.array());
}
JsonArray JsonArray::fromJsonSafe(const char *json, int len) noexcept(false)
{
if (len < 0)
len = strlen(json);
QJsonParseError error;
const auto doc = QJsonDocument::fromJson(QByteArray::fromRawData(json, len), &error);
if (error.error != QJsonParseError::NoError)
throw JsonParseError(error);
if (!doc.isArray())
throw JsonTypeError("JSON root is not an array");
return JsonArray(doc.array());
}
template<class T>
struct JsonValue;
template<class Int>
struct JsonLimits
{
static constexpr Int lowest() { return std::numeric_limits<Int>::lowest(); }
static constexpr Int max() { return std::numeric_limits<Int>::max(); }
};
template<>
struct JsonLimits<int64_t>
{
static constexpr int64_t lowest() { return -(static_cast<int64_t>(1) << 53) + 1; }
static constexpr int64_t max() { return (static_cast<int64_t>(1) << 53) - 1; }
};
template<>
struct JsonLimits<uint64_t>
{
static constexpr uint64_t lowest() { return 0; }
static constexpr uint64_t max() { return JsonLimits<int64_t>::max(); }
};
template<class Int>
struct JsonIntValue
{
static bool matchesType(const QJsonValue &value)
{
if (!value.isDouble())
return false;
double val = value.toDouble();
if (val < JsonLimits<Int>::lowest())
return false;
if (val > JsonLimits<Int>::max())
return false;
double wholeInt = static_cast<Int>(val);
return val == wholeInt;
}
static Int value(const QJsonValue &value) noexcept(false)
{
if (!matchesType(value))
throw JsonTypeError("JSON value not of type Int");
return static_cast<Int>(value.toDouble());
}
};
template<>
struct JsonValue<int16_t> : JsonIntValue<int16_t>
{};
template<>
struct JsonValue<uint16_t> : JsonIntValue<uint16_t>
{};
template<>
struct JsonValue<int32_t> : JsonIntValue<int32_t>
{};
template<>
struct JsonValue<uint32_t> : JsonIntValue<uint32_t>
{};
template<>
struct JsonValue<int64_t> : JsonIntValue<int64_t>
{};
template<>
struct JsonValue<uint64_t> : JsonIntValue<uint64_t>
{};
template<>
struct JsonValue<double>
{
static bool matchesType(const QJsonValue &value) { return value.isDouble(); }
static double value(const QJsonValue &value) noexcept(false)
{
if (!matchesType(value))
throw JsonTypeError("JSON value not of type Double");
return value.toDouble();
}
};
template<>
struct JsonValue<bool>
{
static bool matchesType(const QJsonValue &value) { return value.isBool(); }
static bool value(const QJsonValue &value) noexcept(false)
{
if (!matchesType(value))
throw JsonTypeError("JSON value not of type Bool");
return value.toBool();
}
};
template<>
struct JsonValue<QString>
{
static bool matchesType(const QJsonValue &value) { return value.isString(); }
static QString value(const QJsonValue &value) noexcept(false)
{
if (!matchesType(value))
throw JsonTypeError("JSON value not of type String");
return value.toString();
}
};
template<>
struct JsonValue<std::string>
{
static bool matchesType(const QJsonValue &value) { return value.isString(); }
static std::string value(const QJsonValue &value)
{
return JsonValue<QString>::value(value).toStdString();
}
};
template<>
struct JsonValue<QJsonObject>
{
static bool matchesType(const QJsonValue &value) { return value.isObject(); }
static QJsonObject value(const QJsonValue &value) noexcept(false)
{
if (!matchesType(value))
throw JsonTypeError("JSON value not of type Object");
return value.toObject();
}
};
template<>
struct JsonValue<JsonObject>
{
static bool matchesType(const QJsonValue &value) { return value.isObject(); }
static JsonObject value(const QJsonValue &value) { return JsonObject(JsonValue<QJsonObject>::value(value)); }
};
template<>
struct JsonValue<void>
{
static bool matchesType(const QJsonValue &value) { return value.isNull(); }
};
template<>
struct JsonValue<QJsonArray>
{
static bool matchesType(const QJsonValue &value) { return value.isArray(); }
static QJsonArray value(const QJsonValue &value) noexcept(false)
{
if (!matchesType(value))
throw JsonTypeError("JSON value not of type Array");
return value.toArray();
}
};
template<>
struct JsonValue<JsonArray>
{
static bool matchesType(const QJsonValue &value) { return value.isArray(); }
static JsonArray value(const QJsonValue &value) { return JsonArray(JsonValue<QJsonArray>::value(value)); }
};
template<class T>
struct JsonValue<QVector<T>>
{
static bool matchesType(const QJsonValue &value)
{
if (!value.isArray())
return false;
const JsonArray array(value.toArray());
return array.isVector<T>();
}
static QVector<T> value(const QJsonValue &value)
{
const JsonArray array(JsonValue<QJsonArray>::value(value));
return array.toVector<T>();
}
};
template<class T>
struct JsonValue<std::vector<T>>
{
static bool matchesType(const QJsonValue &value)
{
return JsonValue<QVector<T>>::matchesType(value);
}
static std::vector<T> value(const QJsonValue &value)
{
const JsonArray array(JsonValue<QJsonArray>::value(value));
return array.toStdVector<T>();
}
};
template<class T>
struct JsonValue<QMap<QString, T>>
{
static bool matchesType(const QJsonValue &value)
{
if (!value.isObject())
return false;
const JsonObject obj(JsonValue<QJsonObject>::value(value));
return obj.isMap<T>();
}
static QMap<QString, T> value(const QJsonValue &value)
{
const JsonObject obj(JsonValue<QJsonObject>::value(value));
return obj.toMap<T>();
}
};
template<class T>
struct JsonValue<std::map<std::string, T>>
{
static bool matchesType(const QJsonValue &value)
{
return JsonValue<QMap<QString, T>>::matchesType(value);
}
static std::map<std::string, T> value(const QJsonValue &value)
{
const JsonObject obj(JsonValue<QJsonObject>::value(value));
return obj.toStdMap<T>();
}
};
template<class T>
bool JsonObject::contains(const Key &key) const
{
if (!m_json.contains(key))
return false;
return JsonValue<T>::matchesType(m_json.value(key));
}
template<class T>
T JsonObject::value(const Key &key) const noexcept(false)
{
if (!containsAny(key))
throw JsonKeyError("no element with key: " + static_cast<const QString &>(key).toStdString());
try
{
return JsonValue<T>::value(m_json.value(key));
}
catch(const JsonTypeError &typeError)
{
throw JsonTypeError(std::string(typeError.what()) + " - key: " + static_cast<const QString &>(key).toStdString());
}
}
template<class T>
T JsonObject::valueOr(const Key &key, const T &defaultValue) const
{
try
{
return value<T>(key);
}
catch (const JsonKeyError &)
{
return defaultValue;
}
}
template<class T>
bool JsonObject::isMap() const
{
const QStringList keys = m_json.keys();
for (const auto &key : keys)
if (!JsonValue<T>::matchesType(m_json.value(key)))
return false;
return true;
}
template<class T>
QMap<QString, T> JsonObject::toMap() const
{
QMap<QString, T> result;
for (auto current = m_json.begin(); current != m_json.end(); ++current)
result.insert(current.key(), JsonValue<T>::value(current.value()));
return result;
}
template<class T>
std::map<std::string, T> JsonObject::toStdMap() const
{
std::map<std::string, T> result;
for (auto current = m_json.begin(); current != m_json.end(); ++current)
result.insert({current.key().toStdString(), JsonValue<T>::value(current.value())});
return result;
}
template<class T>
bool JsonArray::contains(int index) const noexcept(false)
{
if (index < 0 || index >= m_json.size())
throw JsonRangeError("index out of range: " + std::to_string(index));
return JsonValue<T>::matchesType(m_json.at(index));
}
template<class T>
T JsonArray::at(int index) const noexcept(false)
{
if (index < 0 || index >= m_json.size())
throw JsonRangeError("index out of range: " + std::to_string(index));
return JsonValue<T>::value(m_json.at(index));
}
template<class T>
bool JsonArray::isVector() const
{
for (const QJsonValue &value : m_json)
if (!JsonValue<T>::matchesType(value))
return false;
return true;
}
template<class T>
QVector<T> JsonArray::toVector() const
{
QVector<T> result;
result.reserve(m_json.size());
for (const QJsonValue &value : m_json)
result.push_back(JsonValue<T>::value(value));
return result;
}
template<class T>
std::vector<T> JsonArray::toStdVector() const
{
std::vector<T> result;
result.reserve(m_json.size());
for (const QJsonValue &value : m_json)
result.push_back(JsonValue<T>::value(value));
return result;
}
}
+14
View File
@@ -0,0 +1,14 @@
#include "lts_portrange.h"
namespace LtsUtils
{
LtsUtils::LtsPortRange fromQPoint(const QPoint &point)
{
if (point.x() < 1025 || point.y() > 65535 || point.x() > point.y())
return {};
return {static_cast<quint16>(point.x()), static_cast<quint16>(point.y())};
}
}
+15
View File
@@ -0,0 +1,15 @@
#pragma once
#include <LtsUtilsCore/ltsutilscore_export.h>
#include <QPair>
#include <QPoint>
namespace LtsUtils
{
typedef QPair<quint16, quint16> LtsPortRange;
LTSUTILSCORE_EXPORT LtsPortRange fromQPoint(const QPoint &point);
}
@@ -0,0 +1,25 @@
#include "lts_translatable_identifier.h"
#include <QCoreApplication>
namespace LtsUtils
{
LtsTranslatableIdentifier::LtsTranslatableIdentifier(const QString &identifier, const QObject *context,
const char *translatableText)
: m_identifier(identifier)
, m_translationContext(context->metaObject()->className())
, m_translatableText(translatableText)
{}
const QString LtsTranslatableIdentifier::translatedText(const char *disambiguation, int n) const
{
if (m_identifier.isEmpty() || m_translationContext == nullptr || m_translatableText == nullptr)
return {};
return QCoreApplication::translate(m_translationContext, m_translatableText, disambiguation, n);
}
}
@@ -0,0 +1,33 @@
#pragma once
#include <LtsUtilsCore/ltsutilscore_export.h>
#include <QObject>
#include <QString>
namespace LtsUtils
{
class LTSUTILSCORE_EXPORT LtsTranslatableIdentifier
{
public:
LtsTranslatableIdentifier()
: m_translationContext(nullptr)
, m_translatableText("")
{}
LtsTranslatableIdentifier(const QString &identifier, const QObject *context, const char *translatableText);
const QString &identifier() const { return m_identifier; }
const QString translatedText(const char *disambiguation = nullptr, int n = -1) const;
const QString _context() const { return QString::fromUtf8(m_translationContext); }
private:
QString m_identifier;
const char *m_translationContext;
const char *m_translatableText;
};
}
+15
View File
@@ -0,0 +1,15 @@
#pragma once
#include <qglobal.h>
namespace LtsUtils
{
inline bool isPositionTimeOutdated(qint64 curTime, qint64 posTime)
{
return curTime > posTime + 11 * 60 * 1000;
}
}
+169
View File
@@ -0,0 +1,169 @@
#include "pgarray.h"
#include <QVector>
#include <QDebug>
#include <functional>
#include <LtsUtilsCore/ltsutilscore_export.h>
namespace LtsUtils
{
template<typename T>
static inline QString convertToPgString(const std::vector<T> &data)
{
if (data.size() == 0)
return QLatin1String("{}");
QString ret(QLatin1Char('{'));
for (T i : data)
ret += QString::number(i) + QLatin1Char(',');
ret.chop(1);
ret += QLatin1Char('}');
return ret;
}
template<>
LTSUTILSCORE_EXPORT QString IntArray::toPgString() const
{
return convertToPgString(m_data);
}
template<>
LTSUTILSCORE_EXPORT QString BigintArray::toPgString() const
{
return convertToPgString(m_data);
}
template<typename T>
static inline T convertFromPgString(const QString &str, const std::function<typename T::Type(const QStringRef &val, bool *bOk)> &convertFunc)
{
typename T::ContainerType result;
int idxStart = str.indexOf(QLatin1Char('{'));
int idxEnd = str.lastIndexOf(QLatin1Char('}'));
if (idxEnd < idxStart)
return T(result);
if (idxStart < 0 && idxEnd < 0)
{
idxStart = -1;
idxEnd = str.length() + 1;
}
const QStringRef strRef = str.midRef(idxStart + 1, idxEnd - idxStart - 1);
const QVector<QStringRef> vec = strRef.split(QLatin1Char(','), QString::SkipEmptyParts);
result.reserve(vec.size());
for (const QStringRef &s : vec)
{
bool ok = false;
const typename T::Type i = convertFunc(s, &ok);
if (ok)
result.push_back(i);
}
return T(result);
}
template<>
LTSUTILSCORE_EXPORT IntArray IntArray::fromPgString(const QString &str)
{
return convertFromPgString<IntArray>(str,
[](const QStringRef & val, bool * bOk) { return val.toInt(bOk);});
}
template<>
LTSUTILSCORE_EXPORT BigintArray BigintArray::fromPgString(const QString &str)
{
return convertFromPgString<BigintArray>(str,
[](const QStringRef & val, bool * bOk) { return val.toLongLong(bOk);});
}
template<typename T>
static inline QString convertToPgString(const std::map<T, T> &data)
{
if (data.size() == 0)
return QLatin1String("{}");
QString ret(QLatin1Char('{'));
for (const auto &it : data)
{
ret += QLatin1Char('{') + QString::number(it.first) +
QLatin1Char(',') + QString::number(it.second) + QLatin1String("},");
}
ret.chop(1);
ret += QLatin1Char('}');
return ret;
}
template<>
LTSUTILSCORE_EXPORT QString IntArray2D::toPgString() const
{
return convertToPgString<IntArray2D::Type>(m_data);
}
template<>
LTSUTILSCORE_EXPORT QString BigintArray2D::toPgString() const
{
return convertToPgString<BigintArray2D::Type>(m_data);
}
template<typename T>
static inline T convertFromPgString2D(const QString &str, const std::function<typename T::Type(const QStringRef &val)> &convertFunc)
{
typename T::ContainerType ret;
int idxStart = str.indexOf(QLatin1Char('{'));
int idxEnd = str.lastIndexOf(QLatin1Char('}'));
if (idxEnd < idxStart)
return T(ret);
if (idxStart < 0 && idxEnd < 0)
{
idxStart = -1;
idxEnd = str.length() + 1;
}
const QStringRef strRef = str.midRef(idxStart + 1, idxEnd - idxStart - 1);
idxStart = strRef.indexOf(QLatin1Char('{'));
while (idxStart >= 0)
{
idxEnd = strRef.indexOf(QLatin1Char('}'), idxStart);
if (idxEnd < 0)
break;
const QStringRef keyValueStr = strRef.mid(idxStart + 1, idxEnd - idxStart - 1);
const QVector<QStringRef> keyValuePair = keyValueStr.split(QLatin1Char(','), QString::SkipEmptyParts);
if (keyValuePair.size() != 2)
break;
const typename T::Type key = convertFunc(keyValuePair.at(0).trimmed());
const typename T::Type value = convertFunc(keyValuePair.at(1).trimmed());
ret.insert(std::make_pair(key, value));
idxStart = strRef.indexOf(QLatin1Char('{'), idxEnd + 1);
}
return T(ret);
}
template<>
LTSUTILSCORE_EXPORT IntArray2D IntArray2D::fromPgString(const QString &str)
{
return convertFromPgString2D<IntArray2D>(str,
[](const QStringRef & val) { return val.toInt();});
}
template<>
LTSUTILSCORE_EXPORT BigintArray2D BigintArray2D::fromPgString(const QString &str)
{
return convertFromPgString2D<BigintArray2D>(str,
[](const QStringRef & val) { return val.toLongLong();});
}
}
+45
View File
@@ -0,0 +1,45 @@
#pragma once
#include <QString>
#include <map>
#include <vector>
#include <cstdint>
namespace LtsUtils
{
template<typename T, typename C>
class PgArray
{
public:
using Type = T;
using ContainerType = C;
PgArray() = default;
Q_DECL_CONSTEXPR explicit PgArray(const C &data)
: m_data(data)
{}
Q_DECL_CONSTEXPR C operator()()const
{
return m_data;
}
QString toPgString() const;
static PgArray fromPgString(const QString &str);
private:
C m_data;
};
using IntArray = PgArray<int, std::vector<int>>;
using BigintArray = PgArray<int64_t, std::vector<int64_t>>;
using IntArray2D = PgArray<int, std::map<int, int>>;
using BigintArray2D = PgArray<int64_t, std::map<int64_t, int64_t>>;
}
+103
View File
@@ -0,0 +1,103 @@
#include "promise.h"
#include <QTimer>
namespace LtsUtils
{
Promise::Promise(const std::function<void(ResultFunction resolve, ResultFunction reject)> &function, QObject *parent)
: QObject(parent)
, m_functionAlreadySet(false)
, m_timeout(new QTimer(this))
, m_resultSet(false)
, m_timeoutSet(false)
{
m_timeout->setSingleShot(true);
connect(m_timeout, &QTimer::timeout,
this, &Promise::slotTimeout);
setFunction(function);
}
void Promise::setFunction(const std::function<void(ResultFunction resolve, ResultFunction reject)> &function)
{
if (!function || m_functionAlreadySet)
return;
m_functionAlreadySet = true;
if (m_timeoutSet)
m_timeout->start();
QTimer::singleShot(0, this, [this, function]()
{
function([this](const QVariant &value)
{
resolve(value);
}, [this](const QVariant &value)
{
reject(value);
});
});
}
void Promise::setTimeout(int interval)
{
m_timeout->stop();
m_timeout->setInterval(interval);
m_timeoutSet = (interval != 0);
if (interval != 0 && m_functionAlreadySet)
m_timeout->start();
}
void Promise::slotTimeout()
{
reject(QStringLiteral("timeout"));
}
void Promise::resolve(const QVariant &value)
{
if (m_resultSet)
return;
m_resultSet = true;
m_timeout->stop();
m_resolveFn(value);
}
void Promise::reject(const QVariant &value)
{
if (m_resultSet)
return;
m_resultSet = true;
m_timeout->stop();
m_rejectFn(value);
}
Promise &Promise::resolved(ResultFunction resolveFn)
{
m_resolveFn = resolveFn;
return *this;
}
Promise &Promise::rejected(ResultFunction rejectFn)
{
m_rejectFn = rejectFn;
return *this;
}
}
+72
View File
@@ -0,0 +1,72 @@
#pragma once
#include <LtsUtilsCore/ltsutilscore_export.h>
#include <QObject>
#include <QVariant>
#include <functional>
class QTimer;
namespace LtsUtils
{
typedef std::function<void(const QVariant &value)> RawResultFunction;
typedef const RawResultFunction &ResultFunction;
class LTSUTILSCORE_EXPORT Promise : public QObject
{
Q_OBJECT
public:
Promise(const std::function<void(ResultFunction resolve, ResultFunction reject)> &function, QObject *parent = nullptr);
void setFunction(const std::function<void(ResultFunction resolve, ResultFunction reject)> &function);
void resolve(const QVariant &value = QVariant());
void reject(const QVariant &value = QVariant());
void setTimeout(int interval);
Promise &resolved(ResultFunction resolveFn);
Promise &rejected(ResultFunction rejectFn);
private:
RawResultFunction m_resolveFn;
RawResultFunction m_rejectFn;
bool m_functionAlreadySet;
QTimer *m_timeout;
bool m_resultSet;
bool m_timeoutSet;
private slots:
void slotTimeout();
};
}
+165
View File
@@ -0,0 +1,165 @@
#include "promise_examples.h"
#include "promise.h"
#include <QTimer>
#include <QTest>
#include <QDebug>
namespace LtsUtils
{
void PromiseExample1_Class::doSomethingAsync1()
{
QTimer::singleShot(200, this, [this]()
{
emit signalDone1(true);
});
}
void PromiseExample1_Class::doSomethingAsync2()
{
QTimer::singleShot(450, this, [this]()
{
emit signalDone2(true, 1234);
});
}
PromiseExample1::PromiseExample1(QObject *parent)
: QObject(parent)
, m_success(false)
{
auto func = [this](ResultFunction resolve
, ResultFunction reject )
{
PromiseExample1_Class *c = new PromiseExample1_Class(this);
connect(c, &PromiseExample1_Class::signalDone1,
this, [this, c, resolve, reject](bool didThisWork)
{
if (!didThisWork)
{
reject(QStringLiteral("First Action did not succeed"));
return;
}
else
{
connect(c, &PromiseExample1_Class::signalDone2,
this, [resolve, reject](bool didThisWork, int someNumberThatReturns)
{
if (didThisWork)
resolve(someNumberThatReturns);
else
reject(QStringLiteral("Second Action did not succeed"));
});
c->doSomethingAsync2();
}
});
c->doSomethingAsync1();
};
Promise *p = new Promise(func, this);
p->resolved([this](const QVariant &value)
{
qDebug() << "example1 promise succeeded! 'someNumberThatReturns' was" << value;
m_success = true;
}).rejected([](const QVariant &value)
{
qDebug() << "example1 promise failed.." << value;
});
}
PromiseExample2::PromiseExample2(QObject *parent)
: QObject(parent)
, m_success(false)
{
Promise *p = new Promise([](ResultFunction , ResultFunction )
{
}, this);
p->setTimeout(1000);
p->resolved([](const QVariant &)
{
QFAIL("This test case's promise should never resolve");
});
p->rejected([this](const QVariant &val)
{
QVERIFY2(val == QStringLiteral("timeout"), "Promise didn't reject with string \"timeout\"");
qDebug() << "Promise rejected as expected";
m_success = true;
});
}
PromiseExample3::PromiseExample3(QObject *parent)
: QObject(parent)
, m_success(true)
, m_alreadyRejected(false)
{
Promise *p = new Promise([](ResultFunction , ResultFunction reject)
{
reject(QString());
}, this);
p->setTimeout(1000);
p->resolved([](const QVariant &)
{
QFAIL("This test case's promise should never resolve");
});
p->rejected([this](const QVariant &val)
{
qDebug() << "rejected with val" << val;
QVERIFY2(val == QString(), "Promise didn't reject with an expected empty string.");
QVERIFY2(!m_alreadyRejected, "Promise rejected more than once");
m_alreadyRejected = true;
qDebug() << "Promise rejected as expected";
});
}
}
+70
View File
@@ -0,0 +1,70 @@
#pragma once
#include <QObject>
namespace LtsUtils
{
class PromiseExample1_Class : public QObject
{
Q_OBJECT
public:
using QObject::QObject;
void doSomethingAsync1();
void doSomethingAsync2();
signals:
void signalDone1(bool didThisWork);
void signalDone2(bool didThisWork, int someNumberThatReturns);
};
class PromiseExample1 : public QObject
{
Q_OBJECT
public:
explicit PromiseExample1(QObject *parent = nullptr);
bool isSuccess() const { return m_success; }
private:
bool m_success;
};
class PromiseExample2 : public QObject
{
Q_OBJECT
public:
explicit PromiseExample2(QObject *parent = nullptr);
bool isSuccess() const { return m_success; }
private:
bool m_success;
};
class PromiseExample3 : public QObject
{
Q_OBJECT
public:
explicit PromiseExample3(QObject *parent = nullptr);
bool isSuccess() const { return m_success; }
private:
bool m_success;
bool m_alreadyRejected;
};
}
+282
View File
@@ -0,0 +1,282 @@
#pragma once
#include <QtCore/QByteArray>
#include <limits>
namespace LtsUtils
{
template<typename T>
void inline set8Byte(const T in, QByteArray& out)
{
static_assert(std::is_integral<T>::value || std::is_enum<T>::value, "Only integrals allowed for raw byte accessd");
out += (in & 0xFF00000000000000UL) >> 56;
out += (in & 0x00FF000000000000UL) >> 48;
out += (in & 0x0000FF0000000000UL) >> 40;
out += (in & 0x000000FF00000000UL) >> 32;
out += (in & 0x00000000FF000000UL) >> 24;
out += (in & 0x0000000000FF0000UL) >> 16;
out += (in & 0x000000000000FF00UL) >> 8;
out += (in & 0x00000000000000FFUL);
}
template<>
void inline set8Byte(const double in, QByteArray &out)
{
union hack
{
double d;
int64_t i;
} h;
h.d = in;
set8Byte(h.i, out);
}
template<typename T>
bool inline get8Byte(const QByteArray& baData,
size_t &pos,
T& out)
{
static_assert(std::is_integral<T>::value || std::is_enum<T>::value, "Only integrals allowed for raw byte accessd");
static_assert(sizeof(T) >= 8, "sizeof(out) is smaller than 8 bytes - will not fit");
out = T();
if(size_t(baData.size()) < pos + 8)
return false;
const char *data = baData.data() + pos;
if(std::numeric_limits<T>::is_signed)
out |= static_cast<signed long long>(data[0]) << 56;
else
out |= (data[0] & 0xFFULL) << 56;
out |= (data[1] & 0xFFULL) << 48;
out |= (data[2] & 0xFFULL) << 40;
out |= (data[3] & 0xFFULL) << 32;
out |= (data[4] & 0xFFULL) << 24;
out |= (data[5] & 0xFFULL) << 16;
out |= (data[6] & 0xFFULL) << 8;
out |= (data[7] & 0xFFULL);
pos += 8;
return true;
}
template<>
bool inline get8Byte(const QByteArray& baData,
size_t &pos,
double& out)
{
out = 0.;
union hack
{
double d;
int64_t i;
} h;
if (!get8Byte(baData, pos, h.i))
return false;
out = h.d;
return true;
}
template<typename T>
bool inline get8Byte(const QByteArray& data, T& out)
{
size_t pos = 0;
return get8Byte(data, pos, out);
}
template<typename T>
void inline set4Byte(const T in, QByteArray& out)
{
static_assert(std::is_integral<T>::value || std::is_enum<T>::value, "Only integrals allowed for raw byte accessd");
out += (in & 0xFF000000) >> 24;
out += (in & 0x00FF0000) >> 16;
out += (in & 0x0000FF00) >> 8;
out += (in & 0x000000FF);
}
template<>
void inline set4Byte(const double in, QByteArray& out)
{
int tmp = qRound(in);
return set4Byte(tmp, out);
}
template<typename T>
bool inline get4Byte(const QByteArray& baData,
size_t &pos,
T& out)
{
static_assert(std::is_integral<T>::value || std::is_enum<T>::value, "Only integrals allowed for raw byte accessd");
static_assert(sizeof(T) >= 4, "sizeof(out) is smaller than 4 bytes - will not fit");
out = T();
if(size_t(baData.size()) < pos + 4)
return false;
const char *data = baData.data() + pos;
if(std::numeric_limits<T>::is_signed)
out |= data[0] << 24;
else
out |= (data[0] & 0xFFU) << 24;
out |= (data[1] & 0xFFU) << 16;
out |= (data[2] & 0xFFU) << 8;
out |= (data[3] & 0xFFU);
pos += 4;
return true;
}
template<>
bool inline get4Byte(const QByteArray& baData,
size_t &pos,
double& out)
{
out = 0.;
int tmp;
if(!get4Byte(baData, pos, tmp))
return false;
out = tmp;
return true;
}
template<typename T>
bool inline get4Byte(const QByteArray& data, T& out)
{
size_t pos = 0;
return get4Byte(data, pos, out);
}
template<typename T>
void inline set3Byte(const T in, QByteArray& out)
{
static_assert(std::is_integral<T>::value || std::is_enum<T>::value, "Only integrals allowed for raw byte accessd");
out += (in & 0x00FF0000) >> 16;
out += (in & 0x0000FF00) >> 8;
out += (in & 0x000000FF);
}
template<typename T>
bool inline get3Byte(const QByteArray& baData,
size_t &pos,
T& out)
{
static_assert(std::is_integral<T>::value || std::is_enum<T>::value, "Only integrals allowed for raw byte accessd");
static_assert(sizeof(T) >= 3, "sizeof(out) is smaller than 3 bytes - will not fit");
out = T();
if(size_t(baData.size()) < pos + 3)
return false;
const char *data = baData.data() + pos;
if(std::numeric_limits<T>::is_signed)
out |= data[0] << 16;
else
out |= (data[0] & 0xFFU) << 16;
out |= (data[1] & 0xFFU) << 8;
out |= (data[2] & 0xFFU);
pos += 3;
return true;
}
template<typename T>
bool inline get3Byte(const QByteArray& data, T& out)
{
size_t pos = 0;
return get3Byte(data, pos, out);
}
template<typename T>
void inline set2Byte(const T in, QByteArray& out)
{
static_assert(std::is_integral<T>::value || std::is_enum<T>::value, "Only integrals allowed for raw byte accessd");
out += (in & 0x0000FF00) >> 8;
out += (in & 0x000000FF);
}
template<typename T>
bool inline get2Byte(const QByteArray& baData,
size_t &pos,
T& out)
{
static_assert(std::is_integral<T>::value || std::is_enum<T>::value, "Only integrals allowed for raw byte accessd");
static_assert(sizeof(T) >= 2, "sizeof(out) is smaller than 2 bytes - will not fit");
out = T();
if(size_t(baData.size()) < pos + 2)
return false;
const char *data = baData.data() + pos;
if(std::numeric_limits<T>::is_signed)
out |= data[0] << 8;
else
out |= (data[0] & 0xFFU) << 8;
out |= data[1] & 0xFFU;
pos += 2;
return true;
}
template<typename T>
bool inline get2Byte(const QByteArray& data, T& out)
{
size_t pos = 0;
return get2Byte(data, pos, out);
}
template<typename T>
void inline set1Byte(const T in, QByteArray& out)
{
static_assert(std::is_integral<T>::value || std::is_enum<T>::value, "Only integrals allowed for raw byte accessd");
unsigned char c = in;
out += c;
}
template<typename T>
bool inline get1Byte(const QByteArray& baData,
size_t &pos,
T& out)
{
static_assert(std::is_integral<T>::value || std::is_enum<T>::value, "Only integrals allowed for raw byte accessd");
out = T();
if(size_t(baData.size()) < pos + 1)
return false;
const char *data = baData.data() + pos;
if(std::numeric_limits<T>::is_signed)
out = (T)(data[0]);
else
out = (T)(data[0] & 0xFF);
pos += 1;
return true;
}
template<typename T>
bool inline get1Byte(const QByteArray& data, T& out)
{
size_t pos = 0;
return get1Byte(data, pos, out);
}
}
+88
View File
@@ -0,0 +1,88 @@
#include "qplane3d.h"
#include <cmath>
namespace LtsUtils
{
QPlane3D::QPlane3D(const QPoint3D &pos, const QPoint3D &vec1, const QPoint3D &vec2)
: m_pos(pos)
, m_vec1(vec1)
, m_vec2(vec2)
{
m_normal = QPoint3D::crossProduct(m_vec1, m_vec2);
m_planeC = QPoint3D::dotProduct(m_pos, m_normal);
}
QPoint3D QPlane3D::intersection(const QPoint3D &point, const QPoint3D &direction) const
{
const double dotProduct = QPoint3D::dotProduct(direction, m_normal);
if (qFuzzyIsNull(dotProduct))
return inPlane(point) ? point : QPoint3D();
const double distance = distanceTo(point) / std::abs(dotProduct);
return point + distance * direction;
}
bool QPlane3D::intersects(const QPoint3D &direction) const
{
return !isParallel(direction);
}
bool QPlane3D::isParallel(const QPoint3D &direction) const
{
return qFuzzyIsNull(QPoint3D::dotProduct(m_normal, direction));
}
bool QPlane3D::inPlane(const QPoint3D &point) const
{
if (point == m_pos)
return true;
return qFuzzyIsNull(QPoint3D::dotProduct(m_normal, point - m_pos));
}
double QPlane3D::distanceTo(const QPoint3D &point) const
{
return QPoint3D::dotProduct(point - m_pos, m_normal);
}
QPolygon3D::QPolygon3D(const QVector<QPoint3D> &vertices)
: QPlane3D(vertices[0], vertices[1], vertices[2])
, m_vertices(vertices)
{
}
bool QPolygon3D::containsPoint(const QPoint3D &point) const
{
if (!inPlane(point))
return false;
if (contains(point))
return true;
double angleSum = 0.;
double cosTheta = 0.;
const int numberOfVertices = m_vertices.size();
for (int i = 0; i < m_vertices.size(); ++i)
{
const QPoint3D &first = m_vertices[i % numberOfVertices] - point;
const QPoint3D &second = m_vertices[(i + 1) % numberOfVertices] - point;
cosTheta = QPoint3D::dotProduct(first, second) / (first.length() * second.length());
angleSum += acos(cosTheta);
}
return qFuzzyIsNull(M_2_PI - angleSum);
}
}
+59
View File
@@ -0,0 +1,59 @@
#pragma once
#include "qpoint3d.h"
#include <LtsUtilsCore/ltsutilscore_export.h>
#include <QVector>
#include <QPointF>
namespace LtsUtils
{
class LTSUTILSCORE_EXPORT QPlane3D
{
public:
QPlane3D(const QPoint3D &pos, const QPoint3D &vec1, const QPoint3D &vec2);
QPoint3D intersection(const QPoint3D &point, const QPoint3D &direction) const;
bool intersects(const QPoint3D &direction) const;
bool isParallel(const QPoint3D &direction) const;
bool inPlane(const QPoint3D &point) const;
double distanceTo(const QPoint3D &point) const;
const QPoint3D &pos() const { return m_pos; }
const QPoint3D &vec1() const { return m_vec1; }
const QPoint3D &vec2() const { return m_vec2; }
const QPoint3D &normal() const { return m_normal; }
double planeC() const { return m_planeC; }
protected:
QPoint3D m_pos;
QPoint3D m_vec1;
QPoint3D m_vec2;
QPoint3D m_normal;
double m_planeC;
};
class LTSUTILSCORE_EXPORT QPolygon3D : public QPlane3D
{
public:
QPolygon3D(const QVector<QPoint3D> &vertices);
bool contains(const QPoint3D &point) const { return m_vertices.contains(point); }
bool containsPoint(const QPoint3D &point) const;
private:
QVector<QPoint3D> m_vertices;
};
}
+48
View File
@@ -0,0 +1,48 @@
#include "qpoint3d.h"
#include <QDataStream>
using namespace LtsUtils;
double QPoint3D::distanceToLine(const QPoint3D &point, const QPoint3D &direction) const
{
if (direction.isNull())
return (*this - point).length();
QPoint3D p = point + dotProduct(*this - point, direction) * direction;
return (*this - p).length();
}
double QPoint3D::distanceToPlane(const QPoint3D &plane, const QPoint3D &normal) const
{
return dotProduct(*this - plane, normal);
}
double QPoint3D::distanceToPlane(const QPoint3D &plane1, const QPoint3D &plane2, const QPoint3D &plane3) const
{
QPoint3D n = normal(plane2 - plane1, plane3 - plane1);
return dotProduct(*this - plane1, n);
}
double QPoint3D::distanceToPoint(const QPoint3D &point) const
{
return (*this - point).length();
}
QDataStream &operator<<(QDataStream &s, const QPoint3D &p)
{
s << p.x() << p.y() << p.z();
return s;
}
QDataStream &operator>>(QDataStream &s, QPoint3D &p)
{
double x, y, z;
s >> x; p.rx() = x;
s >> y; p.ry() = y;
s >> z; p.rz() = z;
return s;
}
+296
View File
@@ -0,0 +1,296 @@
#pragma once
#include <sstream>
#include <cmath>
#include <LtsUtilsCore/ltsutilscore_export.h>
#include <QtCore/qglobal.h>
#include <QtCore/qpoint.h>
namespace LtsUtils
{
class QPoint3D
{
public:
enum class Axis { X, Y, Z };
Q_DECL_CONSTEXPR QPoint3D() = default;
Q_DECL_CONSTEXPR QPoint3D(double xpos, double ypos, double zpos);
template<typename T>
explicit QPoint3D(const T &data)
: xp(data.offsetX())
, yp(data.offsetY())
, zp(data.offsetZ())
{}
inline bool isNull() const;
Q_DECL_CONSTEXPR inline double x() const;
Q_DECL_CONSTEXPR inline double y() const;
Q_DECL_CONSTEXPR inline double z() const;
Q_DECL_RELAXED_CONSTEXPR inline void setX(double xpos);
Q_DECL_RELAXED_CONSTEXPR inline void setY(double ypos);
Q_DECL_RELAXED_CONSTEXPR inline void setZ(double zpos);
Q_DECL_RELAXED_CONSTEXPR inline double &rx();
Q_DECL_RELAXED_CONSTEXPR inline double &ry();
Q_DECL_RELAXED_CONSTEXPR inline double &rz();
Q_DECL_CONSTEXPR inline QPointF toPointF() const;
static QPoint3D fromQPointF(const QPointF &p)
{
return QPoint3D(p.x(), p.y(), .0);
}
inline double lengthSquared() const { return (xp * xp) + (yp * yp) + (zp * zp); }
inline double length() const { return std::sqrt(lengthSquared()); }
inline void normalize()
{
double len = xp * xp + yp * yp + zp * zp;
if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len))
return;
len = std::sqrt(len);
xp /= len;
yp /= len;
zp /= len;
}
inline QPoint3D normalized() const
{
double len = xp * xp + yp * yp + zp * zp;
if (qFuzzyIsNull(len - 1.0f))
return *this;
else if (!qFuzzyIsNull(len))
return *this / std::sqrt(len);
else
return QPoint3D(*this);
}
inline void rotate(const double &phi, const Axis &axis)
{
const double sin = std::sin(phi);
const double cos = std::cos(phi);
switch (axis)
{
case Axis::X:
{
const double _yp = (cos * yp) - (sin * zp);
const double _zp = (sin * yp) + (cos * zp);
yp = _yp;
zp = _zp;
break;
}
case Axis::Y:
{
const double _xp = (cos * xp) + (sin * zp);
const double _zp = (-sin * xp) + (cos * zp);
xp = _xp;
zp = _zp;
break;
}
case Axis::Z:
{
const double _xp = (cos * xp) - (sin * yp);
const double _yp = (sin * xp) + (cos * yp);
xp = _xp;
yp = _yp;
break;
}
}
}
inline QPoint3D rotated(const double &phi, const Axis &axis) const
{
QPoint3D p(*this);
p.rotate(phi, axis);
return p;
}
inline double distanceToLine(const QPoint3D &point, const QPoint3D &direction) const;
inline double distanceToPlane(const QPoint3D &plane, const QPoint3D &normal) const;
inline double distanceToPlane(const QPoint3D &plane1, const QPoint3D &plane2, const QPoint3D &plane3) const;
inline double distanceToPoint(const QPoint3D &point) const;
friend Q_DECL_CONSTEXPR inline bool operator==(const QPoint3D &p1, const QPoint3D &p2);
friend Q_DECL_CONSTEXPR inline bool operator!=(const QPoint3D &p1, const QPoint3D &p2);
friend Q_DECL_CONSTEXPR inline QPoint3D operator +(const QPoint3D &p1, const QPoint3D &p2)
{
return QPoint3D(p1.xp + p2.xp, p1.yp + p2.yp, p1.zp + p2.zp);
}
friend Q_DECL_CONSTEXPR inline QPoint3D operator -(const QPoint3D &p1, const QPoint3D &p2)
{
return QPoint3D(p1.xp - p2.xp, p1.yp - p2.yp, p1.zp - p2.zp);
}
friend Q_DECL_CONSTEXPR inline QPoint3D operator *(const QPoint3D &p1, double factor)
{
return QPoint3D(p1.xp * factor, p1.yp * factor, p1.zp * factor);
}
friend Q_DECL_CONSTEXPR inline QPoint3D operator *(double factor, const QPoint3D &p1)
{
return QPoint3D(p1.xp * factor, p1.yp * factor, p1.zp * factor);
}
friend Q_DECL_CONSTEXPR inline QPoint3D operator /(const QPoint3D &p1, double factor)
{
return QPoint3D(p1.xp / factor, p1.yp / factor, p1.zp / factor);
}
Q_DECL_RELAXED_CONSTEXPR inline QPoint3D &operator +=(const QPoint3D &o)
{
xp += o.xp;
yp += o.yp;
zp += o.zp;
return *this;
}
Q_DECL_RELAXED_CONSTEXPR inline QPoint3D &operator -=(const QPoint3D &o)
{
xp -= o.xp;
yp -= o.yp;
zp -= o.zp;
return *this;
}
Q_DECL_RELAXED_CONSTEXPR inline QPoint3D &operator *=(double factor)
{
xp *= factor;
yp *= factor;
zp *= factor;
return *this;
}
Q_DECL_RELAXED_CONSTEXPR inline QPoint3D &operator /=(double divisor)
{
xp /= divisor;
yp /= divisor;
zp /= divisor;
return *this;
}
Q_DECL_CONSTEXPR static inline double dotProduct(const QPoint3D& v1, const QPoint3D& v2)
{
return v1.xp * v2.xp + v1.yp * v2.yp + v1.zp * v2.zp;
}
Q_DECL_CONSTEXPR static inline QPoint3D crossProduct(const QPoint3D& v1, const QPoint3D& v2)
{
return QPoint3D(v1.yp * v2.zp - v1.zp * v2.yp,
v1.zp * v2.xp - v1.xp * v2.zp,
v1.xp * v2.yp - v1.yp * v2.xp);
}
static inline QPoint3D normal(const QPoint3D &v1, const QPoint3D &v2)
{
return crossProduct(v1, v2).normalized();
}
static inline QPoint3D normal(const QPoint3D &v1, const QPoint3D &v2, const QPoint3D &v3)
{
return crossProduct((v2 - v1), (v3 - v1)).normalized();
}
Q_DECL_CONSTEXPR friend inline bool qFuzzyCompare(const QPoint3D& v1, const QPoint3D& v2);
private:
double xp = 0;
double yp = 0;
double zp = 0;
};
LTSUTILSCORE_EXPORT QDataStream &operator<<(QDataStream &s, const QPoint3D &p);
LTSUTILSCORE_EXPORT QDataStream &operator>>(QDataStream &s, QPoint3D &p);
Q_DECL_CONSTEXPR inline QPoint3D::QPoint3D(double xpos, double ypos, double zpos) : xp(xpos), yp(ypos), zp(zpos) { }
inline bool QPoint3D::isNull() const
{
return qIsNull(xp) && qIsNull(yp) && qIsNull(zp);
}
Q_DECL_CONSTEXPR inline double QPoint3D::x() const
{
return xp;
}
Q_DECL_CONSTEXPR inline double QPoint3D::y() const
{
return yp;
}
Q_DECL_CONSTEXPR inline double QPoint3D::z() const
{
return zp;
}
Q_DECL_RELAXED_CONSTEXPR inline void QPoint3D::setX(double xpos)
{
xp = xpos;
}
Q_DECL_RELAXED_CONSTEXPR inline void QPoint3D::setY(double ypos)
{
yp = ypos;
}
Q_DECL_RELAXED_CONSTEXPR inline void QPoint3D::setZ(double zpos)
{
zp = zpos;
}
Q_DECL_RELAXED_CONSTEXPR inline double &QPoint3D::rx()
{
return xp;
}
Q_DECL_RELAXED_CONSTEXPR inline double &QPoint3D::ry()
{
return yp;
}
Q_DECL_RELAXED_CONSTEXPR inline double &QPoint3D::rz()
{
return zp;
}
Q_DECL_CONSTEXPR inline QPointF QPoint3D::toPointF() const
{
return QPointF(xp, yp);
}
Q_DECL_CONSTEXPR inline bool operator==(const QPoint3D &p1, const QPoint3D &p2)
{
return p1.xp == p2.xp && p1.yp == p2.yp && p1.zp == p2.zp;
}
Q_DECL_CONSTEXPR inline bool operator!=(const QPoint3D &p1, const QPoint3D &p2)
{
return p1.xp != p2.xp || p1.yp != p2.yp || p1.zp != p2.zp;
}
Q_DECL_CONSTEXPR inline bool qFuzzyCompare(const QPoint3D& v1, const QPoint3D& v2)
{
return ::qFuzzyCompare(v1.xp, v2.xp) &&
::qFuzzyCompare(v1.yp, v2.yp) &&
::qFuzzyCompare(v1.zp, v2.zp);
}
inline std::ostream& operator<< (std::ostream& stream, const QPoint3D& pos)
{
stream << "(" << pos.x() << "," << pos.y() << "," << pos.z() << ")";
return stream;
}
}
Q_DECLARE_TYPEINFO(LtsUtils::QPoint3D, Q_MOVABLE_TYPE);
+22
View File
@@ -0,0 +1,22 @@
#include "scoped_connection.h"
#include "connection.h"
namespace LtsUtils
{
ScopedConnection::ScopedConnection(IConnection *connection, Qt::ConnectionType connType)
: m_conn(connection)
{
Q_ASSERT(connection);
m_conn->connect(connType);
}
ScopedConnection::~ScopedConnection()
{
m_conn->disconnect();
}
}
+26
View File
@@ -0,0 +1,26 @@
#pragma once
#include <LtsUtilsCore/ltsutilscore_export.h>
#include <Qt>
namespace LtsUtils
{
class IConnection;
class LTSUTILSCORE_EXPORT ScopedConnection
{
public:
explicit ScopedConnection(IConnection *connection, Qt::ConnectionType = Qt::AutoConnection);
~ScopedConnection();
private:
IConnection *m_conn;
};
}
@@ -0,0 +1,301 @@
#include "sfm_bytemessage_converter.h"
namespace LtsUtils
{
static constexpr unsigned char XON = 0x11;
static constexpr unsigned char XOFF = 0x13;
static constexpr unsigned char STX = 0x02;
static constexpr unsigned char ETX = 0x03;
static constexpr unsigned char SUBST = 0x80;
static constexpr unsigned char SUB_XON = 0x91;
static constexpr unsigned char SUB_XOFF = 0x93;
static constexpr unsigned char SUB_STX = 0x82;
static constexpr unsigned char SUB_ETX = 0x83;
static constexpr unsigned char SUB_SUBST = 0x00;
static constexpr int HEADER_SIZE = 3;
static constexpr int CHECKSUM_SIZE = 1;
static constexpr int MINIMUM_BYTE_SIZE = 1 + HEADER_SIZE + CHECKSUM_SIZE + 1;
static SfmMessage getSfmMessage(const QByteArray &p_data)
{
unsigned short id = 0;
id |= (((unsigned short)p_data[0]) & 0x7F) << 8;
id |= (((unsigned short)p_data[1]) & 0xFF) << 0;
SfmMessage msg;
msg.setId(id);
msg.setRtr(p_data[0]&0x80);
msg.setPayload(p_data.right(p_data.size() - HEADER_SIZE));
return msg;
}
static QByteArray getHeader(const SfmMessage &p_msg)
{
QByteArray header(2, Qt::Uninitialized);
header[0] = ((p_msg.id() >> 8) & 0x7f) | (p_msg.rtr() << 7);
header[1] = (p_msg.id() >> 0) & 0xff;
return header;
}
static inline char getChecksum(const QByteArray &p_data)
{
char sum = 0;
for (const char c : p_data)
sum += c;
return sum ^ 0xff;
}
static QByteArray removeChecksum(const QByteArray &p_data)
{
QByteArray withoutChecksum(p_data);
ConversionError error ("Checksum error");
if (p_data.size() >= CHECKSUM_SIZE)
{
withoutChecksum.chop(1);
if (p_data.at(p_data.size() - 1) != getChecksum(withoutChecksum))
throw error;
}
else
throw error;
return withoutChecksum;
}
static QByteArray maskData(const QByteArray &p_data)
{
QByteArray maskData;
maskData.reserve(p_data.size() * 8 / 6);
for (const unsigned char byte : p_data)
{
switch (byte)
{
case XON:
maskData.append(SUBST);
maskData.append(SUB_XON);
break;
case XOFF:
maskData.append(SUBST);
maskData.append(SUB_XOFF);
break;
case STX:
maskData.append(SUBST);
maskData.append(SUB_STX);
break;
case ETX:
maskData.append(SUBST);
maskData.append(SUB_ETX);
break;
case SUBST:
maskData.append(SUBST);
maskData.append(static_cast<char>(SUB_SUBST));
break;
default:
maskData.append(byte);
break;
}
}
return maskData;
}
static bool mustBeMasked(const unsigned char byte)
{
switch (byte)
{
case XON:
case XOFF:
case STX:
case ETX:
case SUBST:
return true;
default:
break;
}
return false;
}
int lenMaskedData(const QByteArray &data)
{
int ret = data.length();
const unsigned char upperLen = ((data.length() & 0xff00) >> 8);
const unsigned char lowerLen = ((data.length() & 0x00ff) >> 0);
if (mustBeMasked(upperLen))
++ret;
if (mustBeMasked(lowerLen))
++ret;
for (const unsigned char byte : data)
{
if (mustBeMasked(byte))
++ret;
}
if (mustBeMasked(getChecksum(data)))
++ret;
return ret;
}
static QByteArray unmaskData(const QByteArray &p_data)
{
QByteArray unmaskData;
unmaskData.reserve(p_data.size());
for (int position = 0; position < p_data.size(); ++position)
{
unsigned char byte = p_data.at(position);
if (byte == SUBST)
{
++position;
byte = p_data.at(position);
switch (byte)
{
case SUB_XON: unmaskData.append(XON); break;
case SUB_XOFF: unmaskData.append(XOFF); break;
case SUB_STX: unmaskData.append(STX); break;
case SUB_ETX: unmaskData.append(ETX); break;
case SUB_SUBST: unmaskData.append(SUBST); break;
default: break;
}
}
else
unmaskData.append(byte);
}
return unmaskData;
}
static QByteArray addFrame(const QByteArray &p_data)
{
QByteArray ret;
ret.reserve(2 + p_data.size());
ret.append(STX);
ret.append(p_data);
ret.append(ETX);
return ret;
}
static QByteArray removeFrame(const QByteArray &p_data)
{
if (p_data[0] == STX && p_data[p_data.size() - 1] == ETX)
{
return p_data.mid(1, p_data.size() - 2);
}
else
throw ConversionError("Framing Error");
}
static void checkLength(const QByteArray &p_data)
{
if (p_data.size() < HEADER_SIZE)
throw ConversionError("Telegram too short");
unsigned char length = p_data[HEADER_SIZE - 1];
if (length != p_data.size() - HEADER_SIZE)
throw ConversionError("Telegram length does not match");
}
QByteArray byteStreamFromSfmMessage(const SfmMessage &message)
{
QByteArray byteData(getHeader(message));
byteData.append(message.payload().size());
byteData.append(message.payload());
byteData.append(getChecksum(byteData));
return addFrame(maskData(byteData));
}
SfmMessage byteStreamToSfmMessage(const QByteArray &datastream)
{
if (datastream.size() < MINIMUM_BYTE_SIZE)
throw ConversionError("Can't convert an QByteArray that hasn't the minimum size!");
QByteArray checkMsg;
checkMsg = removeFrame(datastream);
checkMsg = unmaskData(checkMsg);
checkMsg = removeChecksum(checkMsg);
checkLength(checkMsg);
return getSfmMessage(checkMsg);
}
QByteArray byteStreamFromEscMessage(const QByteArray &message)
{
QByteArray byteData = message;
if (message.size() == 1)
{
byteData.append(message);
}
else
byteData.append(getChecksum(byteData));
byteData = maskData(byteData);
byteData = addFrame(byteData);
return byteData;
}
QByteArray byteStreamToEscMessage(const QByteArray &datastream)
{
if (datastream.size() < 2)
return QByteArray("ERROR");
QByteArray checkMsg;
checkMsg = removeFrame(datastream);
checkMsg = unmaskData(checkMsg);
checkMsg.chop(1);
return checkMsg;
}
}
@@ -0,0 +1,64 @@
#pragma once
#include <LtsUtilsCore/ltsutilscore_export.h>
#include <QByteArray>
namespace LtsUtils
{
class LTSUTILSCORE_EXPORT SfmMessage
{
public:
unsigned int id() const { return m_id; }
void setId(unsigned int id) { m_id = id; }
bool rtr() const { return m_rtr; }
void setRtr(bool rtr) { m_rtr = rtr; }
QByteArray payload() const { return m_payload; }
void setPayload(const QByteArray &payload) { m_payload = payload; }
bool operator==(const SfmMessage &msg) const
{
return (m_id == msg.id() &&
m_rtr == msg.rtr() &&
m_payload == msg.payload());
}
protected:
unsigned int m_id = 0;
bool m_rtr = false;
QByteArray m_payload;
};
class ConversionError : public std::runtime_error
{
public:
using std::runtime_error::runtime_error;
};
LTSUTILSCORE_EXPORT QByteArray byteStreamFromSfmMessage(const SfmMessage &message);
LTSUTILSCORE_EXPORT SfmMessage byteStreamToSfmMessage(const QByteArray &datastream);
LTSUTILSCORE_EXPORT QByteArray byteStreamFromEscMessage(const QByteArray &message);
LTSUTILSCORE_EXPORT QByteArray byteStreamToEscMessage(const QByteArray &datastream);
LTSUTILSCORE_EXPORT int lenMaskedData(const QByteArray &data);
}
+39
View File
@@ -0,0 +1,39 @@
#pragma once
#include <QVariant>
#include <QDateTime>
#include <ngltools/ngltools_dtg.h>
namespace LtsUtils
{
inline bool lessThan(const QVariant &var1, const QVariant &var2)
{
if (var1.canConvert(QMetaType::QString) && var2.canConvert(QMetaType::QString))
{
QString str1(var1.toString());
QString str2(var2.toString());
bool k1 = false;
double d1 = str1.toDouble(&k1);
if (!k1)
return str1 < str2;
bool k2 = false;
double d2 = str2.toDouble(&k2);
if (!k2)
return str1 < str2;
return d1 < d2;
}
else if (var1.canConvert(QMetaType::Double) && var2.canConvert(QMetaType::Double))
return var1.toDouble() < var2.toDouble();
return false;
}
}
+11
View File
@@ -0,0 +1,11 @@
#
# $Id$
# $HeadURL$
# $Author$
#
# Created by Mike Wille, SLSE, 2016-09-19
#
ADD_SUBDIRECTORY(LtsUtilsGuiDds)
ADD_SUBDIRECTORY(ConnectDialog)
ADD_SUBDIRECTORY(StyleManager)
@@ -0,0 +1,28 @@
#
# $Id$
# $HeadURL$
# $Author$
# Created by Mike Wille, SLSE, 2016-05-12
#
SET(srcs
connect_dialog.h
connect_dialog.cpp
connect_dialog_nt.h
connect_dialog_nt.cpp
)
NGL_WRAP_UI(srcs
connect_dialog.ui
)
NGL_ADD_LIBRARY2(WS LtsUtilsGuiConnectDialog SHARED ${srcs})
NGL_TARGET_INCLUDE_DIRECTORIES(LtsUtilsGuiConnectDialog
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
${CMAKE_CURRENT_BINARY_DIR}/../
)
NGL_TARGET_LINK_LIBRARIES(LtsUtilsGuiConnectDialog
Qt5::Widgets
LtsWidgets
)
@@ -0,0 +1,73 @@
#include "connect_dialog.h"
#include "ui_connect_dialog.h"
#include <stdlib.h>
namespace LtsUtils
{
int ConnectingDialog::s_waitForHistoricalDataWaitTime = 10000;
void ConnectingDialog::reset()
{
m_ui->label->setText(QStringLiteral("<font color='orange'>%1</font>").arg(tr("Connecting to %1 on %2 ...").arg(m_serviceName, m_exerciseName)));
}
void ConnectingDialog::setup()
{
m_ui = new Ui::ConnectingDialog;
m_ui->setupUi(this);
reset();
setMinimumSize(sizeHint());
connect(m_ui->pbRetry, &QPushButton::clicked,
this, [this]()
{
m_ui->pbRetry->setEnabled(false);
m_ui->pbIgnore->setEnabled(false);
reset();
emit signalStopLoop();
});
connect(m_ui->pbIgnore, &QPushButton::clicked,
this, [this]()
{
m_ui->pbIgnore->setEnabled(false);
m_ui->pbRetry->setEnabled(false);
m_ui->pbIgnore->setText(tr("continuing.."));
deleteLater();
return;
});
}
ConnectingDialog::~ConnectingDialog()
{
delete m_ui;
}
void ConnectingDialog::failed()
{
m_ui->label->setText(QStringLiteral("<font color='red'>%1</font>").arg(tr("Could not connect to %1 on %2 !").arg(m_serviceName, m_exerciseName)));
m_ui->pbRetry->setEnabled(true);
m_ui->pbIgnore->setEnabled(true);
raise();
}
}
@@ -0,0 +1,82 @@
#pragma once
#include <ConnectDialog/ltsutilsguiconnectdialog_export.h>
#include <LtsWidgets/lts_frameless_dialog.h>
#include <QWidget>
#include <QTimer>
#include <functional>
namespace Ui
{
class ConnectingDialog;
}
namespace LtsUtils
{
class LTSUTILSGUICONNECTDIALOG_EXPORT ConnectingDialog : public LtsWidgets::LtsFramelessDialog
{
Q_OBJECT
public:
static int s_waitForHistoricalDataWaitTime;
template <typename DtcType, typename WaitForHistoricalDataFunction>
explicit ConnectingDialog(DtcType dtc,
WaitForHistoricalDataFunction waitForHistoricalDataFunction,
const QString &serviceName,
const QString &exerciseName,
QWidget *parent = nullptr)
: LtsWidgets::LtsFramelessDialog(parent, LtsWidgets::Behaviour::Modal)
, m_serviceName(serviceName)
, m_exerciseName(exerciseName)
, m_ui(nullptr)
{
setWindowTitle(tr("Connecting .."));
setup();
show();
while (true)
{
if ((dtc.get()->*waitForHistoricalDataFunction)(s_waitForHistoricalDataWaitTime))
{
deleteLater();
return;
}
if (s_waitForHistoricalDataWaitTime >= 999999)
{
deleteLater();
return;
}
else
{
failed();
}
}
}
~ConnectingDialog();
void failed();
private:
QString m_serviceName;
QString m_exerciseName;
Ui::ConnectingDialog *m_ui;
void reset();
void setup();
signals:
void signalStopLoop();
};
}
@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ConnectingDialog</class>
<widget class="QWidget" name="ConnectingDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>260</width>
<height>200</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>260</width>
<height>200</height>
</size>
</property>
<property name="windowTitle">
<string>Login</string>
</property>
<layout class="QVBoxLayout" name="mainLayout" stretch="0,0">
<item>
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="pbRetry">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Retry</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbIgnore">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Ignore</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,157 @@
#include "connect_dialog.h"
#include "connect_dialog_nt.h"
#include "ui_connect_dialog.h"
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
#include <QRandomGenerator>
#endif
namespace LtsUtils
{
ConnectingDialogNT::ConnectingDialogNT(const std::function<bool(int)> &checkFn,
const QString &serviceName,
const QString &exerciseName,
QWidget *parent)
: LtsWidgets::LtsFramelessDialog(parent, LtsWidgets::Behaviour::Modal)
, m_serviceName(serviceName)
, m_exerciseName(exerciseName)
, m_checkFn(checkFn)
, m_go(false)
, m_autoRetryTimer(new QTimer(this))
, m_ui(new Ui::ConnectingDialog )
{
m_ui->setupUi(this);
m_autoRetryTimer->setInterval(1000);
connect(m_autoRetryTimer, &QTimer::timeout,
this, [this]()
{
if (m_autoRetryTick < 1)
{
slotRetry();
return;
}
m_ui->pbRetry->setText(QStringLiteral("%1 [%2]").arg(tr("Retry")).arg(m_autoRetryTick));
m_autoRetryTick--;
});
reset();
setMinimumSize(sizeHint());
connect(m_ui->pbRetry, &QPushButton::clicked,
this, &ConnectingDialogNT::slotRetry);
connect(m_ui->pbIgnore, &QPushButton::clicked,
this, [this]()
{
m_ui->pbIgnore->setEnabled(false);
m_ui->pbRetry->setEnabled(false);
m_ui->pbIgnore->setText(tr("continuing.."));
emit signalFailed();
deleteLater();
return;
});
show();
connect(this, &ConnectingDialogNT::signalGo,
this, &ConnectingDialogNT::slotGo, Qt::QueuedConnection);
m_go = true;
m_ui->pbRetry->setEnabled(false);
}
int ConnectingDialogNT::random(int min, int max)
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
return QRandomGenerator::global()->bounded(min, max);
#else
return (qrand() % (((max + 1) - min) + min));
#endif
}
bool ConnectingDialogNT::event(QEvent *event)
{
bool result = LtsWidgets::LtsFramelessDialog::event(event);
if (event->type() == QEvent::Paint && m_go)
{
m_go = false;
QTimer::singleShot(0, this, &ConnectingDialogNT::signalGo);
}
return result;
}
void ConnectingDialogNT::slotRetry()
{
m_autoRetryTimer->stop();
m_ui->pbRetry->setText(tr("Retry"));
m_ui->pbRetry->setEnabled(false);
m_ui->pbIgnore->setEnabled(false);
reset();
QTimer::singleShot(1, this, &ConnectingDialogNT::slotGo);
}
void ConnectingDialogNT::slotGo()
{
if (m_checkFn(ConnectingDialog::s_waitForHistoricalDataWaitTime))
{
emit signalSuccess();
deleteLater();
return;
}
failed();
}
void ConnectingDialogNT::reset()
{
m_ui->label->setText(QStringLiteral("<font color='orange'>%1</font>").arg(tr("Connecting to %1 on %2 ...").arg(m_serviceName, m_exerciseName)));
}
ConnectingDialogNT::~ConnectingDialogNT()
{
delete m_ui;
}
void ConnectingDialogNT::failed()
{
m_ui->label->setText(QStringLiteral("<font color='red'>%1</font>").arg(tr("Could not connect to %1 on %2 !").arg(m_serviceName, m_exerciseName)));
m_ui->pbRetry->setEnabled(true);
m_ui->pbIgnore->setEnabled(true);
m_autoRetryTick = random(5, 20);
m_autoRetryTimer->start();
raise();
}
}
@@ -0,0 +1,63 @@
#pragma once
#include <ConnectDialog/ltsutilsguiconnectdialog_export.h>
#include <LtsWidgets/lts_frameless_dialog.h>
#include <functional>
class QTimer;
namespace Ui
{
class ConnectingDialog;
}
namespace LtsUtils
{
class LTSUTILSGUICONNECTDIALOG_EXPORT ConnectingDialogNT : public LtsWidgets::LtsFramelessDialog
{
Q_OBJECT
public:
explicit ConnectingDialogNT(const std::function<bool(int)> &checkFn,
const QString &serviceName,
const QString &exerciseName,
QWidget *parent);
~ConnectingDialogNT();
void failed();
private slots:
void slotGo();
void slotRetry();
signals:
void signalGo();
void signalFailed();
void signalSuccess();
private:
QString m_serviceName;
QString m_exerciseName;
std::function<bool(int)> m_checkFn;
bool m_go;
QTimer *m_autoRetryTimer;
int m_autoRetryTick { 0 };
Ui::ConnectingDialog *m_ui;
int random(int min, int max);
bool event(QEvent *event) override;
void reset();
};
}
@@ -0,0 +1,49 @@
#
# $Id$
# $HeadURL$
# $Author$
#
# Created by Mike Wille, SLSE, 2016-09-19
#
SET(SRCS
dds_vector_to_pixmap.cpp
dds_vector_to_pixmap.h
request_helper.cpp
request_helper.h
)
NGL_ADD_LIBRARY2(WS LtsUtilsGuiDds SHARED ${SRCS})
NGL_TARGET_INCLUDE_DIRECTORIES(LtsUtilsGuiDds
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
)
NGL_TARGET_LINK_LIBRARIES(LtsUtilsGuiDds
PRIVATE
LtsUtilsCoreHeaderOnly
LtsWidgets
Qt5::Gui
Qt5::Widgets
Qt5::Svg
PUBLIC
Qt5::Core
ddscore
)
NGL_TARGET_COMPILE_DEFINITIONS(LtsUtilsGuiDds
PUBLIC
REQUEST_HELPER_WITH_GUI
)
NGL_ADD_LIBRARY2(AAR HLA SV LtsUtilsDds SHARED request_helper.cpp request_helper.h)
NGL_TARGET_INCLUDE_DIRECTORIES(LtsUtilsDds
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
)
NGL_TARGET_LINK_LIBRARIES(LtsUtilsDds
PRIVATE
LtsUtilsCoreHeaderOnly
PUBLIC
Qt5::Core
ddscore
)
@@ -0,0 +1,134 @@
#include <LtsUtilsCore/dds_vector.h>
#include <LtsUtilsGuiDds/dds_vector_to_pixmap.h>
#include <QBuffer>
#include <QFile>
#include <QIcon>
#include <QImage>
#include <QPainter>
#include <QPixmap>
#include <QSvgRenderer>
namespace LtsUtils
{
QIcon iconFromSvg(const QByteArray &svgData, QSize iconSize)
{
QSvgRenderer renderer(svgData);
QPixmap p(iconSize);
p.fill(Qt::transparent);
QPainter painter(&p);
renderer.render(&painter);
painter.end();
return {p};
}
QIcon iconFromSvg(const QString &svgFilename, QSize iconSize)
{
QFile f(svgFilename);
if (!f.open(QIODevice::ReadOnly))
return {};
return iconFromSvg(f.readAll(), iconSize);
}
QPixmap pixmapFromIcon(const QIcon &icon, QSize iconSize)
{
return icon.pixmap(iconSize).scaled(100, 100, Qt::AspectRatioMode::IgnoreAspectRatio);
}
QPixmap pixmapFromSvg(const QString &svgFilename, QSize iconSize)
{
return pixmapFromIcon(iconFromSvg(svgFilename, iconSize), iconSize);
}
QPixmap getPixmap(const std::vector<uint8_t> &data)
{
if (data.size() == 0)
return QPixmap();
return getPixmap(QByteArray(reinterpret_cast<const char*>(&data.at(0)), data.size()));
}
QPixmap getPixmap(const QByteArray &data)
{
return QPixmap::fromImage(QImage::fromData(data));
}
QImage getImage(const std::vector<uint8_t> &data)
{
if (data.size() == 0)
return QImage();
return getImage(QByteArray(reinterpret_cast<const char*>(&data.at(0)), data.size()));
}
QImage getImage(const QByteArray &data)
{
return QImage::fromData(data);
}
static inline void setIf(bool *boolPtr, bool val)
{
if (boolPtr)
*boolPtr = val;
}
std::vector<uint8_t> fromPixmap(const QPixmap &pixmap, bool *bIsPng)
{
QBuffer buf;
buf.open(QIODevice::WriteOnly);
pixmap.save(&buf, "PNG");
buf.close();
QByteArray ba = buf.buffer();
setIf(bIsPng, true);
if (ba.size() > 10240 && !pixmap.hasAlpha() && !pixmap.hasAlphaChannel())
{
QBuffer buf2;
buf2.open(QIODevice::WriteOnly);
pixmap.save(&buf2, "JPG");
buf2.close();
if (buf2.buffer().size() < buf.buffer().size())
{
setIf(bIsPng, false);
ba = buf2.buffer();
}
}
return convert<std::vector<uint8_t>>(ba);
}
std::vector<uint8_t> fromImage(const QImage &image, bool *bIsPng)
{
QBuffer buf;
buf.open(QIODevice::WriteOnly);
image.save(&buf, "PNG");
buf.close();
QByteArray ba = buf.buffer();
setIf(bIsPng, true);
if ((ba.size() > 10240 && !image.hasAlphaChannel()) ||
ba.size() > 1024 * 1024)
{
QBuffer buf2;
buf2.open(QIODevice::WriteOnly);
image.save(&buf2, "JPG");
buf2.close();
if (buf2.buffer().size() < buf.buffer().size())
{
setIf(bIsPng, false);
ba = buf2.buffer();
}
}
return convert<std::vector<uint8_t>>(ba);
}
}
@@ -0,0 +1,33 @@
#pragma once
#include <LtsUtilsCore/ltsutilscore_export.h>
#include <QSize>
#include <QString>
#include <cstdint>
#include <vector>
class QByteArray;
class QPixmap;
class QImage;
class QIcon;
namespace LtsUtils
{
LTSUTILSCORE_EXPORT QPixmap getPixmap(const std::vector<uint8_t> &data);
LTSUTILSCORE_EXPORT QPixmap getPixmap(const QByteArray &data);
LTSUTILSCORE_EXPORT QImage getImage(const std::vector<uint8_t> &data);
LTSUTILSCORE_EXPORT QImage getImage(const QByteArray &data);
LTSUTILSCORE_EXPORT QIcon iconFromSvg(const QByteArray &svgData, QSize iconSize = QSize(100, 100));
LTSUTILSCORE_EXPORT QIcon iconFromSvg(const QString &svgFilename, QSize iconSize = QSize(100, 100));
LTSUTILSCORE_EXPORT QPixmap pixmapFromIcon(const QIcon &icon, QSize iconSize = QSize(100, 100));
LTSUTILSCORE_EXPORT QPixmap pixmapFromSvg(const QString &svgFilename, QSize iconSize = QSize(100, 100));
LTSUTILSCORE_EXPORT std::vector<uint8_t> fromPixmap(const QPixmap &pixmap, bool *bIsPng = nullptr);
LTSUTILSCORE_EXPORT std::vector<uint8_t> fromImage(const QImage &image, bool *bIsPng = nullptr);
}
@@ -0,0 +1,276 @@
#include "request_helper.h"
#ifdef REQUEST_HELPER_WITH_GUI
#include <LtsWidgets/lts_global_wait_dialog.h>
#include <LtsWidgets/lts_message_dialog.h>
#include <QWidget>
#endif
#include <QEventLoop>
#include <QTimer>
#include <memory>
#include <QJsonDocument>
#include <QJsonObject>
#define DEBUG
namespace LtsUtils
{
bool RequestHelper::s_debug = false;
RequestHelper::RequestHelper(QObject *parent, bool quiet,
const std::function<void (void)> &success,
const std::function<void (void)> &failure)
: QObject(parent)
, m_failed(false)
, m_repliedId(-1)
, m_quiet(quiet)
, m_blockingCall(true)
, m_successFn(success)
, m_failureFn(failure)
{
connect(this, &RequestHelper::signalSuccess, this, m_successFn, Qt::QueuedConnection);
connect(this, &RequestHelper::signalFailed, this, m_failureFn, Qt::QueuedConnection);
if (s_debug)
{
QTimer *t = new QTimer(this);
t->setInterval(2000);
t->setSingleShot(true);
connect(this, &RequestHelper::signalNextRequest, t, static_cast<void (QTimer::*)(void)>(&QTimer::start));
connect(t, &QTimer::timeout, this, &RequestHelper::slotNextRequest, Qt::QueuedConnection);
}
else
{
connect(this, &RequestHelper::signalNextRequest,
this, &RequestHelper::slotNextRequest,
Qt::QueuedConnection
);
}
}
void RequestHelper::addRequest(const std::function<int64_t()> &requestFunction,
const std::function<void(const Core::FunctionReply &baseReply)> &baseReplyHandler)
{
m_requestFunctions.append(RequestFunctionContainer(requestFunction, baseReplyHandler));
}
bool RequestHelper::requestReply(const Core::FunctionReply &baseReply)
{
const Core::FunctionReplyObject fro(baseReply.id(),
baseReply.errorString(),
baseReply.errorParams());
return _requestReply(fro, &baseReply);
}
bool RequestHelper::requestReply(const Core::FunctionReplyObject &replyObject)
{
return _requestReply(replyObject, nullptr);
}
bool RequestHelper::_requestReply(const Core::FunctionReplyObject &fro, const Core::FunctionReply *baseReply)
{
m_errorString = fro.translated();
#ifdef REQUEST_HELPER_WITH_GUI
if (fro.error())
{
if (!m_quiet)
{
if (m_blockingCall)
{
LtsWidgets::LtsMessageDialog::showMessage(qobject_cast<QWidget *>(parent()),
m_errorString,
tr("Request failed"));
}
else
{
new LtsWidgets::LtsMessageDialogNew(qobject_cast<QWidget *>(parent()),
m_errorString,
tr("Request failed"));
}
}
}
#endif
m_repliedId = fro.id();
if (m_singleRequestCustomFunctionReply != nullptr)
{
if (baseReply)
m_singleRequestCustomFunctionReply(*baseReply);
else
m_singleRequestCustomFunctionReply(Core::FunctionReply(fro.id(), fro.str(), fro.args(), fro.additionalInfo()));
}
if (fro.error())
{
failure();
return false;
}
emit signalNextRequest();
return true;
}
bool RequestHelper::startSingleRequest(const std::function<int64_t()> &requestFunction,
const std::function<void(const Core::FunctionReply &baseReply)> &baseReplyHandler)
{
addRequest(requestFunction, baseReplyHandler);
return startRequests();
}
void RequestHelper::failure()
{
m_failed = true;
emit signalFailed();
done();
}
void RequestHelper::done()
{
#ifdef REQUEST_HELPER_WITH_GUI
if (!m_quiet)
LtsWidgets::LtsGlobalWaitDialog::getInstance()->done();
#endif
m_requestFunctions.clear();
m_singleRequestCustomFunctionReply = nullptr;
if (m_blockingCall)
emit signalQuitLoop();
m_blockingCall = true;
if (!m_blockingCall)
deleteLater();
}
void RequestHelper::slotNextRequest()
{
if (m_requestFunctions.isEmpty())
{
if (!m_blockingCall)
emit signalSuccess();
done();
return;
}
const RequestFunctionContainer rfc = m_requestFunctions.takeFirst();
m_singleRequestCustomFunctionReply = rfc.second;
int64_t result = rfc.first();
if (result == 0)
{
#ifdef REQUEST_HELPER_WITH_GUI
if (!m_quiet)
{
if (m_blockingCall)
{
LtsWidgets::LtsMessageDialog::showMessage(qobject_cast<QWidget *>(parent()),
tr("Request failed"));
}
else
{
connect(new LtsWidgets::LtsMessageDialogNew(qobject_cast<QWidget *>(parent()),
tr("Request failed")), &LtsWidgets::LtsMessageDialogNew::destroyed,
this, [this]()
{
failure();
});
return;
}
}
#endif
failure();
}
}
void RequestHelper::startSingleBackgroundRequest(const std::function<int64_t()> &requestFunction,
const std::function<void (const Core::FunctionReply &)> &baseReplyHandler)
{
m_blockingCall = false;
startSingleRequest(requestFunction, baseReplyHandler);
}
void RequestHelper::startBackgroundRequests()
{
m_blockingCall = false;
startRequests();
}
void RequestHelper::setCustomWaitMessage(const QString &customWaitMessage)
{
m_customWaitMessage = (customWaitMessage + QStringLiteral(" ..."));
}
bool RequestHelper::startRequests()
{
if (m_requestFunctions.isEmpty())
{
#ifdef LTS_DEBUG
qWarning("RequestHelper: started request helper without requests!");
#endif
return true;
}
m_failed = false;
#ifdef REQUEST_HELPER_WITH_GUI
if (!m_quiet)
LtsWidgets::LtsGlobalWaitDialog::getInstance()->wait(m_customWaitMessage);
m_customWaitMessage.clear();
#endif
m_errorString.clear();
m_repliedId = -1;
if (s_debug)
{
QTimer *t = new QTimer(this);
t->setInterval(2000);
connect(t, &QTimer::timeout, this, &RequestHelper::slotNextRequest, Qt::QueuedConnection);
connect(t, &QTimer::timeout, t, &QTimer::deleteLater);
t->start();
}
else
{
slotNextRequest();
if (m_blockingCall)
{
QEventLoop loop;
connect(this, &RequestHelper::signalQuitLoop,
&loop, &QEventLoop::quit,
Qt::QueuedConnection);
loop.exec();
}
}
return (!m_failed);
}
}
@@ -0,0 +1,123 @@
#pragma once
#ifdef REQUEST_HELPER_WITH_GUI
#include <LtsUtilsGuiDds/ltsutilsguidds_export.h>
#define LTSUTILSGUIDDS_INTERNAL_EXPORT LTSUTILSGUIDDS_EXPORT
#else
#include <LtsUtilsGuiDds/ltsutilsdds_export.h>
#define LTSUTILSGUIDDS_INTERNAL_EXPORT LTSUTILSDDS_EXPORT
#endif
#include <DDS/Core/function_reply_object.h>
#include <DDS/Core/core.hpp>
#include <QObject>
#include <QVector>
#include <QPair>
#include <functional>
namespace LtsUtils
{
template<typename T>
dds::core::optional<T> toOptional(T inVal)
{
return inVal != T() ? dds::core::optional<T>(inVal) : dds::core::optional<T>();
}
template<typename T>
dds::core::optional<T> optional()
{
return dds::core::optional<T>();
}
class LTSUTILSGUIDDS_INTERNAL_EXPORT RequestHelper : public QObject
{
Q_OBJECT
public:
static bool s_debug;
explicit RequestHelper(QObject *parent = nullptr, bool quiet = false,
const std::function<void (void)> &success = [](){},
const std::function<void (void)> &failure = [](){});
~RequestHelper() = default;
bool quiet() const { return m_quiet; }
void setQuiet(bool quiet) { m_quiet = quiet; }
void addRequest(const std::function<int64_t()> &requestFunction,
const std::function<void(const Core::FunctionReply &baseReply)> &baseReplyHandler = nullptr);
bool startRequests();
bool startSingleRequest(const std::function<int64_t(void)> &requestFunction,
const std::function<void(const Core::FunctionReply &baseReply)> &baseReplyHandler = nullptr
);
void startSingleBackgroundRequest(const std::function<int64_t()> &requestFunction,
const std::function<void(const Core::FunctionReply &baseReply)> &baseReplyHandler = nullptr);
void startBackgroundRequests();
bool requestReply(const Core::FunctionReply &baseReply);
bool requestReply(const Core::FunctionReplyObject &replyObject);
bool hasRequests() const { return !m_requestFunctions.isEmpty(); }
int getRepliedId() const { return m_repliedId; }
QString getErrorString() const { return m_errorString; }
void setCustomWaitMessage(const QString &customWaitMessage);
bool failed() const { return m_failed; }
void failure();
private:
using RequestFunctionContainer = QPair<std::function<int64_t()>, std::function<void(const Core::FunctionReply &)>>;
QVector<RequestFunctionContainer> m_requestFunctions;
bool m_failed;
int m_repliedId;
std::function<void(const Core::FunctionReply &)> m_singleRequestCustomFunctionReply;
bool m_quiet;
bool m_blockingCall;
std::function<void (void)> m_successFn;
std::function<void (void)> m_failureFn;
QString m_errorString;
QString m_customWaitMessage;
void done();
bool _requestReply(const Core::FunctionReplyObject &fro, const Core::FunctionReply *baseReply);
signals:
void signalNextRequest();
void signalQuitLoop();
void signalSuccess();
void signalFailed();
private slots:
void slotNextRequest();
};
}
@@ -0,0 +1,22 @@
#
# $Id$
# $HeadURL$
# $Author$
# Created by Mike Wille, NLSE, 2018-02-15
#
SET(srcs
style_manager.h
style_manager.cpp
)
NGL_ADD_LIBRARY2(WS LtsUtilsGuiStyleManager SHARED ${srcs})
NGL_TARGET_INCLUDE_DIRECTORIES(LtsUtilsGuiStyleManager
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
${CMAKE_CURRENT_BINARY_DIR}/../
)
NGL_TARGET_LINK_LIBRARIES(LtsUtilsGuiStyleManager
Qt5::Core
LtsPluginLoader
)
@@ -0,0 +1,114 @@
#include "style_manager.h"
#include <LtsPluginManager/lts_plugin_loader.h>
#include <PluginInterfaces/style_plugin_interface.h>
#include <QPluginLoader>
#include <QDebug>
namespace LtsUtils
{
struct StyleManagerHandler
{
StyleManager styleManager;
};
Q_GLOBAL_STATIC(StyleManagerHandler, s_styleManagerHandler)
StyleManager *StyleManager::getInstance()
{
return &s_styleManagerHandler->styleManager;
}
bool StyleManager::loadStyle(const QString &stylePluginName, bool highDpi)
{
if (m_currentStylePluginLoader != nullptr)
{
QObject *pluginInstance = m_currentStylePluginLoader->instance();
StylePlugin::Plugin *sp = qobject_cast<StylePlugin::Plugin *>(pluginInstance);
if (sp == nullptr)
{
qWarning() << "StyleManager::loadStyle: could not unload style plugin - wrong type ("
<< pluginInstance->metaObject()->className() << ") - new style not loaded";
return false;
}
sp->unloadStyle();
m_currentStylePluginLoader = nullptr;
}
LtsPluginManager::LtsPluginLoader *pluginLoader = LtsPluginManager::LtsPluginLoader::getInstance();
QPluginLoader *stylePluginLoader = nullptr;
int pluginsLoaded = 0;
std::function<bool(const LtsPluginManager::PluginInstance &pi)> loadPluginFn = [&stylePluginLoader, &pluginsLoaded]
(const LtsPluginManager::PluginInstance &pi)
{
stylePluginLoader = pi.pluginLoader;
pluginsLoaded++;
return true;
};
if (!pluginLoader->loadPlugins(LtsPluginManager::PluginType::STYLE, loadPluginFn, QStringList() << stylePluginName))
{
qWarning() << "StyleManager::loadStyle: Error loading Style Plugin - using default Qt style";
return false;
}
if (pluginsLoaded == 0)
{
qWarning() << "StyleManager::loadStyle: Could not find Style Plugin" << stylePluginName << "- using default Qt style";
return false;
}
if (pluginsLoaded > 1)
{
qWarning() << "StyleManager::loadStyle: Style Plugin" << stylePluginName << " is ambiguous - using default Qt style";
return false;
}
if (stylePluginLoader == nullptr)
{
qWarning() << "StyleManager::loadStyle: No Style Plugin loader available - using default Qt style";
return false;
}
StylePlugin::Plugin *sp = qobject_cast<StylePlugin::Plugin *>(stylePluginLoader->instance());
if (sp == nullptr)
{
qWarning() << "StyleManager::loadStyle: could not load style plugin - wrong type ("
<< stylePluginLoader->instance()->metaObject()->className() << ") - new style not loaded";
return false;
}
sp->loadStyle(highDpi);
m_currentStylePluginLoader = stylePluginLoader;
m_stylePluginName = stylePluginName;
emit signalStyleChanged(stylePluginName);
return true;
}
}
@@ -0,0 +1,36 @@
#pragma once
#include <StyleManager/ltsutilsguistylemanager_export.h>
#include <QObject>
class QPluginLoader;
namespace LtsUtils
{
class LTSUTILSGUISTYLEMANAGER_EXPORT StyleManager : public QObject
{
Q_OBJECT
using QObject::QObject;
~StyleManager() = default;
public:
static StyleManager *getInstance();
bool loadStyle(const QString &stylePluginName, bool highDpi = false);
const QString &currentStyleName() const { return m_stylePluginName; }
private:
friend struct StyleManagerHandler;
QPluginLoader *m_currentStylePluginLoader = nullptr;
QString m_stylePluginName;
signals:
void signalStyleChanged(const QString &stylePluginName);
};
}
+21
View File
@@ -0,0 +1,21 @@
#
# $Id$
# $HeadURL$
# $Author$
#
SET(SRCS
settings.h
settings.cpp
)
NGL_ADD_LIBRARY2(ALL LtsUtilsSettings SHARED ${SRCS})
NGL_TARGET_INCLUDE_DIRECTORIES(LtsUtilsSettings
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
)
NGL_TARGET_LINK_LIBRARIES(LtsUtilsSettings
PUBLIC
Qt5::Core
)
+264
View File
@@ -0,0 +1,264 @@
#include "settings.h"
#include <QByteArray>
#include <QCoreApplication>
#include <QDataStream>
#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QRegularExpression>
#include <QVector>
#include <QDebug>
namespace LtsUtils
{
enum class SettingType
{
String = 1,
StringList = 2,
Json = 3,
FunctionKeys = 4,
Boolean = 5,
};
QString typeToString(SettingType t)
{
switch (t)
{
case SettingType::String:
return QStringLiteral("String");
case SettingType::StringList:
return QStringLiteral("StringList");
case SettingType::Json:
return QStringLiteral("Json");
case SettingType::FunctionKeys:
return QStringLiteral("FunctionKeys");
case SettingType::Boolean:
return QStringLiteral("Boolean");
}
Q_ASSERT(false);
return QStringLiteral("Unknown SettingType (%1)").arg(int(t));
}
SettingType stringToType(const QString &s)
{
if (s == typeToString(SettingType::String))
return SettingType::String;
if (s == typeToString(SettingType::StringList))
return SettingType::StringList;
if (s == typeToString(SettingType::Json))
return SettingType::Json;
if (s == typeToString(SettingType::FunctionKeys))
return SettingType::FunctionKeys;
if (s == typeToString(SettingType::Boolean))
return SettingType::Boolean;
Q_ASSERT(false);
return SettingType::String;
}
static QString craftKey(const QString &group, const QString &identifier)
{
return group + QLatin1Char('.') + identifier;
}
static OperatorSettings *s_operatorSettings = nullptr;
static void cleanupOperatorSettings()
{
delete s_operatorSettings;
s_operatorSettings = nullptr;
}
OperatorSettings *OperatorSettings::getInstance()
{
if (!s_operatorSettings)
{
s_operatorSettings = new OperatorSettings;
qAddPostRoutine(&cleanupOperatorSettings);
}
return s_operatorSettings;
}
static ProjectSettings *s_projectSettings = nullptr;
static void cleanupProjectSettings()
{
delete s_projectSettings;
s_projectSettings = nullptr;
}
ProjectSettings *ProjectSettings::getInstance()
{
if (!s_projectSettings)
{
s_projectSettings = new ProjectSettings;
qAddPostRoutine(&cleanupProjectSettings);
}
return s_projectSettings;
}
bool ProjectSettings::initFromFile(const QString &filename)
{
QFile f(filename);
if (!f.open(QIODevice::ReadOnly))
return false;
QJsonParseError jErr;
const QJsonObject settings = QJsonDocument::fromJson(f.readAll(), &jErr).object();
if (jErr.error != QJsonParseError::NoError)
return false;
const QJsonObject psObj = settings[QStringLiteral("ProjectSettings")].toObject();
if (psObj.isEmpty())
return false;
QHash<QString, QVariant> newData;
const QStringList &groupKeys(psObj.keys());
for (const auto &gKey : groupKeys)
{
const QJsonObject objGroup(psObj[gKey].toObject());
const QStringList &itemKeys(objGroup.keys());
for (const auto &key : itemKeys)
{
const QJsonObject obj(objGroup[key].toObject());
const auto strType(obj[QStringLiteral("Type")].toString());
const auto type = stringToType(strType);
const QJsonValue jVal(obj[QStringLiteral("Default")]);
QVariant val;
switch (type)
{
case SettingType::Json:
val = QJsonDocument(jVal.toObject()).toJson();
break;
case SettingType::StringList:
{
const QJsonArray arr(jVal.toArray());
QStringList sl;
sl.reserve(arr.size());
for (const auto &ele : arr)
sl.push_back(ele.toString());
val = sl;
break;
}
case SettingType::FunctionKeys:
val = jVal.toVariant();
break;
case SettingType::String:
val = jVal.toString();
break;
case SettingType::Boolean:
val = jVal.toBool();
break;
}
newData[craftKey(gKey, key)] = val;
}
}
getInstance()->m_data = newData;
return true;
}
bool ProjectSettings::isFunctionEnabled(const QString &group, const QString &function)
{
const QStringList functionNames = getInstance()->value(QStringLiteral("Functionalities"),
QStringLiteral("IdentifierList")).toStringList();
return functionNames.contains(group + QLatin1Char(':') + function);
}
void Settings::init(const QByteArray &settings)
{
QByteArray uncompressed;
try
{
uncompressed = qUncompress(settings);
}
catch (...)
{}
if (uncompressed.isEmpty())
uncompressed = settings;
QDataStream stream(uncompressed);
stream >> m_data;
}
QByteArray Settings::exportSettings() const
{
if (m_data.isEmpty())
return QByteArray();
QByteArray ba;
QDataStream stream(&ba, QIODevice::WriteOnly);
stream << m_data;
return qCompress(ba);
}
void Settings::clear()
{
m_data.clear();
}
void Settings::dump()
{
qWarning() << "Settings::m_data: keys=" << m_data.keys();
QHashIterator<QString, QVariant> it(m_data);
int i=0;
while (it.hasNext())
{
it.next();
qWarning() << i++ << ":" << " - key='" << it.key() << "' value -> '" << it.value() << "'";
}
qWarning() << "Settings::m_data: ------------------";
}
void Settings::setValue(const QString &group, const QString &identifier, const QVariant &value)
{
m_data.insert(craftKey(group, identifier), value);
emit valueChanged(group, identifier, value);
}
void Settings::removeValue(const QString &group, const QString &identifier)
{
if (m_data.remove(craftKey(group, identifier)))
emit valueRemoved(group, identifier);
}
QStringList Settings::identifiers(const QString &group) const
{
QStringList result;
for (auto it = m_data.begin(); it != m_data.end(); ++it)
{
QVector<QStringRef> decrafted = it.key().splitRef(QLatin1Char('.'));
if (decrafted.size() > 1 && group.compare(decrafted.at(0)) == 0)
result.append(decrafted.at(1).toString());
}
return result;
}
QVariant Settings::value(const QString &group, const QString &identifier, const QVariant &defaultValue) const
{
return m_data.value(craftKey(group, identifier), defaultValue);
}
}
+73
View File
@@ -0,0 +1,73 @@
#pragma once
#include <QObject>
#include <QVariant>
#include <QMap>
#include <LtsUtilsSettings/ltsutilssettings_export.h>
class QJsonObject;
namespace LtsUtils
{
class LTSUTILSSETTINGS_EXPORT Settings : public QObject
{
Q_OBJECT
public:
~Settings() = default;
void setValue(const QString &group, const QString &identifier, const QVariant &value);
void removeValue(const QString &group, const QString &identifier);
QVariant value(const QString &group, const QString &identifier, const QVariant &defaultValue = QVariant()) const;
QStringList identifiers(const QString &group) const;
void init(const QByteArray &settings);
QByteArray exportSettings() const;
void clear();
void dump();
protected:
Settings() = default;
signals:
void valueChanged(const QString &group, const QString &identifier, const QVariant &value);
void valueRemoved(const QString &group, const QString &identifier);
protected:
QHash<QString, QVariant> m_data;
};
class LTSUTILSSETTINGS_EXPORT OperatorSettings : public Settings
{
Q_OBJECT
public:
static OperatorSettings *getInstance();
};
class LTSUTILSSETTINGS_EXPORT ProjectSettings : public Settings
{
Q_OBJECT
public:
static ProjectSettings *getInstance();
static bool initFromFile(const QString &filename);
static bool isFunctionEnabled(const QString &group, const QString &function);
};
}