Imported existing sources

This commit is contained in:
0xFEEDC0DE64
2018-09-15 20:49:15 +02:00
parent 3aa39af9e3
commit a62aa7ec5a
17 changed files with 544 additions and 0 deletions

10
DbMessaging.pro Normal file
View File

@@ -0,0 +1,10 @@
TEMPLATE = subdirs
SUBDIRS += messagingclient \
messaginglib \
messagingserver \
messagingtest
messagingclient.depends += messaginglib
messagingserver.depends += messaginglib
messagingtest.depends += messaginglib

28
messagingclient/main.cpp Normal file
View File

@@ -0,0 +1,28 @@
#include <QCoreApplication>
#include <QDebug>
#include "messages/mymessage.h"
int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
MyMessage original("Daniel", QDate(1996, 11, 12), QDateTime::currentDateTime(), 21, 80);
MyMessage copy(original);
original.setName("Peter");
QVariantMap delta;
original.copyTouchedTo(delta);
original.setTouched(false);
qDebug() << "before applying delta";
copy.debug();
copy.apply(delta);
qDebug() << "after applying delta";
copy.debug();
return app.exec();
}

View File

@@ -0,0 +1,20 @@
QT += core network
QT -= gui widgets
DBLIBS += messaginglib
TARGET = messagingclient
PROJECT_ROOT = ../..
SOURCES += main.cpp
HEADERS +=
FORMS +=
RESOURCES +=
TRANSLATIONS +=
include($${PROJECT_ROOT}/app.pri)

100
messaginglib/dbmsgbase.cpp Normal file
View File

@@ -0,0 +1,100 @@
#include "dbmsgbase.h"
#include <QDebug>
#include <algorithm>
#include "dbmsgfieldbase.h"
const QString DbMsgBase::m_clearedFieldsName(QStringLiteral("__CLEARED_FIELDS"));
DbMsgBase::DbMsgBase()
{
}
DbMsgBase::~DbMsgBase()
{
}
bool DbMsgBase::touched() const
{
const auto fields = getFields();
return std::any_of(fields.cbegin(), fields.cend(), [](const DbMsgFieldBase *field) { return field->touched(); });
}
void DbMsgBase::setTouched(bool touched)
{
for(DbMsgFieldBase *field : getFields())
field->setTouched(touched);
}
void DbMsgBase::debug() const
{
const auto fields = getFields();
for(auto iter = fields.cbegin(); iter != fields.cend(); iter++)
qDebug() << iter.key() << iter.value()->toVariant() << iter.value()->touched();
}
void DbMsgBase::copyTo(QVariantMap &variantMap) const
{
const auto fields = getFields();
for(auto iter = fields.cbegin(); iter != fields.cend(); iter++)
{
const auto key = iter.key();
const auto field = iter.value();
const auto hasValue = field->hasValue();
const auto variant = field->toVariant();
if(hasValue)
variantMap.insert(key, variant);
else
qWarning() << key << "has no value for full transmission!";
}
}
void DbMsgBase::copyTouchedTo(QVariantMap &variantMap) const
{
QStringList clearedFields;
const auto fields = getFields();
for(auto iter = fields.cbegin(); iter != fields.cend(); iter++)
if(iter.value()->touched())
{
if(iter.value()->hasValue())
variantMap.insert(iter.key(), iter.value()->toVariant());
else
clearedFields.append(iter.key());
}
if(!clearedFields.isEmpty())
variantMap.insert(m_clearedFieldsName, clearedFields);
}
void DbMsgBase::apply(const QVariantMap &variantMap)
{
const auto fields = getFields();
for(auto iter = variantMap.cbegin(); iter != variantMap.cend(); iter++)
{
if(iter.key() == m_clearedFieldsName)
{
Q_ASSERT(iter.value().type() == QVariant::StringList);
for(const auto &clearedField : iter.value().toStringList())
{
Q_ASSERT(fields.contains(clearedField));
const auto field = fields.value(clearedField);
if(field->touched())
qWarning() << "delta message contained field which has been touched!";
field->clear();
field->setTouched(false);
}
}
else
{
Q_ASSERT(fields.contains(iter.key()));
const auto field = fields.value(iter.key());
if(field->touched())
qWarning() << "delta message contained field which has been touched!";
field->setVariant(iter.value());
field->setTouched(false);
}
}
}

33
messaginglib/dbmsgbase.h Normal file
View File

