/******************************************************************************
* THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN
*/
#include "pushrules.h"
using namespace Quotient;
/******************************************************************************
* Copyright (C) 2015 Felix Rohrbach <kde@fxrh.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include <QtCore/QString>
#include <QtCore/QDateTime>
#include <QtCore/QJsonObject>
#include <QtCore/QJsonArray>
#include "util.h"
#include <memory>
namespace QMatrixClient
{
template <typename EventT>
using event_ptr_tt = std::unique_ptr<EventT>;
namespace _impl
{
template <typename EventT>
event_ptr_tt<EventT> doMakeEvent(const QJsonObject& obj);
}
class Event
{
Q_GADGET
public:
enum class Type : quint16
{
Unknown = 0,
Typing, Receipt, Tag, DirectChat, ReadMarker,
RoomEventBase = 0x1000,
RoomMessage = RoomEventBase + 1,
RoomEncryptedMessage, Redaction,
RoomStateEventBase = 0x1800,
RoomName = RoomStateEventBase + 1,
RoomAliases, RoomCanonicalAlias, RoomMember, RoomTopic,
RoomAvatar, RoomEncryption, RoomCreate, RoomJoinRules,
RoomPowerLevels,
Reserved = 0x2000
};
explicit Event(Type type) : _type(type) { }
Event(Type type, const QJsonObject& rep);
Event(const Event&) = delete;
virtual ~Event();
Type type() const { return _type; }
QString jsonType() const;
bool isStateEvent() const
{
return (quint16(_type) & 0x1800) == 0x1800;
}
QByteArray originalJson() const;
QJsonObject originalJsonObject() const;
// According to the CS API spec, every event also has
// a "content" object; but since its structure is different for
// different types, we're implementing it per-event type
// (and in most cases it will be a combination of other fields
// instead of "content" field).
const QJsonObject contentJson() const;
private:
Type _type;
QJsonObject _originalJson;
REGISTER_ENUM(Type)
Q_PROPERTY(Type type READ type CONSTANT)
Q_PROPERTY(QJsonObject contentJson READ contentJson CONSTANT)
};
using EventType = Event::Type;
using EventPtr = event_ptr_tt<Event>;
/** Create an event with proper type from a JSON object
* Use this factory template to detect the type from the JSON object
* contents (the detected event type should derive from the template
* parameter type) and create an event object of that type.
*/
template <typename EventT>
event_ptr_tt<EventT> makeEvent(const QJsonObject& obj)
{
auto e = _impl::doMakeEvent<EventT>(obj);
if (!e)
e = std::make_unique<EventT>(EventType::Unknown, obj);
return e;
}
namespace _impl
{
template <>
EventPtr doMakeEvent<Event>(const QJsonObject& obj);
}
/**
* \brief A vector of pointers to events with deserialisation capabilities
*
* This is a simple wrapper over a generic vector type that adds
* a convenience method to deserialise events from QJsonArray.
* \tparam EventT base type of all events in the vector
*/
template <typename EventT>
class EventsBatch : public std::vector<event_ptr_tt<EventT>>
{
public:
/**
* \brief Deserialise events from an array
*
* Given the following JSON construct, creates events from
* the array stored at key "node":
* \code
* "container": {
* "node": [ { "event_id": "!evt1:srv.org", ... }, ... ]
* }
* \endcode
* \param container - the wrapping JSON object
* \param node - the key in container that holds the array of events
*/
void fromJson(const QJsonObject& container, const QString& node)
{
const auto objs = container.value(node).toArray();
using size_type = typename std::vector<event_ptr_tt<EventT>>::size_type;
// The below line accommodates the difference in size types of
// STL and Qt containers.
this->reserve(static_cast<size_type>(objs.size()));
for (auto objValue: objs)
this->emplace_back(makeEvent<EventT>(objValue.toObject()));
}
};
using Events = EventsBatch<Event>;
class RedactionEvent;
/** This class corresponds to m.room.* events */
class RoomEvent : public Event
{
Q_GADGET
Q_PROPERTY(QString id READ id)
Q_PROPERTY(QDateTime timestamp READ timestamp CONSTANT)
Q_PROPERTY(QString roomId READ roomId CONSTANT)
Q_PROPERTY(QString senderId READ senderId CONSTANT)
Q_PROPERTY(QString redactionReason READ redactionReason)
Q_PROPERTY(bool isRedacted READ isRedacted)
Q_PROPERTY(QString transactionId READ transactionId)
public:
// RedactionEvent is an incomplete type here so we cannot inline
// constructors and destructors
explicit RoomEvent(Type type);
RoomEvent(Type type, const QJsonObject& rep);
~RoomEvent();
QString id() const { return _id; }
QDateTime timestamp() const;
QString roomId() const;
QString senderId() const;
bool isRedacted() const { return bool(_redactedBecause); }
const RedactionEvent* redactedBecause() const
{
return _redactedBecause.get();
}
QString redactionReason() const;
const QString& transactionId() const { return _txnId; }
/**
* Sets the transaction id for locally created events. This should be
* done before the event is exposed to any code using the respective
* Q_PROPERTY.
*
* \param txnId - transaction id, normally obtained from
* Connection::generateTxnId()
*/
void setTransactionId(const QString& txnId) { _txnId = txnId; }
/**
* Sets event id for locally created events
*
* When a new event is created locally, it has no server id yet.
* This function allows to add the id once the confirmation from
* the server is received. There should be no id set previously
* in the event. It's the responsibility of the code calling addId()
* to notify clients that use Q_PROPERTY(id) about its change
*/
void addId(const QString& id);
private:
QString _id;
// QString _roomId;
// QString _senderId;
// QDateTime _serverTimestamp;
event_ptr_tt<RedactionEvent> _redactedBecause;
QString _txnId;
};
using RoomEvents = EventsBatch<RoomEvent>;
using RoomEventPtr = event_ptr_tt<RoomEvent>;
namespace _impl
{
template <>
RoomEventPtr doMakeEvent<RoomEvent>(const QJsonObject& obj);
}
/**
* Conceptually similar to QStringView (but much more primitive), it's a
* simple abstraction over a pair of RoomEvents::const_iterator values
* referring to the beginning and the end of a range in a RoomEvents
* container.
*/
struct RoomEventsRange
{
RoomEvents::iterator from;
RoomEvents::iterator to;
RoomEvents::size_type size() const
{
Q_ASSERT(std::distance(from, to) >= 0);
return RoomEvents::size_type(std::distance(from, to));
}
bool empty() const { return from == to; }
RoomEvents::const_iterator begin() const { return from; }
RoomEvents::const_iterator end() const { return to; }
RoomEvents::iterator begin() { return from; }
RoomEvents::iterator end() { return to; }
};
class StateEventBase: public RoomEvent
{
public:
explicit StateEventBase(Type type, const QJsonObject& obj)
: RoomEvent(obj.contains("state_key") ? type : Type::Unknown,
obj)
{ }
explicit StateEventBase(Type type)
: RoomEvent(type)
{ }
~StateEventBase() override = 0;
virtual bool repeatsState() const;
};
template <typename ContentT>
struct Prev
{
template <typename... ContentParamTs>
explicit Prev(const QJsonObject& unsignedJson,
ContentParamTs&&... contentParams)
: senderId(unsignedJson.value("prev_sender").toString())
, content(unsignedJson.value("prev_content").toObject(),
std::forward<ContentParamTs>(contentParams)...)
{ }
QString senderId;
ContentT content;
};
template <typename ContentT>
class StateEvent: public StateEventBase
{
public:
using content_type = ContentT;
template <typename... ContentParamTs>
explicit StateEvent(Type type, const QJsonObject& obj,
ContentParamTs&&... contentParams)
: StateEventBase(type, obj)
, _content(contentJson(),
std::forward<ContentParamTs>(contentParams)...)
{
auto unsignedData = obj.value("unsigned").toObject();
if (unsignedData.contains("prev_content"))
_prev = std::make_unique<Prev<ContentT>>(unsignedData,
std::forward<ContentParamTs>(contentParams)...);
}
template <typename... ContentParamTs>
explicit StateEvent(Type type, ContentParamTs&&... contentParams)
: StateEventBase(type)
, _content(std::forward<ContentParamTs>(contentParams)...)
{ }
QJsonObject toJson() const { return _content.toJson(); }
const ContentT& content() const { return _content; }
/** @deprecated Use prevContent instead */
const ContentT* prev_content() const { return prevContent(); }
const ContentT* prevContent() const
{ return _prev ? &_prev->content : nullptr; }
QString prevSenderId() const { return _prev ? _prev->senderId : ""; }
protected:
ContentT _content;
std::unique_ptr<Prev<ContentT>> _prev;
};
} // namespace QMatrixClient
Q_DECLARE_METATYPE(QMatrixClient::Event*)
Q_DECLARE_METATYPE(QMatrixClient::RoomEvent*)
Q_DECLARE_METATYPE(const QMatrixClient::Event*)
Q_DECLARE_METATYPE(const QMatrixClient::RoomEvent*)