mirror of
https://github.com/overte-org/overte.git
synced 2025-08-07 23:49:55 +02:00
Ported over fixes that I made when working on delta-encoding for avatars.
This commit is contained in:
parent
6f5d2ba233
commit
6db385de7a
5 changed files with 184 additions and 32 deletions
|
@ -193,7 +193,7 @@ void Bitstream::persistWriteMappings(const WriteMappings& mappings) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
connect(it.key().data(), SIGNAL(destroyed(QObject*)), SLOT(clearSharedObject(QObject*)));
|
connect(it.key().data(), SIGNAL(destroyed(QObject*)), SLOT(clearSharedObject(QObject*)));
|
||||||
QPointer<SharedObject>& reference = _sharedObjectReferences[it.key()->getID()];
|
QPointer<SharedObject>& reference = _sharedObjectReferences[it.key()->getOriginID()];
|
||||||
if (reference) {
|
if (reference) {
|
||||||
_sharedObjectStreamer.removePersistentID(reference);
|
_sharedObjectStreamer.removePersistentID(reference);
|
||||||
reference->disconnect(this);
|
reference->disconnect(this);
|
||||||
|
@ -227,7 +227,7 @@ void Bitstream::persistReadMappings(const ReadMappings& mappings) {
|
||||||
if (!it.value()) {
|
if (!it.value()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
QPointer<SharedObject>& reference = _sharedObjectReferences[it.value()->getRemoteID()];
|
QPointer<SharedObject>& reference = _sharedObjectReferences[it.value()->getRemoteOriginID()];
|
||||||
if (reference) {
|
if (reference) {
|
||||||
_sharedObjectStreamer.removePersistentValue(reference.data());
|
_sharedObjectStreamer.removePersistentValue(reference.data());
|
||||||
}
|
}
|
||||||
|
@ -411,6 +411,10 @@ Bitstream& Bitstream::operator>>(QUrl& url) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Bitstream& Bitstream::operator<<(const QVariant& value) {
|
Bitstream& Bitstream::operator<<(const QVariant& value) {
|
||||||
|
if (!value.isValid()) {
|
||||||
|
_typeStreamerStreamer << NULL;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
const TypeStreamer* streamer = getTypeStreamers().value(value.userType());
|
const TypeStreamer* streamer = getTypeStreamers().value(value.userType());
|
||||||
if (streamer) {
|
if (streamer) {
|
||||||
_typeStreamerStreamer << streamer;
|
_typeStreamerStreamer << streamer;
|
||||||
|
@ -424,7 +428,11 @@ Bitstream& Bitstream::operator<<(const QVariant& value) {
|
||||||
Bitstream& Bitstream::operator>>(QVariant& value) {
|
Bitstream& Bitstream::operator>>(QVariant& value) {
|
||||||
TypeReader reader;
|
TypeReader reader;
|
||||||
_typeStreamerStreamer >> reader;
|
_typeStreamerStreamer >> reader;
|
||||||
value = reader.read(*this);
|
if (reader.getTypeName().isEmpty()) {
|
||||||
|
value = QVariant();
|
||||||
|
} else {
|
||||||
|
value = reader.read(*this);
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -656,6 +664,10 @@ Bitstream& Bitstream::operator>(ObjectReader& objectReader) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Bitstream& Bitstream::operator<(const TypeStreamer* streamer) {
|
Bitstream& Bitstream::operator<(const TypeStreamer* streamer) {
|
||||||
|
if (!streamer) {
|
||||||
|
*this << QByteArray();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
const char* typeName = QMetaType::typeName(streamer->getType());
|
const char* typeName = QMetaType::typeName(streamer->getType());
|
||||||
*this << QByteArray::fromRawData(typeName, strlen(typeName));
|
*this << QByteArray::fromRawData(typeName, strlen(typeName));
|
||||||
if (_metadataType == NO_METADATA) {
|
if (_metadataType == NO_METADATA) {
|
||||||
|
@ -702,6 +714,10 @@ Bitstream& Bitstream::operator<(const TypeStreamer* streamer) {
|
||||||
Bitstream& Bitstream::operator>(TypeReader& reader) {
|
Bitstream& Bitstream::operator>(TypeReader& reader) {
|
||||||
QByteArray typeName;
|
QByteArray typeName;
|
||||||
*this >> typeName;
|
*this >> typeName;
|
||||||
|
if (typeName.isEmpty()) {
|
||||||
|
reader = TypeReader();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
const TypeStreamer* streamer = _typeStreamerSubstitutions.value(typeName);
|
const TypeStreamer* streamer = _typeStreamerSubstitutions.value(typeName);
|
||||||
if (!streamer) {
|
if (!streamer) {
|
||||||
streamer = getTypeStreamers().value(QMetaType::type(typeName.constData()));
|
streamer = getTypeStreamers().value(QMetaType::type(typeName.constData()));
|
||||||
|
@ -847,9 +863,10 @@ Bitstream& Bitstream::operator<(const SharedObjectPointer& object) {
|
||||||
return *this << (int)0;
|
return *this << (int)0;
|
||||||
}
|
}
|
||||||
*this << object->getID();
|
*this << object->getID();
|
||||||
QPointer<SharedObject> reference = _sharedObjectReferences.value(object->getID());
|
*this << object->getOriginID();
|
||||||
|
QPointer<SharedObject> reference = _sharedObjectReferences.value(object->getOriginID());
|
||||||
if (reference) {
|
if (reference) {
|
||||||
writeRawDelta((QObject*)object.data(), (QObject*)reference.data());
|
writeRawDelta((const QObject*)object.data(), (const QObject*)reference.data());
|
||||||
} else {
|
} else {
|
||||||
*this << (QObject*)object.data();
|
*this << (QObject*)object.data();
|
||||||
}
|
}
|
||||||
|
@ -863,7 +880,9 @@ Bitstream& Bitstream::operator>(SharedObjectPointer& object) {
|
||||||
object = SharedObjectPointer();
|
object = SharedObjectPointer();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
QPointer<SharedObject> reference = _sharedObjectReferences.value(id);
|
int originID;
|
||||||
|
*this >> originID;
|
||||||
|
QPointer<SharedObject> reference = _sharedObjectReferences.value(originID);
|
||||||
QPointer<SharedObject>& pointer = _weakSharedObjectHash[id];
|
QPointer<SharedObject>& pointer = _weakSharedObjectHash[id];
|
||||||
if (pointer) {
|
if (pointer) {
|
||||||
ObjectReader objectReader;
|
ObjectReader objectReader;
|
||||||
|
@ -876,15 +895,19 @@ Bitstream& Bitstream::operator>(SharedObjectPointer& object) {
|
||||||
} else {
|
} else {
|
||||||
QObject* rawObject;
|
QObject* rawObject;
|
||||||
if (reference) {
|
if (reference) {
|
||||||
readRawDelta(rawObject, (QObject*)reference.data());
|
readRawDelta(rawObject, (const QObject*)reference.data());
|
||||||
} else {
|
} else {
|
||||||
*this >> rawObject;
|
*this >> rawObject;
|
||||||
}
|
}
|
||||||
pointer = static_cast<SharedObject*>(rawObject);
|
pointer = static_cast<SharedObject*>(rawObject);
|
||||||
if (pointer) {
|
if (pointer) {
|
||||||
|
if (reference) {
|
||||||
|
pointer->setOriginID(reference->getOriginID());
|
||||||
|
}
|
||||||
pointer->setRemoteID(id);
|
pointer->setRemoteID(id);
|
||||||
|
pointer->setRemoteOriginID(originID);
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "Null object" << pointer << reference;
|
qDebug() << "Null object" << pointer << reference << id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
object = static_cast<SharedObject*>(pointer.data());
|
object = static_cast<SharedObject*>(pointer.data());
|
||||||
|
@ -893,7 +916,7 @@ Bitstream& Bitstream::operator>(SharedObjectPointer& object) {
|
||||||
|
|
||||||
void Bitstream::clearSharedObject(QObject* object) {
|
void Bitstream::clearSharedObject(QObject* object) {
|
||||||
SharedObject* sharedObject = static_cast<SharedObject*>(object);
|
SharedObject* sharedObject = static_cast<SharedObject*>(object);
|
||||||
_sharedObjectReferences.remove(sharedObject->getID());
|
_sharedObjectReferences.remove(sharedObject->getOriginID());
|
||||||
int id = _sharedObjectStreamer.takePersistentID(sharedObject);
|
int id = _sharedObjectStreamer.takePersistentID(sharedObject);
|
||||||
if (id != 0) {
|
if (id != 0) {
|
||||||
emit sharedObjectCleared(id);
|
emit sharedObjectCleared(id);
|
||||||
|
@ -1099,6 +1122,10 @@ uint qHash(const TypeReader& typeReader, uint seed) {
|
||||||
return qHash(typeReader.getTypeName(), seed);
|
return qHash(typeReader.getTypeName(), seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDebug& operator<<(QDebug& debug, const TypeReader& typeReader) {
|
||||||
|
return debug << typeReader.getTypeName();
|
||||||
|
}
|
||||||
|
|
||||||
FieldReader::FieldReader(const TypeReader& reader, int index) :
|
FieldReader::FieldReader(const TypeReader& reader, int index) :
|
||||||
_reader(reader),
|
_reader(reader),
|
||||||
_index(index) {
|
_index(index) {
|
||||||
|
@ -1152,6 +1179,10 @@ uint qHash(const ObjectReader& objectReader, uint seed) {
|
||||||
return qHash(objectReader.getClassName(), seed);
|
return qHash(objectReader.getClassName(), seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDebug& operator<<(QDebug& debug, const ObjectReader& objectReader) {
|
||||||
|
return debug << objectReader.getClassName();
|
||||||
|
}
|
||||||
|
|
||||||
PropertyReader::PropertyReader(const TypeReader& reader, const QMetaProperty& property) :
|
PropertyReader::PropertyReader(const TypeReader& reader, const QMetaProperty& property) :
|
||||||
_reader(reader),
|
_reader(reader),
|
||||||
_property(property) {
|
_property(property) {
|
||||||
|
@ -1236,3 +1267,12 @@ QVariant TypeStreamer::getValue(const QVariant& object, int index) const {
|
||||||
void TypeStreamer::setValue(QVariant& object, int index, const QVariant& value) const {
|
void TypeStreamer::setValue(QVariant& object, int index, const QVariant& value) const {
|
||||||
// nothing by default
|
// nothing by default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDebug& operator<<(QDebug& debug, const TypeStreamer* typeStreamer) {
|
||||||
|
return debug << (typeStreamer ? QMetaType::typeName(typeStreamer->getType()) : "null");
|
||||||
|
}
|
||||||
|
|
||||||
|
QDebug& operator<<(QDebug& debug, const QMetaObject* metaObject) {
|
||||||
|
return debug << (metaObject ? metaObject->className() : "null");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -294,6 +294,9 @@ public:
|
||||||
template<class T> void writeRawDelta(const QList<T>& value, const QList<T>& reference);
|
template<class T> void writeRawDelta(const QList<T>& value, const QList<T>& reference);
|
||||||
template<class T> void readRawDelta(QList<T>& value, const QList<T>& reference);
|
template<class T> void readRawDelta(QList<T>& value, const QList<T>& reference);
|
||||||
|
|
||||||
|
template<class T> void writeRawDelta(const QVector<T>& value, const QVector<T>& reference);
|
||||||
|
template<class T> void readRawDelta(QVector<T>& value, const QVector<T>& reference);
|
||||||
|
|
||||||
template<class T> void writeRawDelta(const QSet<T>& value, const QSet<T>& reference);
|
template<class T> void writeRawDelta(const QSet<T>& value, const QSet<T>& reference);
|
||||||
template<class T> void readRawDelta(QSet<T>& value, const QSet<T>& reference);
|
template<class T> void readRawDelta(QSet<T>& value, const QSet<T>& reference);
|
||||||
|
|
||||||
|
@ -339,6 +342,9 @@ public:
|
||||||
template<class T> Bitstream& operator<<(const QList<T>& list);
|
template<class T> Bitstream& operator<<(const QList<T>& list);
|
||||||
template<class T> Bitstream& operator>>(QList<T>& list);
|
template<class T> Bitstream& operator>>(QList<T>& list);
|
||||||
|
|
||||||
|
template<class T> Bitstream& operator<<(const QVector<T>& list);
|
||||||
|
template<class T> Bitstream& operator>>(QVector<T>& list);
|
||||||
|
|
||||||
template<class T> Bitstream& operator<<(const QSet<T>& set);
|
template<class T> Bitstream& operator<<(const QSet<T>& set);
|
||||||
template<class T> Bitstream& operator>>(QSet<T>& set);
|
template<class T> Bitstream& operator>>(QSet<T>& set);
|
||||||
|
|
||||||
|
@ -472,6 +478,36 @@ template<class T> inline void Bitstream::readRawDelta(QList<T>& value, const QLi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class T> inline void Bitstream::writeRawDelta(const QVector<T>& value, const QVector<T>& reference) {
|
||||||
|
*this << value.size();
|
||||||
|
*this << reference.size();
|
||||||
|
for (int i = 0; i < value.size(); i++) {
|
||||||
|
if (i < reference.size()) {
|
||||||
|
writeDelta(value.at(i), reference.at(i));
|
||||||
|
} else {
|
||||||
|
*this << value.at(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> inline void Bitstream::readRawDelta(QVector<T>& value, const QVector<T>& reference) {
|
||||||
|
value = reference;
|
||||||
|
int size, referenceSize;
|
||||||
|
*this >> size >> referenceSize;
|
||||||
|
if (size < value.size()) {
|
||||||
|
value.erase(value.begin() + size, value.end());
|
||||||
|
}
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
if (i < referenceSize) {
|
||||||
|
readDelta(value[i], reference.at(i));
|
||||||
|
} else {
|
||||||
|
T element;
|
||||||
|
*this >> element;
|
||||||
|
value.append(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<class T> inline void Bitstream::writeRawDelta(const QSet<T>& value, const QSet<T>& reference) {
|
template<class T> inline void Bitstream::writeRawDelta(const QSet<T>& value, const QSet<T>& reference) {
|
||||||
int addedOrRemoved = 0;
|
int addedOrRemoved = 0;
|
||||||
foreach (const T& element, value) {
|
foreach (const T& element, value) {
|
||||||
|
@ -600,6 +636,27 @@ template<class T> inline Bitstream& Bitstream::operator>>(QList<T>& list) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class T> inline Bitstream& Bitstream::operator<<(const QVector<T>& vector) {
|
||||||
|
*this << vector.size();
|
||||||
|
foreach (const T& entry, vector) {
|
||||||
|
*this << entry;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> inline Bitstream& Bitstream::operator>>(QVector<T>& vector) {
|
||||||
|
int size;
|
||||||
|
*this >> size;
|
||||||
|
vector.clear();
|
||||||
|
vector.reserve(size);
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
T entry;
|
||||||
|
*this >> entry;
|
||||||
|
vector.append(entry);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
template<class T> inline Bitstream& Bitstream::operator<<(const QSet<T>& set) {
|
template<class T> inline Bitstream& Bitstream::operator<<(const QSet<T>& set) {
|
||||||
*this << set.size();
|
*this << set.size();
|
||||||
foreach (const T& entry, set) {
|
foreach (const T& entry, set) {
|
||||||
|
@ -683,6 +740,8 @@ private:
|
||||||
|
|
||||||
uint qHash(const TypeReader& typeReader, uint seed = 0);
|
uint qHash(const TypeReader& typeReader, uint seed = 0);
|
||||||
|
|
||||||
|
QDebug& operator<<(QDebug& debug, const TypeReader& typeReader);
|
||||||
|
|
||||||
/// Contains the information required to read a metatype field from the stream and apply it.
|
/// Contains the information required to read a metatype field from the stream and apply it.
|
||||||
class FieldReader {
|
class FieldReader {
|
||||||
public:
|
public:
|
||||||
|
@ -726,6 +785,8 @@ private:
|
||||||
|
|
||||||
uint qHash(const ObjectReader& objectReader, uint seed = 0);
|
uint qHash(const ObjectReader& objectReader, uint seed = 0);
|
||||||
|
|
||||||
|
QDebug& operator<<(QDebug& debug, const ObjectReader& objectReader);
|
||||||
|
|
||||||
/// Contains the information required to read an object property from the stream and apply it.
|
/// Contains the information required to read an object property from the stream and apply it.
|
||||||
class PropertyReader {
|
class PropertyReader {
|
||||||
public:
|
public:
|
||||||
|
@ -808,6 +869,10 @@ private:
|
||||||
int _type;
|
int _type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
QDebug& operator<<(QDebug& debug, const TypeStreamer* typeStreamer);
|
||||||
|
|
||||||
|
QDebug& operator<<(QDebug& debug, const QMetaObject* metaObject);
|
||||||
|
|
||||||
/// A streamer that works with Bitstream's operators.
|
/// A streamer that works with Bitstream's operators.
|
||||||
template<class T> class SimpleTypeStreamer : public TypeStreamer {
|
template<class T> class SimpleTypeStreamer : public TypeStreamer {
|
||||||
public:
|
public:
|
||||||
|
@ -818,11 +883,11 @@ public:
|
||||||
virtual void writeDelta(Bitstream& out, const QVariant& value, const QVariant& reference) const {
|
virtual void writeDelta(Bitstream& out, const QVariant& value, const QVariant& reference) const {
|
||||||
out.writeDelta(value.value<T>(), reference.value<T>()); }
|
out.writeDelta(value.value<T>(), reference.value<T>()); }
|
||||||
virtual void readDelta(Bitstream& in, QVariant& value, const QVariant& reference) const {
|
virtual void readDelta(Bitstream& in, QVariant& value, const QVariant& reference) const {
|
||||||
in.readDelta(*static_cast<T*>(value.data()), reference.value<T>()); }
|
T rawValue; in.readDelta(rawValue, reference.value<T>()); value = QVariant::fromValue(rawValue); }
|
||||||
virtual void writeRawDelta(Bitstream& out, const QVariant& value, const QVariant& reference) const {
|
virtual void writeRawDelta(Bitstream& out, const QVariant& value, const QVariant& reference) const {
|
||||||
out.writeRawDelta(value.value<T>(), reference.value<T>()); }
|
out.writeRawDelta(value.value<T>(), reference.value<T>()); }
|
||||||
virtual void readRawDelta(Bitstream& in, QVariant& value, const QVariant& reference) const {
|
virtual void readRawDelta(Bitstream& in, QVariant& value, const QVariant& reference) const {
|
||||||
in.readRawDelta(*static_cast<T*>(value.data()), reference.value<T>()); }
|
T rawValue; in.readRawDelta(rawValue, reference.value<T>()); value = QVariant::fromValue(rawValue); }
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A streamer for types compiled by mtc.
|
/// A streamer for types compiled by mtc.
|
||||||
|
@ -858,6 +923,22 @@ public:
|
||||||
static_cast<QList<T>*>(object.data())->replace(index, value.value<T>()); }
|
static_cast<QList<T>*>(object.data())->replace(index, value.value<T>()); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// A streamer for vector types.
|
||||||
|
template<class T> class CollectionTypeStreamer<QVector<T> > : public SimpleTypeStreamer<QVector<T> > {
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual TypeReader::Type getReaderType() const { return TypeReader::LIST_TYPE; }
|
||||||
|
virtual const TypeStreamer* getValueStreamer() const { return Bitstream::getTypeStreamer(qMetaTypeId<T>()); }
|
||||||
|
virtual void insert(QVariant& object, const QVariant& value) const {
|
||||||
|
static_cast<QVector<T>*>(object.data())->append(value.value<T>()); }
|
||||||
|
virtual void prune(QVariant& object, int size) const {
|
||||||
|
QVector<T>* list = static_cast<QVector<T>*>(object.data()); list->erase(list->begin() + size, list->end()); }
|
||||||
|
virtual QVariant getValue(const QVariant& object, int index) const {
|
||||||
|
return QVariant::fromValue(static_cast<const QVector<T>*>(object.constData())->at(index)); }
|
||||||
|
virtual void setValue(QVariant& object, int index, const QVariant& value) const {
|
||||||
|
static_cast<QVector<T>*>(object.data())->replace(index, value.value<T>()); }
|
||||||
|
};
|
||||||
|
|
||||||
/// A streamer for set types.
|
/// A streamer for set types.
|
||||||
template<class T> class CollectionTypeStreamer<QSet<T> > : public SimpleTypeStreamer<QSet<T> > {
|
template<class T> class CollectionTypeStreamer<QSet<T> > : public SimpleTypeStreamer<QSet<T> > {
|
||||||
public:
|
public:
|
||||||
|
@ -940,6 +1021,13 @@ template<class T> int registerStreamableMetaType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Registers a collection type and its streamer.
|
||||||
|
template<class T> int registerCollectionMetaType() {
|
||||||
|
int type = qRegisterMetaType<T>();
|
||||||
|
Bitstream::registerTypeStreamer(type, new CollectionTypeStreamer<T>());
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
/// Flags a class as streamable (use as you would Q_OBJECT).
|
/// Flags a class as streamable (use as you would Q_OBJECT).
|
||||||
#define STREAMABLE public: \
|
#define STREAMABLE public: \
|
||||||
static const int Type; \
|
static const int Type; \
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
|
||||||
#include "Bitstream.h"
|
#include "AttributeRegistry.h"
|
||||||
|
|
||||||
class ReliableChannel;
|
class ReliableChannel;
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,9 @@ REGISTER_META_OBJECT(SharedObject)
|
||||||
|
|
||||||
SharedObject::SharedObject() :
|
SharedObject::SharedObject() :
|
||||||
_id(++_lastID),
|
_id(++_lastID),
|
||||||
_remoteID(0) {
|
_originID(_id),
|
||||||
|
_remoteID(0),
|
||||||
|
_remoteOriginID(0) {
|
||||||
|
|
||||||
_weakHash.insert(_id, this);
|
_weakHash.insert(_id, this);
|
||||||
}
|
}
|
||||||
|
@ -39,26 +41,33 @@ void SharedObject::decrementReferenceCount() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedObject* SharedObject::clone(bool withID) const {
|
SharedObject* SharedObject::clone(bool withID, SharedObject* target) const {
|
||||||
// default behavior is to make a copy using the no-arg constructor and copy the stored properties
|
// default behavior is to make a copy using the no-arg constructor and copy the stored properties
|
||||||
const QMetaObject* metaObject = this->metaObject();
|
const QMetaObject* metaObject = this->metaObject();
|
||||||
SharedObject* newObject = static_cast<SharedObject*>(metaObject->newInstance());
|
if (!target) {
|
||||||
|
target = static_cast<SharedObject*>(metaObject->newInstance());
|
||||||
|
}
|
||||||
for (int i = 0; i < metaObject->propertyCount(); i++) {
|
for (int i = 0; i < metaObject->propertyCount(); i++) {
|
||||||
QMetaProperty property = metaObject->property(i);
|
QMetaProperty property = metaObject->property(i);
|
||||||
if (property.isStored()) {
|
if (property.isStored()) {
|
||||||
property.write(newObject, property.read(this));
|
if (property.userType() == qMetaTypeId<SharedObjectPointer>()) {
|
||||||
|
SharedObject* value = property.read(this).value<SharedObjectPointer>().data();
|
||||||
|
property.write(target, QVariant::fromValue(value ? value->clone(withID) : value));
|
||||||
|
} else {
|
||||||
|
property.write(target, property.read(this));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (const QByteArray& propertyName, dynamicPropertyNames()) {
|
foreach (const QByteArray& propertyName, dynamicPropertyNames()) {
|
||||||
newObject->setProperty(propertyName, property(propertyName));
|
target->setProperty(propertyName, property(propertyName));
|
||||||
}
|
}
|
||||||
if (withID) {
|
if (withID) {
|
||||||
newObject->setID(_id);
|
target->setOriginID(_originID);
|
||||||
}
|
}
|
||||||
return newObject;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SharedObject::equals(const SharedObject* other) const {
|
bool SharedObject::equals(const SharedObject* other, bool sharedAncestry) const {
|
||||||
if (!other) {
|
if (!other) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -67,7 +76,7 @@ bool SharedObject::equals(const SharedObject* other) const {
|
||||||
}
|
}
|
||||||
// default behavior is to compare the properties
|
// default behavior is to compare the properties
|
||||||
const QMetaObject* metaObject = this->metaObject();
|
const QMetaObject* metaObject = this->metaObject();
|
||||||
if (metaObject != other->metaObject()) {
|
if (metaObject != other->metaObject() && !sharedAncestry) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < metaObject->propertyCount(); i++) {
|
for (int i = 0; i < metaObject->propertyCount(); i++) {
|
||||||
|
@ -92,13 +101,15 @@ void SharedObject::dump(QDebug debug) const {
|
||||||
debug << this;
|
debug << this;
|
||||||
const QMetaObject* metaObject = this->metaObject();
|
const QMetaObject* metaObject = this->metaObject();
|
||||||
for (int i = 0; i < metaObject->propertyCount(); i++) {
|
for (int i = 0; i < metaObject->propertyCount(); i++) {
|
||||||
debug << metaObject->property(i).name() << metaObject->property(i).read(this);
|
QMetaProperty property = metaObject->property(i);
|
||||||
|
if (property.isStored()) {
|
||||||
|
debug << property.name() << property.read(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QList<QByteArray> dynamicPropertyNames = this->dynamicPropertyNames();
|
||||||
|
foreach (const QByteArray& propertyName, dynamicPropertyNames) {
|
||||||
|
debug << propertyName << property(propertyName);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void SharedObject::setID(int id) {
|
|
||||||
_weakHash.remove(_id);
|
|
||||||
_weakHash.insert(_id = id, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SharedObject::_lastID = 0;
|
int SharedObject::_lastID = 0;
|
||||||
|
|
|
@ -41,31 +41,44 @@ public:
|
||||||
/// Returns the unique local ID for this object.
|
/// Returns the unique local ID for this object.
|
||||||
int getID() const { return _id; }
|
int getID() const { return _id; }
|
||||||
|
|
||||||
|
/// Returns the local origin ID for this object.
|
||||||
|
int getOriginID() const { return _originID; }
|
||||||
|
|
||||||
|
void setOriginID(int originID) { _originID = originID; }
|
||||||
|
|
||||||
/// Returns the unique remote ID for this object, or zero if this is a local object.
|
/// Returns the unique remote ID for this object, or zero if this is a local object.
|
||||||
int getRemoteID() const { return _remoteID; }
|
int getRemoteID() const { return _remoteID; }
|
||||||
|
|
||||||
void setRemoteID(int remoteID) { _remoteID = remoteID; }
|
void setRemoteID(int remoteID) { _remoteID = remoteID; }
|
||||||
|
|
||||||
|
/// Returns the remote origin ID for this object, or zero if this is a local object.
|
||||||
|
int getRemoteOriginID() const { return _remoteOriginID; }
|
||||||
|
|
||||||
|
void setRemoteOriginID(int remoteOriginID) { _remoteOriginID = remoteOriginID; }
|
||||||
|
|
||||||
int getReferenceCount() const { return _referenceCount.load(); }
|
int getReferenceCount() const { return _referenceCount.load(); }
|
||||||
void incrementReferenceCount();
|
void incrementReferenceCount();
|
||||||
void decrementReferenceCount();
|
void decrementReferenceCount();
|
||||||
|
|
||||||
/// Creates a new clone of this object.
|
/// Creates a new clone of this object.
|
||||||
/// \param withID if true, give the clone the same ID as this object
|
/// \param withID if true, give the clone the same origin ID as this object
|
||||||
virtual SharedObject* clone(bool withID = false) const;
|
/// \target if non-NULL, a target object to populate (as opposed to creating a new instance of this object's class)
|
||||||
|
virtual SharedObject* clone(bool withID = false, SharedObject* target = NULL) const;
|
||||||
|
|
||||||
/// Tests this object for equality with another.
|
/// Tests this object for equality with another.
|
||||||
virtual bool equals(const SharedObject* other) const;
|
/// \param sharedAncestry if true and the classes of the objects differ, compare their shared ancestry (assuming that
|
||||||
|
/// this is an instance of a superclass of the other object's class) rather than simply returning false.
|
||||||
|
virtual bool equals(const SharedObject* other, bool sharedAncestry = false) const;
|
||||||
|
|
||||||
// Dumps the contents of this object to the debug output.
|
// Dumps the contents of this object to the debug output.
|
||||||
virtual void dump(QDebug debug = QDebug(QtDebugMsg)) const;
|
virtual void dump(QDebug debug = QDebug(QtDebugMsg)) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void setID(int id);
|
|
||||||
|
|
||||||
int _id;
|
int _id;
|
||||||
|
int _originID;
|
||||||
int _remoteID;
|
int _remoteID;
|
||||||
|
int _remoteOriginID;
|
||||||
QAtomicInt _referenceCount;
|
QAtomicInt _referenceCount;
|
||||||
|
|
||||||
static int _lastID;
|
static int _lastID;
|
||||||
|
|
Loading…
Reference in a new issue