@@ -0,0 +1,33 @@
#pragma once
#include <QString>
#include <QVariantMap>
#include <QMap>
#include "messaginglib_global.h"
#include "dbmsgmacros.h"
class DbMsgFieldBase;
class MESSAGINGLIB_EXPORT DbMsgBase
{
static const QString m_clearedFieldsName;
public:
DbMsgBase();
virtual ~DbMsgBase();
bool touched() const;
void setTouched(bool touched);
void debug() const;
void copyTo(QVariantMap &variantMap) const;
void copyTouchedTo(QVariantMap &variantMap) const;
void apply(const QVariantMap &variantMap);
protected:
virtual QMap<QString, DbMsgFieldBase*> getFields() = 0;
virtual QMap<QString, const DbMsgFieldBase*> getFields() const = 0;
};

72
messaginglib/dbmsgfield.h Normal file
View File

@@ -0,0 +1,72 @@
#pragma once
#include <QMetaType>
#include "dbmsgfieldbase.h"
#include "messaginglib_global.h"
template<typename T>
class DbMsgField : public DbMsgFieldBase
{
public:
DbMsgField();
DbMsgField(const T &value);
const T &getValue() const;
void setValue(const T &value);
void clear() override;
QVariant toVariant() const override;
void setVariant(const QVariant &variant) override;
private:
T m_value;
};
template<typename T>
DbMsgField<T>::DbMsgField() :
DbMsgFieldBase()
{
}
template<typename T>
DbMsgField<T>::DbMsgField(const T &value) :
DbMsgFieldBase(),
m_value(value)
{
setHasValue(true);
}
template<typename T>
const T &DbMsgField<T>::getValue() const
{
return m_value;
}
template<typename T>
void DbMsgField<T>::setValue(const T &value)
{
m_value = value;
setHasValue(true);
setTouched(true);
}
template<typename T>
void DbMsgField<T>::clear()
{
DbMsgFieldBase::clear();
m_value = T();
}
template<typename T>
QVariant DbMsgField<T>::toVariant() const
{
return getValue();
}
template<typename T>
void DbMsgField<T>::setVariant(const QVariant &variant)
{
Q_ASSERT(variant.type() == qMetaTypeId<T>());
m_value = variant.value<T>();
}

View File

@@ -0,0 +1,38 @@
#include "dbmsgfieldbase.h"
DbMsgFieldBase::DbMsgFieldBase() :
m_hasValue(false), m_touched(false)
{
}
DbMsgFieldBase::~DbMsgFieldBase()
{
}
bool DbMsgFieldBase::hasValue() const
{
return m_hasValue;
}
void DbMsgFieldBase::clear()
{
m_hasValue = false;
}
bool DbMsgFieldBase::touched() const
{
return m_touched;
}
void DbMsgFieldBase::setTouched(bool touched)
{
m_touched = touched;
}
void DbMsgFieldBase::setHasValue(bool hasValue)
{
if(m_hasValue && !hasValue)
clear();
else
m_hasValue = hasValue;
}

View File

@@ -0,0 +1,28 @@
#pragma once
#include <QVariant>
#include "messaginglib_global.h"
class MESSAGINGLIB_EXPORT DbMsgFieldBase
{
public:
DbMsgFieldBase();
virtual ~DbMsgFieldBase();
bool hasValue() const;
virtual void clear();
bool touched() const;
void setTouched(bool touched);
virtual QVariant toVariant() const = 0;
virtual void setVariant(const QVariant &variant) = 0;
protected:
void setHasValue(bool hasValue);
private:
bool m_hasValue;
bool m_touched;
};

View File

@@ -0,0 +1,51 @@
#pragma once
#define DECLARE_DBFIELD(TYPE, NAME, UPPER_NAME) \
private: \
DbMsgField<TYPE> m_##NAME;\
\
public: \
inline TYPE get##UPPER_NAME() const { return m_##NAME.getValue(); } \
inline void set##UPPER_NAME(const TYPE &NAME) { m_##NAME.setValue(NAME); } \
inline bool has##UPPER_NAME() const { return m_##NAME.hasValue(); } \
inline void clear##UPPER_NAME() { m_##NAME.clear(); } \
\
inline DbMsgField<TYPE> &NAME##Field() { return m_##NAME; } \
inline const DbMsgField<TYPE> &NAME##Field() const { return m_##NAME; } \
inline DbMsgFieldBase &NAME##FieldBase() { return m_##NAME; } \
inline const DbMsgFieldBase &NAME##FieldBase() const { return m_##NAME; }
#define DECLARE_DBMESSAGE(ClassName) \
public: \
ClassName() = default; \
ClassName(const ClassName &) = default; \
ClassName(ClassName &&) = default; \
protected: \
QMap<QString, DbMsgFieldBase*> getFields() override; \
QMap<QString, const DbMsgFieldBase*> getFields() const override; \
private: \
typedef DbMsgFieldBase &(ClassName::*FieldGetterMethod)(); \
static const QMap<QString, FieldGetterMethod> ALL_FIELDS;
#define IMPLEMENT_DBMESSAGE(ClassName) \
QMap<QString, DbMsgFieldBase *> ClassName::getFields() \
{ \
QMap<QString, DbMsgFieldBase*> fields; \
\
for(auto iter = ALL_FIELDS.cbegin(); iter != ALL_FIELDS.cend(); iter++) \
fields.insert(iter.key(), &(this->*iter.value())()); \
\
return fields; \
} \
\
QMap<QString, const DbMsgFieldBase *> ClassName::getFields() const \
{ \
QMap<QString, const DbMsgFieldBase*> fields; \
\
for(auto iter = ALL_FIELDS.cbegin(); iter != ALL_FIELDS.cend(); iter++) \
fields.insert(iter.key(), &(const_cast<ClassName*>(this)->*iter.value())()); \
\
return fields; \
} \
\
const QMap<QString, ClassName::FieldGetterMethod> ClassName::ALL_FIELDS

