aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--avatar.cpp80
-rw-r--r--avatar.h57
-rw-r--r--user.cpp93
-rw-r--r--user.h5
5 files changed, 152 insertions, 84 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0395774a..fc3276c9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -60,6 +60,7 @@ set(libqmatrixclient_SRCS
logging.cpp
room.cpp
user.cpp
+ avatar.cpp
settings.cpp
events/event.cpp
events/eventcontent.cpp
diff --git a/avatar.cpp b/avatar.cpp
new file mode 100644
index 00000000..0ce9210b
--- /dev/null
+++ b/avatar.cpp
@@ -0,0 +1,80 @@
+/******************************************************************************
+ * 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 "avatar.h"
+
+#include "jobs/mediathumbnailjob.h"
+#include "events/eventcontent.h"
+#include "connection.h"
+
+using namespace QMatrixClient;
+
+QPixmap Avatar::get(int width, int height, std::function<void()> continuation)
+{
+ QSize size(width, height);
+
+ // FIXME: Alternating between longer-width and longer-height requests
+ // is a sure way to trick the below code into constantly getting another
+ // image from the server because the existing one is alleged unsatisfactory.
+ // This is plain abuse by the client, though; so not critical for now.
+ if( (!_valid && _url.isValid() && !_ongoingRequest)
+ || width > _requestedSize.width()
+ || height > _requestedSize.height() )
+ {
+ qCDebug(MAIN) << "Getting avatar from" << _url.toString();
+ _requestedSize = size;
+ _ongoingRequest = _connection->callApi<MediaThumbnailJob>(_url, size);
+ _ongoingRequest->connect( _ongoingRequest, &MediaThumbnailJob::finished,
+ _connection, [=]() {
+ if (_ongoingRequest->status().good())
+ {
+ _valid = true;
+ _originalPixmap = _ongoingRequest->scaledThumbnail(_requestedSize);
+ _scaledPixmaps.clear();
+ continuation();
+ }
+ _ongoingRequest = nullptr;
+ });
+ }
+
+ if( _originalPixmap.isNull() )
+ {
+ if (_defaultIcon.isNull())
+ return _originalPixmap;
+
+ _originalPixmap = _defaultIcon.pixmap(size);
+ }
+
+ auto& pixmap = _scaledPixmaps[{width, height}]; // Create if needed
+ if (pixmap.isNull())
+ {
+ pixmap = _originalPixmap.scaled(size,
+ Qt::KeepAspectRatio, Qt::SmoothTransformation);
+ }
+ return pixmap;
+}
+
+bool Avatar::updateUrl(const QUrl& newUrl)
+{
+ if (newUrl == _url)
+ return false;
+
+ _url = newUrl;
+ _valid = false;
+ return true;
+}
diff --git a/avatar.h b/avatar.h
new file mode 100644
index 00000000..6889e839
--- /dev/null
+++ b/avatar.h
@@ -0,0 +1,57 @@
+/******************************************************************************
+ * 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 <QtGui/QIcon>
+#include <QtCore/QUrl>
+
+#include <functional>
+
+namespace QMatrixClient
+{
+ class MediaThumbnailJob;
+ class Connection;
+
+ class Avatar
+ {
+ public:
+ explicit Avatar(Connection* connection, QIcon defaultIcon = {})
+ : _defaultIcon(std::move(defaultIcon)), _connection(connection)
+ { }
+
+ QPixmap get(int w, int h, std::function<void()> continuation);
+
+ QUrl url() const { return _url; }
+ bool updateUrl(const QUrl& newUrl);
+
+ private:
+ QUrl _url;
+ QPixmap _originalPixmap;
+ QIcon _defaultIcon;
+
+ /// Map of requested size to the actual pixmap used for it
+ /// (it's a shame that QSize has no predefined qHash()).
+ QHash<QPair<int,int>, QPixmap> _scaledPixmaps;
+
+ QSize _requestedSize;
+ bool _valid = false;
+ Connection* _connection;
+ MediaThumbnailJob* _ongoingRequest = nullptr;
+ };
+} // namespace QMatrixClient
diff --git a/user.cpp b/user.cpp
index aa1aa447..b2c0dc1e 100644
--- a/user.cpp
+++ b/user.cpp
@@ -19,14 +19,12 @@
#include "user.h"
#include "connection.h"
+#include "avatar.h"
#include "events/event.h"
#include "events/roommemberevent.h"
-#include "jobs/mediathumbnailjob.h"
#include "jobs/generated/profile.h"
#include <QtCore/QTimer>
-#include <QtCore/QDebug>
-#include <QtGui/QIcon>
#include <QtCore/QRegularExpression>
using namespace QMatrixClient;
@@ -35,35 +33,20 @@ class User::Private
{
public:
Private(QString userId, Connection* connection)
- : q(nullptr), userId(std::move(userId)), connection(connection)
- , defaultIcon(QIcon::fromTheme(QStringLiteral("user-available")))
- , avatarValid(false) , avatarOngoingRequest(false)
+ : userId(std::move(userId)), connection(connection)
+ , avatar(connection, QIcon::fromTheme(QStringLiteral("user-available")))
{ }
- User* q;
QString userId;
QString name;
- QUrl avatarUrl;
- Connection* connection;
-
- QPixmap avatar;
- QIcon defaultIcon;
- QSize requestedSize;
- bool avatarValid;
- bool avatarOngoingRequest;
- /// Map of requested size to the actual pixmap used for it
- /// (it's a shame that QSize has no predefined qHash()).
- QHash<QPair<int,int>, QPixmap> scaledAvatars;
QString bridged;
-
- void requestAvatar();
+ Connection* connection;
+ Avatar avatar;
};
User::User(QString userId, Connection* connection)
- : QObject(connection), d(new Private(userId, connection))
-{
- d->q = this; // Initialization finished
-}
+ : QObject(connection), d(new Private(std::move(userId), connection))
+{ }
User::~User()
{
@@ -109,43 +92,12 @@ QString User::bridged() const {
QPixmap User::avatar(int width, int height)
{
- QSize size(width, height);
-
- // FIXME: Alternating between longer-width and longer-height requests
- // is a sure way to trick the below code into constantly getting another
- // image from the server because the existing one is alleged unsatisfactory.
- // This is plain abuse by the client, though; so not critical for now.
- if( (!d->avatarValid && d->avatarUrl.isValid() && !d->avatarOngoingRequest)
- || width > d->requestedSize.width()
- || height > d->requestedSize.height() )
- {
- qCDebug(MAIN) << "Getting avatar for" << id()
- << "from" << d->avatarUrl.toString();
- d->requestedSize = size;
- d->avatarOngoingRequest = true;
- QTimer::singleShot(0, this, SLOT(requestAvatar()));
- }
-
- if( d->avatar.isNull() )
- {
- if (d->defaultIcon.isNull())
- return d->avatar;
-
- d->avatar = d->defaultIcon.pixmap(size);
- }
-
- auto& pixmap = d->scaledAvatars[{width, height}]; // Create the entry if needed
- if (pixmap.isNull())
- {
- pixmap = d->avatar.scaled(width, height,
- Qt::KeepAspectRatio, Qt::SmoothTransformation);
- }
- return pixmap;
+ return d->avatar.get(width, height, [=] { emit avatarChanged(this); });
}
-const QUrl& User::avatarUrl() const
+QUrl User::avatarUrl() const
{
- return d->avatarUrl;
+ return d->avatar.url();
}
void User::processEvent(Event* event)
@@ -165,28 +117,7 @@ void User::processEvent(Event* event)
newName.truncate(match.capturedStart(0));
}
updateName(newName);
- if( d->avatarUrl != e->avatarUrl() )
- {
- d->avatarUrl = e->avatarUrl();
- d->avatarValid = false;
- }
+ if (d->avatar.updateUrl(e->avatarUrl()))
+ emit avatarChanged(this);
}
}
-
-void User::requestAvatar()
-{
- d->requestAvatar();
-}
-
-void User::Private::requestAvatar()
-{
- auto* job = connection->callApi<MediaThumbnailJob>(avatarUrl, requestedSize);
- connect( job, &MediaThumbnailJob::success, [=]() {
- avatarOngoingRequest = false;
- avatarValid = true;
- avatar = job->scaledThumbnail(requestedSize);
- scaledAvatars.clear();
- emit q->avatarChanged(q);
- });
-}
-
diff --git a/user.h b/user.h
index 79a6f5db..aee6ec3e 100644
--- a/user.h
+++ b/user.h
@@ -30,7 +30,7 @@ namespace QMatrixClient
Q_OBJECT
public:
User(QString userId, Connection* connection);
- virtual ~User();
+ ~User() override;
/**
* Returns the id of the user
@@ -54,12 +54,11 @@ namespace QMatrixClient
QPixmap avatar(int requestedWidth, int requestedHeight);
- const QUrl& avatarUrl() const;
+ QUrl avatarUrl() const;
void processEvent(Event* event);
public slots:
- void requestAvatar();
void rename(const QString& newName);
signals: