diff --git a/.gitmodules b/.gitmodules index fa882c1..9b476d5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "submodules/easyssl"] path = submodules/easyssl url = https://github.com/QuasarApp/easyssl.git +[submodule "submodules/constexpr-xxh3"] + path = submodules/constexpr-xxh3 + url = git@github.com:QuasarApp/constexpr-xxh3.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 32e68d9..44af376 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,6 +50,8 @@ find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network Sql Concurrent REQUIR add_subdirectory(submodules/QuasarAppLib) add_subdirectory(submodules/crc) +add_subdirectory(submodules/constexpr-xxh3) + if (HEART_SSL) option(EASYSSL_TESTS "disable tests of the easyssl submodule " OFF) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d417ba2..0c70004 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -51,7 +51,7 @@ set(PRIVATE_INCUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/private") add_library(${PROJECT_NAME} ${SOURCE_CPP}) -target_link_libraries(${PROJECT_NAME} PUBLIC Qt::Core Qt::Network Qt::Sql Qt::Concurrent QuasarApp crc ) +target_link_libraries(${PROJECT_NAME} PUBLIC Qt::Core Qt::Network Qt::Sql Qt::Concurrent QuasarApp crc xxh3) if (HEART_SSL) target_link_libraries(${PROJECT_NAME} PUBLIC easyssl) endif() diff --git a/src/public/streammultiversion.cpp b/src/public/streammultiversion.cpp index dbf1750..24feccb 100644 --- a/src/public/streammultiversion.cpp +++ b/src/public/streammultiversion.cpp @@ -22,4 +22,16 @@ char StreamMultiversion::readVersion(QDataStream &stream) { return version; } + +char StreamMultiversion::versionHeader(char, QDataStream &stream) { + return readVersion(stream); +} + +char StreamMultiversion::versionHeader(char version, QDataStream &stream) const { + saveVersion(version, stream); + return version; + +} + + } diff --git a/src/public/streammultiversion.h b/src/public/streammultiversion.h index 0030335..83dd9d2 100644 --- a/src/public/streammultiversion.h +++ b/src/public/streammultiversion.h @@ -23,16 +23,41 @@ namespace QH { * class myClass: public StreamMultiversion { * protected: * QDataStream &fromStream(QDataStream &stream) override { - * char version = readVersion(); + * char version = versionHeader(0, stream); + * readWrite(stream, data); * return stream; * } * * QDataStream &toStream(QDataStream &stream) const override { - * saveVersion(1, stream); + * char version = versionHeader(0, stream); + * readWrite(stream, data); * return stream; * } * + * private: + * int data; + * * } + * @endcode + * + * More example of use: + * @code{cpp} + * QDataStream &ClassName::fromStream(QDataStream &stream) + { + versionHeader(0, stream); + + READ_WRITE_IMPL(fild0, + fild1) + } + + QDataStream &ClassName::toStream(QDataStream &stream) const + { + versionHeader(0, stream); + + READ_WRITE_IMPL(fild0, + fild1) + } + * @endcode * */ class HEARTSHARED_EXPORT StreamMultiversion: public StreamBase @@ -43,6 +68,8 @@ class HEARTSHARED_EXPORT StreamMultiversion: public StreamBase ~StreamMultiversion(); // StreamBase interface +protected: + /** * @brief saveVersion save version of the object to the stream. * @param version - version of the object. @@ -62,7 +89,72 @@ class HEARTSHARED_EXPORT StreamMultiversion: public StreamBase */ char readVersion(QDataStream &stream); + /** + * @brief versionHeader this is new function that automaticaly choose what shuld be to-do (read/wirte). + * @param version this is a version of object. + * @param stream this is stream cheenel to save or read. + * @return version of object. + */ + char versionHeader(char version, QDataStream &stream); + + /** + * @brief versionHeader this is new function that automaticaly choose what shuld be to-do (read/wirte). + * @param version this is a version of object. + * @param stream this is stream cheenel to save or read. + * @return version of object. + */ + char versionHeader(char version, QDataStream &stream) const; + + /** + * @brief readWrite this method automaticaly choose what we need to-do read or write. + * @param stream + * @param data + */ + template + void readWrite(QDataStream &stream, const T& data) const { + stream << data; + } + + /** + * @brief readWrite this method automaticaly choose what we need to-do read or write. + * @param stream + * @param data + */ + template + void readWrite(QDataStream &stream, T& data) { + stream >> data; + + } + + /** + * @brief readWritePack - this is a pack write or read from the srting + * @param stream - stream cheenel to save or read. + * @param args - list of arguments + */ + template + void readWritePack(QDataStream &stream, Args&&... args) const { + (readWrite(stream, std::forward(args)), ...); + } + + /** + * @brief readWritePack - this is a pack write or read from the srting + * @param stream - stream cheenel to save or read. + * @param args - list of arguments + */ + template + void readWritePack(QDataStream &stream, Args&&... args) { + (readWrite(stream, std::forward(args)), ...); + } }; + } + + +#define READ_WRITE_IMPL(...) \ + readWritePack(stream, __VA_ARGS__); \ + return stream; \ + + + #endif // STREAMMULTIVERSION_H diff --git a/src/public/translatablestring.cpp b/src/public/translatablestring.cpp new file mode 100644 index 0000000..67e84be --- /dev/null +++ b/src/public/translatablestring.cpp @@ -0,0 +1,111 @@ +//# +//# Copyright (C) 2025-2025 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "translatablestring.h" +#include "crc32constexper.h" +namespace QH { + +TranslatableString::TranslatableString(int data) { + _data = QString::number(data); + _isKey = false; +} + +TranslatableString::TranslatableString(const QString& data, bool isKey) { + _data = data; + _isKey = isKey; +} + +TranslatableString::TranslatableString(const QList &pack) { + _pack = pack; +} + +bool TranslatableString::operator==(const TranslatableString &other) const { + return _data == other._data && _isKey == other._isKey && _args == other._args && _pack == other._pack; +} + +bool TranslatableString::isValid() const { + return true; +} + +bool TranslatableString::isEmpty() const { + return _data.isEmpty() && _pack.isEmpty(); +} + +QString TranslatableString::text() const { + if (_pack.size()) { + QString result = _pack.first().text(); + for (int i = 1; i < _pack.size(); i++) { + result += ", " + _pack[i].text(); + } + return result; + } + + if (_isKey) { + QString result = QObject::tr(_data.toLatin1()); + for (const auto& arg: _args) { + result = result.arg(arg.text()); + } + + return result; + } + + return _data; +} + +const QString &TranslatableString::rawText() const { + return _data; +} + +int TranslatableString::calcCrc32Hash() const { + if (_data.isEmpty()) + return 0; + return QuasarAppUtils::calculateCrc32(_data.toLatin1(), _data.size()); +} + +TranslatableString TranslatableString::tr(const QString &source) { + return {source, true}; +} + +QDataStream &TranslatableString::fromStream(QDataStream &stream) { + versionHeader(0, stream); + + readWrite(stream, _isKey); + readWrite(stream, _data); + readWrite(stream, _args); + readWrite(stream, _pack); + + return stream; +} + +QDataStream &TranslatableString::toStream(QDataStream &stream) const { + versionHeader(0, stream); + + readWrite(stream, _isKey); + readWrite(stream, _data); + readWrite(stream, _args); + readWrite(stream, _pack); + + return stream; +} + +TranslatableString &TranslatableString::setArgs(const QList &newArgs) { + _args = newArgs; + + return *this; +} + +TranslatableString &TranslatableString::arg(const TranslatableString &newArg) { + _args.push_back(newArg); + + return *this; +} + +TranslatableString &TranslatableString::arg(int newArg) { + _args.push_back({newArg}); + return *this; +} +} diff --git a/src/public/translatablestring.h b/src/public/translatablestring.h new file mode 100644 index 0000000..efb2d1c --- /dev/null +++ b/src/public/translatablestring.h @@ -0,0 +1,101 @@ +//# +//# Copyright (C) 2025-2025 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + + +#ifndef TRANSLATABLESTRING_H +#define TRANSLATABLESTRING_H +#include + + +namespace QH { + +/** + * @brief The TranslatableString class is a wrapper for The QString with boolean flag isKey. + * @note ise this class if you want to save text into file and want to get correct translations after reading. + */ +class HEARTSHARED_EXPORT TranslatableString: public StreamMultiversion +{ +public: + TranslatableString(int data ); + + TranslatableString(const QString& data = "", + bool isKey = true); + + TranslatableString(const QList& pack); + + + TranslatableString(const TranslatableString &) = default; + TranslatableString(TranslatableString &&) = default; + TranslatableString &operator=(const TranslatableString &) = default; + TranslatableString &operator=(TranslatableString &&) = default; + + bool operator==(const TranslatableString& other) const; + + // ValidableObject interface + bool isValid() const override; + + bool isEmpty() const; + + /** + * @brief text this method return translated text. + * @return + */ + QString text() const; + + /** + * @brief rawText return raw key source. + * @return source text (key if object created with the qtTrId method) + */ + const QString& rawText() const; + + /** + * @brief calcCrc32Hash this method calc hash from raw text. + * @return + */ + int calcCrc32Hash() const; + + /** + * @brief tr this method create a string translation wrapper and save translation key for lupdate tool + * @param source this is text source. + * @return + */ + static TranslatableString tr(const QString& source); + + /** + * @brief qtTrId this method create a string translation wrapper and save translation key for lupdate tool + * @param source this is a source text. + * @return translatable string. + * @see https://doc.qt.io/qt-6/qttranslation.html#qtTrId + */ + static TranslatableString qtTrId(const QString& source); + + /** + * @brief setArgs this method set args for translation. + * @param newArgs this is a list of args. + * @return this object. + */ + TranslatableString& setArgs(const QList &newArgs); + TranslatableString& arg(const TranslatableString &newArg); + + TranslatableString& arg(int newArg); + +protected: + QDataStream &fromStream(QDataStream &stream) override; + QDataStream &toStream(QDataStream &stream) const override; + +private: + QString _data; + bool _isKey = false; + QList _args; + QList _pack; + +}; +} + + +#endif // TRANSLATABLESTRING_H diff --git a/submodules/QuasarAppLib b/submodules/QuasarAppLib index 36adbce..7eaf293 160000 --- a/submodules/QuasarAppLib +++ b/submodules/QuasarAppLib @@ -1 +1 @@ -Subproject commit 36adbced12a51229d17bd90d2a2252f537eb9f17 +Subproject commit 7eaf293630d528f6bcd846788e4aff52b74cc088 diff --git a/submodules/constexpr-xxh3 b/submodules/constexpr-xxh3 new file mode 160000 index 0000000..c750e82 --- /dev/null +++ b/submodules/constexpr-xxh3 @@ -0,0 +1 @@ +Subproject commit c750e827e7162757c946bb3a0ef569a91252f18a