aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--events/event.cpp2
-rw-r--r--events/event.h3
-rw-r--r--events/roomavatarevent.cpp23
-rw-r--r--events/roomavatarevent.h53
-rw-r--r--libqmatrixclient.pri2
-rw-r--r--room.cpp57
-rw-r--r--room.h10
-rw-r--r--user.cpp5
-rw-r--r--user.h2
10 files changed, 146 insertions, 12 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index fc3276c9..26c7bf46 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -70,6 +70,7 @@ set(libqmatrixclient_SRCS
events/roomcanonicalaliasevent.cpp
events/roommemberevent.cpp
events/roomtopicevent.cpp
+ events/roomavatarevent.cpp
events/typingevent.cpp
events/receiptevent.cpp
events/encryptedevent.cpp
diff --git a/events/event.cpp b/events/event.cpp
index 304f2af6..9963a0ef 100644
--- a/events/event.cpp
+++ b/events/event.cpp
@@ -24,6 +24,7 @@
#include "roomcanonicalaliasevent.h"
#include "roommemberevent.h"
#include "roomtopicevent.h"
+#include "roomavatarevent.h"
#include "typingevent.h"
#include "receiptevent.h"
#include "encryptedevent.h"
@@ -136,6 +137,7 @@ RoomEvent* RoomEvent::fromJson(const QJsonObject& obj)
"m.room.canonical_alias", make<RoomCanonicalAliasEvent>,
"m.room.member", make<RoomMemberEvent>,
"m.room.topic", make<RoomTopicEvent>,
+ "m.room.avatar", make<RoomAvatarEvent>,
"m.room.encryption", make<EncryptionEvent>,
/* Insert new ROOM event types BEFORE this line */
nullptr
diff --git a/events/event.h b/events/event.h
index ec993522..c151ac0e 100644
--- a/events/event.h
+++ b/events/event.h
@@ -34,7 +34,8 @@ namespace QMatrixClient
enum class Type
{
RoomMessage, RoomName, RoomAliases, RoomCanonicalAlias,
- RoomMember, RoomTopic, RoomEncryption, RoomEncryptedMessage,
+ RoomMember, RoomTopic, RoomAvatar,
+ RoomEncryption, RoomEncryptedMessage,
Typing, Receipt, Unknown
};
diff --git a/events/roomavatarevent.cpp b/events/roomavatarevent.cpp
new file mode 100644
index 00000000..7a5f82a1
--- /dev/null
+++ b/events/roomavatarevent.cpp
@@ -0,0 +1,23 @@
+/******************************************************************************
+ * Copyright (C) 2017 Kitsune Ral <kitsune-ral@users.sf.net>
+ *
+ * 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 "roomavatarevent.h"
+
+using namespace QMatrixClient;
+
+
diff --git a/events/roomavatarevent.h b/events/roomavatarevent.h
new file mode 100644
index 00000000..411de4e8
--- /dev/null
+++ b/events/roomavatarevent.h
@@ -0,0 +1,53 @@
+/******************************************************************************
+ * Copyright (C) 2017 Kitsune Ral <kitsune-ral@users.sf.net>
+ *
+ * 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 <utility>
+
+#include "eventcontent.h"
+
+namespace QMatrixClient
+{
+ class RoomAvatarEvent: public RoomEvent
+ {
+ public:
+ explicit RoomAvatarEvent(EventContent::ImageContent avatar)
+ : RoomEvent(Type::RoomAvatar), _avatar(std::move(avatar))
+ { }
+ explicit RoomAvatarEvent(const QJsonObject& obj)
+ : RoomEvent(Type::RoomAvatar, obj), _avatar(contentJson())
+ { }
+
+ const EventContent::ImageContent& content() const { return _avatar; }
+
+ QJsonObject toJson() const { return _avatar.toJson(); }
+
+ static constexpr const char* TypeId = "m.room.avatar";
+
+ private:
+ // It's a bit of an overkill to use a full-fledged ImageContent
+ // because in reality m.room.avatar usually only has a single URL,
+ // without a thumbnail. But The Spec says there be thumbnails, and
+ // we follow The Spec.
+ EventContent::ImageContent _avatar;
+ };
+
+} // namespace QMatrixClient
diff --git a/libqmatrixclient.pri b/libqmatrixclient.pri
index 9bcb911f..9eb6bd16 100644
--- a/libqmatrixclient.pri
+++ b/libqmatrixclient.pri
@@ -18,6 +18,7 @@ HEADERS += \
$$PWD/events/roomcanonicalaliasevent.h \
$$PWD/events/roommemberevent.h \
$$PWD/events/roomtopicevent.h \
+ $$PWD/events/roomavatarevent.h \
$$PWD/events/typingevent.h \
$$PWD/events/receiptevent.h \
$$PWD/jobs/basejob.h \
@@ -48,6 +49,7 @@ SOURCES += \
$$PWD/events/roomcanonicalaliasevent.cpp \
$$PWD/events/roommemberevent.cpp \
$$PWD/events/roomtopicevent.cpp \
+ $$PWD/events/roomavatarevent.cpp \
$$PWD/events/typingevent.cpp \
$$PWD/events/receiptevent.cpp \
$$PWD/jobs/basejob.cpp \
diff --git a/room.cpp b/room.cpp
index 65cf2d2a..53a6b160 100644
--- a/room.cpp
+++ b/room.cpp
@@ -27,12 +27,14 @@
#include "events/roomaliasesevent.h"
#include "events/roomcanonicalaliasevent.h"
#include "events/roomtopicevent.h"
+#include "events/roomavatarevent.h"
#include "events/roommemberevent.h"
#include "events/typingevent.h"
#include "events/receiptevent.h"
#include "jobs/sendeventjob.h"
#include "jobs/roommessagesjob.h"
#include "jobs/postreceiptjob.h"
+#include "avatar.h"
#include "connection.h"
#include "user.h"
@@ -53,7 +55,7 @@ class Room::Private
Private(Connection* c, QString id_, JoinState initialJoinState)
: q(nullptr), connection(c), id(std::move(id_))
- , joinState(initialJoinState), unreadMessages(false)
+ , avatar(c), joinState(initialJoinState), unreadMessages(false)
, highlightCount(0), notificationCount(0), roomMessagesJob(nullptr)
{ }
@@ -73,6 +75,7 @@ class Room::Private
QString name;
QString displayname;
QString topic;
+ Avatar avatar;
JoinState joinState;
bool unreadMessages;
int highlightCount;
@@ -189,6 +192,23 @@ QString Room::topic() const
return d->topic;
}
+QPixmap Room::avatar(int width, int height)
+{
+ if (!d->avatar.url().isEmpty())
+ return d->avatar.get(width, height, [=] { emit avatarChanged(); });
+
+ // Use the other side's avatar for 1:1's
+ if (d->membersMap.size() == 2)
+ {
+ auto theOtherOneIt = d->membersMap.begin();
+ if (theOtherOneIt.value() == localUser())
+ ++theOtherOneIt;
+ return theOtherOneIt.value()->avatarObject()
+ .get(width, height, [=] { emit avatarChanged(); });
+ }
+ return {};
+}
+
JoinState Room::joinState() const
{
return d->joinState;
@@ -778,6 +798,17 @@ void Room::processStateEvents(const RoomEvents& events)
emit topicChanged();
break;
}
+ case EventType::RoomAvatar: {
+ const auto& avatarEventContent =
+ static_cast<RoomAvatarEvent*>(event)->content();
+ if (d->avatar.updateUrl(avatarEventContent.url))
+ {
+ qCDebug(MAIN) << "Room avatar URL updated:"
+ << avatarEventContent.url.toString();
+ emit avatarChanged();
+ }
+ break;
+ }
case EventType::RoomMember: {
auto memberEvent = static_cast<RoomMemberEvent*>(event);
// Can't use d->member() below because the user may be not a member (yet)
@@ -939,9 +970,13 @@ void Room::Private::updateDisplayname()
emit q->displaynameChanged(q);
}
-QJsonObject stateEventToJson(const QString& type, const QString& name,
- const QJsonValue& content)
+template <typename T>
+void appendEventJson(QJsonArray& events, const QString& type,
+ const QString& name, const T& content)
{
+ if (content.isEmpty())
+ return;
+
QJsonObject contentObj;
contentObj.insert(name, content);
@@ -949,7 +984,7 @@ QJsonObject stateEventToJson(const QString& type, const QString& name,
eventObj.insert("type", type);
eventObj.insert("content", contentObj);
- return eventObj;
+ events.append(eventObj);
}
QJsonObject Room::Private::toJson() const
@@ -958,12 +993,14 @@ QJsonObject Room::Private::toJson() const
{
QJsonArray stateEvents;
- stateEvents.append(stateEventToJson("m.room.name", "name", name));
- stateEvents.append(stateEventToJson("m.room.topic", "topic", topic));
- stateEvents.append(stateEventToJson("m.room.aliases", "aliases",
- QJsonArray::fromStringList(aliases)));
- stateEvents.append(stateEventToJson("m.room.canonical_alias", "alias",
- canonicalAlias));
+ appendEventJson(stateEvents, "m.room.name", "name", name);
+ appendEventJson(stateEvents, "m.room.topic", "topic", topic);
+ appendEventJson(stateEvents, "m.room.avatar", "avatar_url",
+ avatar.url().toString());
+ appendEventJson(stateEvents, "m.room.aliases", "aliases",
+ QJsonArray::fromStringList(aliases));
+ appendEventJson(stateEvents, "m.room.canonical_alias", "alias",
+ canonicalAlias);
for (const auto &i : membersMap)
{
diff --git a/room.h b/room.h
index 2d0453bc..2fa7e7d5 100644
--- a/room.h
+++ b/room.h
@@ -25,6 +25,7 @@
#include <QtCore/QStringList>
#include <QtCore/QObject>
#include <QtCore/QJsonObject>
+#include <QtGui/QPixmap>
#include "jobs/syncjob.h"
#include "events/roommessageevent.h"
@@ -79,7 +80,7 @@ namespace QMatrixClient
using rev_iter_t = Timeline::const_reverse_iterator;
Room(Connection* connection, QString id, JoinState initialJoinState);
- virtual ~Room();
+ ~Room() override;
Connection* connection() const;
User* localUser() const;
@@ -98,6 +99,12 @@ namespace QMatrixClient
Q_INVOKABLE int memberCount() const;
/**
+ * Returns a room avatar and requests it from the network if needed
+ * @return a pixmap with the avatar or a placeholder if there's none
+ * available yet
+ */
+ Q_INVOKABLE QPixmap avatar(int width, int height);
+ /**
* @brief Produces a disambiguated name for a given user in
* the context of the room
*/
@@ -181,6 +188,7 @@ namespace QMatrixClient
/** @brief The room displayname changed */
void displaynameChanged(Room* room);
void topicChanged();
+ void avatarChanged();
void userAdded(User* user);
void userRemoved(User* user);
void memberRenamed(User* user);
diff --git a/user.cpp b/user.cpp
index b2c0dc1e..8c8a7fdb 100644
--- a/user.cpp
+++ b/user.cpp
@@ -90,6 +90,11 @@ QString User::bridged() const {
return d->bridged;
}
+Avatar& User::avatarObject()
+{
+ return d->avatar;
+}
+
QPixmap User::avatar(int width, int height)
{
return d->avatar.get(width, height, [=] { emit avatarChanged(this); });
diff --git a/user.h b/user.h
index aee6ec3e..148ed64d 100644
--- a/user.h
+++ b/user.h
@@ -20,6 +20,7 @@
#include <QtCore/QString>
#include <QtCore/QObject>
+#include "avatar.h"
namespace QMatrixClient
{
@@ -52,6 +53,7 @@ namespace QMatrixClient
*/
Q_INVOKABLE QString bridged() const;
+ Avatar& avatarObject();
QPixmap avatar(int requestedWidth, int requestedHeight);
QUrl avatarUrl() const;