View File

@@ -0,0 +1,15 @@
#include "mymessage.h"
IMPLEMENT_DBMESSAGE(MyMessage) {
{ "name", &MyMessage::nameFieldBase },
{ "birthday", &MyMessage::birthdayFieldBase },
{ "sendTimestamp", &MyMessage::sendTimestampFieldBase },
{ "age", &MyMessage::ageFieldBase },
{ "weight", &MyMessage::weightFieldBase }
};
MyMessage::MyMessage(const QString &name, const QDate &birthday, const QDateTime &sendTimestamp, int age, double weight) :
DbMsgBase(),
m_name(name), m_birthday(birthday), m_sendTimestamp(sendTimestamp), m_age(age), m_weight(weight)
{
}

View File

@@ -0,0 +1,25 @@
#pragma once
#include <QString>
#include <QDateTime>
#include <QMap>
#include "dbmsgbase.h"
#include "messaginglib_global.h"
#include "dbmsgfield.h"
class DbMsgFieldBase;
class MESSAGINGLIB_EXPORT MyMessage : public DbMsgBase
{
DECLARE_DBMESSAGE(MyMessage)
public:
MyMessage(const QString &name, const QDate &birthday, const QDateTime &sendTimestamp, int age, double weight);
DECLARE_DBFIELD(QString, name, Name)
DECLARE_DBFIELD(QDate, birthday, Birthday)
DECLARE_DBFIELD(QDateTime, sendTimestamp, SendTimestamp)
DECLARE_DBFIELD(int, age, Age)
DECLARE_DBFIELD(double, weight, Weight)
};

View File

@@ -0,0 +1,28 @@
QT += core network
QT -= gui widgets
DBLIBS +=
PROJECT_ROOT = ../..
DEFINES += MESSAGINGLIB_LIBRARY
SOURCES += \
dbmsgbase.cpp \
dbmsgfieldbase.cpp \
messages/mymessage.cpp
HEADERS += messaginglib_global.h \
dbmsgbase.h \
dbmsgfield.h \
dbmsgfieldbase.h \
dbmsgmacros.h \
messages/mymessage.h
FORMS +=
RESOURCES +=
TRANSLATIONS +=
include($${PROJECT_ROOT}/lib.pri)

View File

@@ -0,0 +1,9 @@
#pragma once
#include <QtGlobal>
#if defined(MESSAGINGLIB_LIBRARY)
# define MESSAGINGLIB_EXPORT Q_DECL_EXPORT
#else
# define MESSAGINGLIB_EXPORT Q_DECL_IMPORT
#endif

11
messagingserver/main.cpp Normal file
View File

@@ -0,0 +1,11 @@
#include <QCoreApplication>
#include <QDebug>
int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
qDebug() << "hello from server";
return 0;
}

View File

@@ -0,0 +1,20 @@
QT += core network
QT -= gui widgets
DBLIBS += messaginglib
TARGET = messagingserver
PROJECT_ROOT = ../..
SOURCES += main.cpp
HEADERS +=
FORMS +=
RESOURCES +=
TRANSLATIONS +=
include($${PROJECT_ROOT}/app.pri)

View File

@@ -0,0 +1,21 @@
QT += core testlib
QT -= gui widgets
DBLIBS += messaginglib
#this makes install step fail
# CONFIG += testcase
PROJECT_ROOT = ../..
SOURCES += tst_messagingtest.cpp
HEADERS +=
FORMS +=
RESOURCES +=
TRANSLATIONS +=
include($${PROJECT_ROOT}/app.pri)

View File

@@ -0,0 +1,35 @@
#include <QtTest>
// add necessary includes here
class MessagingTest : public QObject
{
Q_OBJECT
public:
MessagingTest();
~MessagingTest();
private slots:
void test_case1();
};
MessagingTest::MessagingTest()
{
}
MessagingTest::~MessagingTest()
{
}
void MessagingTest::test_case1()
{
}
QTEST_APPLESS_MAIN(MessagingTest)
#include "tst_messagingtest.moc"