From cb54a2a5f9e83a5076eb501e60e88846a4aa28df Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 25 Jan 2018 09:43:11 +0900 Subject: Expose avatar URLs of Room and User as Q_PROPERTY This is needed for QML integration. Closes #155. --- room.cpp | 5 +++++ room.h | 4 ++++ user.h | 3 ++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/room.cpp b/room.cpp index 71b7b228..1c9063c9 100644 --- a/room.cpp +++ b/room.cpp @@ -262,6 +262,11 @@ QString Room::topic() const return d->topic; } +QUrl Room::avatarUrl() const +{ + return d->avatar.url(); +} + QImage Room::avatar(int dimension) { return avatar(dimension, dimension); diff --git a/room.h b/room.h index 2284e8b1..5b9a1785 100644 --- a/room.h +++ b/room.h @@ -105,6 +105,7 @@ namespace QMatrixClient Q_PROPERTY(QString canonicalAlias READ canonicalAlias NOTIFY namesChanged) Q_PROPERTY(QString displayName READ displayName NOTIFY namesChanged) Q_PROPERTY(QString topic READ topic NOTIFY topicChanged) + Q_PROPERTY(QUrl avatarUrl READ avatarUrl NOTIFY avatarChanged) Q_PROPERTY(int timelineSize READ timelineSize NOTIFY addedMessages) Q_PROPERTY(QStringList memberNames READ memberNames NOTIFY memberListChanged) Q_PROPERTY(int memberCount READ memberCount NOTIFY memberListChanged) @@ -122,6 +123,8 @@ namespace QMatrixClient Room(Connection* connection, QString id, JoinState initialJoinState); ~Room() override; + // Property accessors + Connection* connection() const; User* localUser() const; const QString& id() const; @@ -130,6 +133,7 @@ namespace QMatrixClient QString canonicalAlias() const; QString displayName() const; QString topic() const; + QUrl avatarUrl() const; Q_INVOKABLE JoinState joinState() const; Q_INVOKABLE QList usersTyping() const; QList membersLeft() const; diff --git a/user.h b/user.h index 91dfdc09..3df188a1 100644 --- a/user.h +++ b/user.h @@ -33,6 +33,7 @@ namespace QMatrixClient Q_PROPERTY(QString name READ name NOTIFY nameChanged) Q_PROPERTY(QString displayName READ displayname NOTIFY nameChanged STORED false) Q_PROPERTY(QString bridgeName READ bridged NOTIFY nameChanged STORED false) + Q_PROPERTY(QUrl avatarUrl READ avatarUrl NOTIFY avatarChanged) public: User(QString userId, Connection* connection); ~User() override; @@ -61,7 +62,7 @@ namespace QMatrixClient Q_INVOKABLE QImage avatar(int dimension); Q_INVOKABLE QImage avatar(int requestedWidth, int requestedHeight); - Q_INVOKABLE QUrl avatarUrl() const; + QUrl avatarUrl() const; void processEvent(Event* event); -- cgit v1.2.3 From 8590054a675bc5d2b07fff1acbb084d67c068113 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 25 Jan 2018 19:42:13 +0900 Subject: StateEvent<>: introduce Prev structure and prevSenderId() accessor Also switch prev_content() from accidental snake case to camel case (old name still provided for compatibility). --- events/event.h | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/events/event.h b/events/event.h index 6ed5ba49..b5a4d94e 100644 --- a/events/event.h +++ b/events/event.h @@ -255,6 +255,21 @@ namespace QMatrixClient virtual bool repeatsState() const; }; + template + struct Prev + { + template + explicit Prev(const QJsonObject& unsignedJson, + ContentParamTs&&... contentParams) + : senderId(unsignedJson.value("prev_sender").toString()) + , content(unsignedJson.value("prev_content").toObject(), + std::forward(contentParams)...) + { } + + QString senderId; + ContentT content; + }; + template class StateEvent: public StateEventBase { @@ -270,9 +285,8 @@ namespace QMatrixClient { auto unsignedData = obj.value("unsigned").toObject(); if (unsignedData.contains("prev_content")) - _prev.reset(new ContentT( - unsignedData.value("prev_content").toObject(), - std::forward(contentParams)...)); + _prev = std::make_unique>(unsignedData, + std::forward(contentParams)...); } template explicit StateEvent(Type type, ContentParamTs&&... contentParams) @@ -283,11 +297,15 @@ namespace QMatrixClient QJsonObject toJson() const { return _content.toJson(); } ContentT content() const { return _content; } - ContentT* prev_content() const { return _prev.data(); } + /** @deprecated Use prevContent instead */ + ContentT* prev_content() const { return prevContent(); } + ContentT* prevContent() const + { return _prev ? &_prev->content : nullptr; } + QString prevSenderId() const { return _prev ? _prev->senderId : ""; } protected: ContentT _content; - QScopedPointer _prev; + std::unique_ptr> _prev; }; } // namespace QMatrixClient Q_DECLARE_METATYPE(QMatrixClient::Event*) -- cgit v1.2.3 From 3a913f33853c675a1051460bc36278be20a4c941 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 25 Jan 2018 19:45:08 +0900 Subject: Room, User: const-tighten up the code, set QObject names To make debugging (including QML debugging) more convenient. --- room.cpp | 4 +++- room.h | 3 +-- user.cpp | 7 +++++-- user.h | 2 +- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/room.cpp b/room.cpp index 1c9063c9..d79363a3 100644 --- a/room.cpp +++ b/room.cpp @@ -213,6 +213,7 @@ RoomEventPtr TimelineItem::replaceEvent(RoomEventPtr&& other) Room::Room(Connection* connection, QString id, JoinState initialJoinState) : QObject(connection), d(new Private(connection, id, initialJoinState)) { + setObjectName(id); // See "Accessing the Public Class" section in // https://marcmutz.wordpress.com/translated-articles/pimp-my-pimpl-%E2%80%94-reloaded/ d->q = this; @@ -757,7 +758,7 @@ void Room::Private::removeMember(User* u) } } -QString Room::roomMembername(User *u) const +QString Room::roomMembername(const User* u) const { // See the CS spec, section 11.2.2.3 @@ -1239,6 +1240,7 @@ void Room::processStateEvents(const RoomEvents& events) case EventType::RoomCanonicalAlias: { auto aliasEvent = static_cast(event); d->canonicalAlias = aliasEvent->alias(); + setObjectName(d->canonicalAlias); qCDebug(MAIN) << "Room canonical alias updated:" << d->canonicalAlias; emitNamesChanged = true; break; diff --git a/room.h b/room.h index 5b9a1785..d2962d95 100644 --- a/room.h +++ b/room.h @@ -40,7 +40,6 @@ namespace QMatrixClient class MemberSorter; class LeaveRoomJob; class RedactEventJob; - class Room; class TimelineItem { @@ -162,7 +161,7 @@ namespace QMatrixClient * @brief Produces a disambiguated name for a given user in * the context of the room */ - Q_INVOKABLE QString roomMembername(User* u) const; + Q_INVOKABLE QString roomMembername(const User* u) const; /** * @brief Produces a disambiguated name for a user with this id in * the context of the room diff --git a/user.cpp b/user.cpp index baa7bc45..8b662acb 100644 --- a/user.cpp +++ b/user.cpp @@ -51,7 +51,9 @@ class User::Private User::User(QString userId, Connection* connection) : QObject(connection), d(new Private(std::move(userId), connection)) -{ } +{ + setObjectName(userId); +} User::~User() { @@ -74,6 +76,7 @@ void User::updateName(const QString& newName) if (oldName != newName) { d->name = newName; + setObjectName(displayname()); emit nameChanged(newName, oldName); } } @@ -127,7 +130,7 @@ QString User::bridged() const { return d->bridged; } -const Avatar& User::avatarObject() +const Avatar& User::avatarObject() const { return d->avatar; } diff --git a/user.h b/user.h index 3df188a1..4f48f20c 100644 --- a/user.h +++ b/user.h @@ -58,7 +58,7 @@ namespace QMatrixClient */ QString bridged() const; - const Avatar& avatarObject(); + const Avatar& avatarObject() const; Q_INVOKABLE QImage avatar(int dimension); Q_INVOKABLE QImage avatar(int requestedWidth, int requestedHeight); -- cgit v1.2.3 From 80f7e44e1a9056fc55147718dd2812eb93925ec1 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 25 Jan 2018 19:48:08 +0900 Subject: Room, User: expose avatarMediaId(); declare User for the metatype system To make it easy to use User objects and fetch room and user avatars from QML. Closes #155. --- avatar.cpp | 5 +++++ avatar.h | 1 + room.cpp | 9 +++++++-- room.h | 3 +++ user.cpp | 5 +++++ user.h | 3 +++ 6 files changed, 24 insertions(+), 2 deletions(-) diff --git a/avatar.cpp b/avatar.cpp index 44cad4e5..040bf9bb 100644 --- a/avatar.cpp +++ b/avatar.cpp @@ -62,6 +62,11 @@ QImage Avatar::get(int width, int height, notifier_t notifier) const return d->get({width, height}, notifier); } +QString Avatar::mediaId() const +{ + return d->_url.authority() + d->_url.path(); +} + QImage Avatar::Private::get(QSize size, Avatar::notifier_t notifier) const { // FIXME: Alternating between longer-width and longer-height requests diff --git a/avatar.h b/avatar.h index 28c16e4d..4d476ea5 100644 --- a/avatar.h +++ b/avatar.h @@ -38,6 +38,7 @@ namespace QMatrixClient QImage get(int dimension, notifier_t notifier) const; QImage get(int w, int h, notifier_t notifier) const; + QString mediaId() const; QUrl url() const; bool updateUrl(const QUrl& newUrl); diff --git a/room.cpp b/room.cpp index d79363a3..bc7c083e 100644 --- a/room.cpp +++ b/room.cpp @@ -263,6 +263,11 @@ QString Room::topic() const return d->topic; } +QString Room::avatarMediaId() const +{ + return d->avatar.mediaId(); +} + QUrl Room::avatarUrl() const { return d->avatar.url(); @@ -284,8 +289,8 @@ QImage Room::avatar(int width, int height) auto theOtherOneIt = d->membersMap.begin(); if (theOtherOneIt.value() == localUser()) ++theOtherOneIt; - return theOtherOneIt.value()->avatarObject() - .get(width, height, [=] { emit avatarChanged(); }); + return (*theOtherOneIt)->avatarObject() + .get(width, height, [=] { emit avatarChanged(); }); } return {}; } diff --git a/room.h b/room.h index d2962d95..b908a763 100644 --- a/room.h +++ b/room.h @@ -104,7 +104,9 @@ namespace QMatrixClient Q_PROPERTY(QString canonicalAlias READ canonicalAlias NOTIFY namesChanged) Q_PROPERTY(QString displayName READ displayName NOTIFY namesChanged) Q_PROPERTY(QString topic READ topic NOTIFY topicChanged) + Q_PROPERTY(QString avatarMediaId READ avatarMediaId NOTIFY avatarChanged STORED false) Q_PROPERTY(QUrl avatarUrl READ avatarUrl NOTIFY avatarChanged) + Q_PROPERTY(int timelineSize READ timelineSize NOTIFY addedMessages) Q_PROPERTY(QStringList memberNames READ memberNames NOTIFY memberListChanged) Q_PROPERTY(int memberCount READ memberCount NOTIFY memberListChanged) @@ -132,6 +134,7 @@ namespace QMatrixClient QString canonicalAlias() const; QString displayName() const; QString topic() const; + QString avatarMediaId() const; QUrl avatarUrl() const; Q_INVOKABLE JoinState joinState() const; Q_INVOKABLE QList usersTyping() const; diff --git a/user.cpp b/user.cpp index 8b662acb..b0890b61 100644 --- a/user.cpp +++ b/user.cpp @@ -145,6 +145,11 @@ QImage User::avatar(int width, int height) return d->avatar.get(width, height, [=] { emit avatarChanged(this); }); } +QString User::avatarMediaId() const +{ + return d->avatar.mediaId(); +} + QUrl User::avatarUrl() const { return d->avatar.url(); diff --git a/user.h b/user.h index 4f48f20c..8a2c53d9 100644 --- a/user.h +++ b/user.h @@ -33,6 +33,7 @@ namespace QMatrixClient Q_PROPERTY(QString name READ name NOTIFY nameChanged) Q_PROPERTY(QString displayName READ displayname NOTIFY nameChanged STORED false) Q_PROPERTY(QString bridgeName READ bridged NOTIFY nameChanged STORED false) + Q_PROPERTY(QString avatarMediaId READ avatarMediaId NOTIFY avatarChanged STORED false) Q_PROPERTY(QUrl avatarUrl READ avatarUrl NOTIFY avatarChanged) public: User(QString userId, Connection* connection); @@ -62,6 +63,7 @@ namespace QMatrixClient Q_INVOKABLE QImage avatar(int dimension); Q_INVOKABLE QImage avatar(int requestedWidth, int requestedHeight); + QString avatarMediaId() const; QUrl avatarUrl() const; void processEvent(Event* event); @@ -84,3 +86,4 @@ namespace QMatrixClient Private* d; }; } +Q_DECLARE_METATYPE(QMatrixClient::User*) -- cgit v1.2.3