From 6ea1fb621488910de055bd3af4d00343a763541a Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Mon, 5 Mar 2018 10:16:20 +0900 Subject: ReadMarkerEvent; TagEvent remade with less boilerplate code tagevent.h -> accountdataevents.h now has a macro to define more simplistic events along the lines of simplestateevents.h but inheriting from Event instead. TagEvent and ReadMarkerEvent(m.fully_read) are defined using this macro. ReadMarkerEvent is also wired through event.* (but not further yet). --- events/accountdataevents.h | 78 ++++++++++++++++++++++++++++++++++++++++++++++ events/event.cpp | 5 +-- events/event.h | 2 +- events/tagevent.cpp | 71 ----------------------------------------- events/tagevent.h | 74 ------------------------------------------- 5 files changed, 82 insertions(+), 148 deletions(-) create mode 100644 events/accountdataevents.h delete mode 100644 events/tagevent.cpp delete mode 100644 events/tagevent.h (limited to 'events') diff --git a/events/accountdataevents.h b/events/accountdataevents.h new file mode 100644 index 00000000..78cf9c46 --- /dev/null +++ b/events/accountdataevents.h @@ -0,0 +1,78 @@ +#include + +/****************************************************************************** + * Copyright (C) 2018 Kitsune Ral + * + * 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 "event.h" +#include "eventcontent.h" + +namespace QMatrixClient +{ + static constexpr const char* FavouriteTag = "m.favourite"; + static constexpr const char* LowPriorityTag = "m.lowpriority"; + + struct TagRecord + { + TagRecord (QString order) : order(std::move(order)) { } + explicit TagRecord(const QJsonValue& jv = {}) + : order(jv.toObject().value("order").toString()) + { } + + QString order; + + bool operator==(const TagRecord& other) const + { return order == other.order; } + bool operator!=(const TagRecord& other) const + { return !operator==(other); } + }; + + inline QJsonValue toJson(const TagRecord& rec) + { + return QJsonObject {{ QStringLiteral("order"), rec.order }}; + } + + using TagsMap = QHash; + +#define DEFINE_SIMPLE_EVENT(_Name, _TypeId, _EnumType, _ContentType, _ContentKey) \ + class _Name : public Event \ + { \ + public: \ + static constexpr const char* TypeId = _TypeId; \ + static const char* typeId() { return TypeId; } \ + explicit _Name(const QJsonObject& obj) \ + : Event((_EnumType), obj) \ + , _content(contentJson(), QStringLiteral(#_ContentKey)) \ + { } \ + template \ + explicit _Name(Ts&&... contentArgs) \ + : Event(_EnumType) \ + , _content(QStringLiteral(#_ContentKey), \ + std::forward(contentArgs)...) \ + { } \ + const _ContentType& _ContentKey() const { return _content.value; } \ + QJsonObject toJson() const { return _content.toJson(); } \ + protected: \ + EventContent::SimpleContent<_ContentType> _content; \ + }; + + DEFINE_SIMPLE_EVENT(TagEvent, "m.tag", EventType::Tag, TagsMap, tags) + DEFINE_SIMPLE_EVENT(ReadMarkerEvent, "m.fully_read", EventType::ReadMarker, + QString, event_id) +} diff --git a/events/event.cpp b/events/event.cpp index 74a2c3d7..f3e965e2 100644 --- a/events/event.cpp +++ b/events/event.cpp @@ -24,7 +24,7 @@ #include "roomavatarevent.h" #include "typingevent.h" #include "receiptevent.h" -#include "tagevent.h" +#include "accountdataevents.h" #include "redactionevent.h" #include "logging.h" @@ -88,7 +88,8 @@ EventPtr _impl::doMakeEvent(const QJsonObject& obj) return EventPtr(move(e)); return EventPtr { makeIfMatches(obj, obj["type"].toString()) }; + TypingEvent, ReceiptEvent, TagEvent, ReadMarkerEvent>( + obj, obj["type"].toString()) }; } RoomEvent::RoomEvent(Event::Type type) : Event(type) { } diff --git a/events/event.h b/events/event.h index f0ca2d15..eccfec41 100644 --- a/events/event.h +++ b/events/event.h @@ -45,7 +45,7 @@ namespace QMatrixClient enum class Type : quint16 { Unknown = 0, - Typing, Receipt, Tag, DirectChat, + Typing, Receipt, Tag, DirectChat, ReadMarker, RoomEventBase = 0x1000, RoomMessage = RoomEventBase + 1, RoomEncryptedMessage, Redaction, diff --git a/events/tagevent.cpp b/events/tagevent.cpp deleted file mode 100644 index c643ac62..00000000 --- a/events/tagevent.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2018 Kitsune Ral - * - * 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 - */ - -#include "tagevent.h" - -using namespace QMatrixClient; - -TagRecord::TagRecord(const QJsonObject& json) - : order(json.value("order").toString()) -{ } - -TagEvent::TagEvent() - : Event(Type::Tag) -{ - // TODO: Support getting a list of tags and saving it -} - -TagEvent::TagEvent(const QJsonObject& obj) - : Event(Type::Tag, obj) -{ - Q_ASSERT(obj["type"].toString() == TypeId); -} - -QStringList TagEvent::tagNames() const -{ - return tagsObject().keys(); -} - -QHash TagEvent::tags() const -{ - QHash result; - auto allTags = tagsObject(); - for (auto it = allTags.begin(); it != allTags.end(); ++ it) - result.insert(it.key(), TagRecord(it.value().toObject())); - return result; -} - -bool TagEvent::empty() const -{ - return tagsObject().empty(); -} - -bool TagEvent::contains(const QString& name) const -{ - return tagsObject().contains(name); -} - -TagRecord TagEvent::recordForTag(const QString& name) const -{ - return TagRecord(tagsObject().value(name).toObject()); -} - -QJsonObject TagEvent::tagsObject() const -{ - return contentJson().value("tags").toObject(); -} diff --git a/events/tagevent.h b/events/tagevent.h deleted file mode 100644 index 26fe8788..00000000 --- a/events/tagevent.h +++ /dev/null @@ -1,74 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2018 Kitsune Ral - * - * 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 "event.h" - -namespace QMatrixClient -{ - static constexpr const char* FavouriteTag = "m.favourite"; - static constexpr const char* LowPriorityTag = "m.lowpriority"; - - struct TagRecord - { - explicit TagRecord(const QJsonObject& json = {}); - - QString order; - }; - - class TagEvent : public Event - { - public: - TagEvent(); - explicit TagEvent(const QJsonObject& obj); - - /** Get the list of tag names */ - QStringList tagNames() const; - - /** Get the list of tags along with information on each */ - QHash tags() const; - - /** Check if the event lists no tags */ - bool empty() const; - - /** Check whether the tags list contains the specified name */ - bool contains(const QString& name) const; - - /** Get the record for the given tag name */ - TagRecord recordForTag(const QString& name) const; - - /** Get the whole tags content as a JSON object - * It's NOT recommended to use this method directly from client code. - * Use other convenience methods provided by the class. - */ - QJsonObject tagsObject() const; - - static constexpr const char * TypeId = "m.tag"; - }; - - using TagEventPtr = event_ptr_tt; - - inline QJsonValue toJson(const TagEventPtr& tagEvent) - { - return QJsonObject {{ "type", "m.tag" }, - // TODO: Replace tagsObject() with a genuine list of tags - // (or make the needed JSON upon TagEvent creation) - { "content", QJsonObject {{ "tags", tagEvent->tagsObject() }} }}; - } -} -- cgit v1.2.3 From f9cd6410623b7ddebf97e248584d1a8e838b4da8 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Mon, 5 Mar 2018 11:44:00 +0900 Subject: Room: addTag() and removeTag() Slightly changed TagRecord constructors to match. --- events/accountdataevents.h | 4 ++-- room.cpp | 20 ++++++++++++++++++++ room.h | 19 +++++++++++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) (limited to 'events') diff --git a/events/accountdataevents.h b/events/accountdataevents.h index 78cf9c46..f3ba27bb 100644 --- a/events/accountdataevents.h +++ b/events/accountdataevents.h @@ -30,8 +30,8 @@ namespace QMatrixClient struct TagRecord { - TagRecord (QString order) : order(std::move(order)) { } - explicit TagRecord(const QJsonValue& jv = {}) + TagRecord (QString order = {}) : order(std::move(order)) { } + explicit TagRecord(const QJsonValue& jv) : order(jv.toObject().value("order").toString()) { } diff --git a/room.cpp b/room.cpp index 86d1e6cd..cb94ddb6 100644 --- a/room.cpp +++ b/room.cpp @@ -586,6 +586,26 @@ TagRecord Room::tag(const QString& name) const return d->tags.value(name); } +void Room::addTag(const QString& name, const TagRecord& record) +{ + if (d->tags.contains(name)) + return; + + d->tags.insert(name, record); + d->setAccountData(TagEvent(d->tags)); + emit tagsChanged(); +} + +void Room::removeTag(const QString& name) +{ + if (!d->tags.contains(name)) + return; + + d->tags.remove(name); + d->setAccountData(TagEvent(d->tags)); + emit tagsChanged(); +} + void Room::setTags(const TagsMap& newTags) { if (newTags == d->tags) diff --git a/room.h b/room.h index bdd11452..0eb5ecc3 100644 --- a/room.h +++ b/room.h @@ -240,6 +240,25 @@ namespace QMatrixClient TagsMap tags() const; TagRecord tag(const QString& name) const; + /** Add a new tag to this room + * If this room already has this tag, nothing happens. If it's a new + * tag for the room, the respective tag record is added to the set + * of tags and the new set is sent to the server to update other + * clients. + */ + void addTag(const QString& name, const TagRecord& record = {}); + + /** Remove a tag from the room */ + void removeTag(const QString& name); + + /** Overwrite the room's tags + * This completely replaces the existing room's tags with a set + * of new ones and updates the new set on the server. Unlike + * most other methods in Room, this one sends a signal about changes + * immediately, not waiting for confirmation from the server + * (because tags are saved in account data rather than in shared + * room state). + */ void setTags(const TagsMap& newTags); /** Check whether the list of tags has m.favourite */ -- cgit v1.2.3