Add avatar support.

square-messages
Black Hat 2018-03-02 16:56:36 +08:00
parent 6a610e3808
commit d4c2a1ed50
10 changed files with 148 additions and 52 deletions

View File

@ -1,9 +1,12 @@
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QNetworkProxy>
#include <QQmlContext>
#include "matrix/controller.h"
#include "matrix/roomlistmodel.h"
#include "matrix/imageprovider.h"
using namespace QMatrixClient;
int main(int argc, char *argv[])
@ -25,6 +28,13 @@ int main(int argc, char *argv[])
qmlRegisterType<RoomListModel>("Matrique", 0, 1, "RoomListModel");
QQmlApplicationEngine engine;
Connection* m_connection = new Connection();
ImageProvider* m_provider = new ImageProvider();
m_provider->setConnection(m_connection);
engine.rootContext()->setContextProperty("m_connection", m_connection);
engine.addImageProvider(QLatin1String("mxc"), m_provider);
engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;

View File

@ -16,7 +16,8 @@ DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += main.cpp \
matrix/controller.cpp \
matrix/roomlistmodel.cpp
matrix/roomlistmodel.cpp \
matrix/imageprovider.cpp
RESOURCES += \
res.qrc
@ -48,4 +49,5 @@ DISTFILES += \
HEADERS += \
matrix/controller.h \
matrix/roomlistmodel.h
matrix/roomlistmodel.h \
matrix/imageprovider.h

View File

@ -3,10 +3,7 @@
#include "libqmatrixclient/connection.h"
Controller::Controller(QObject *parent) : QObject(parent) {
connect(m_connection, &QMatrixClient::Connection::connected, this, &Controller::connected);
connect(m_connection, &QMatrixClient::Connection::resolveError, this, &Controller::reconnect);
connect(m_connection, &QMatrixClient::Connection::syncError, this, &Controller::reconnect);
connect(m_connection, &QMatrixClient::Connection::syncDone, this, &Controller::resync);
}
Controller::~Controller() {
@ -31,6 +28,18 @@ void Controller::login(QString home, QString user, QString pass) {
}
}
void Controller::setConnection(QMatrixClient::Connection* conn) {
qDebug() << "Setting controller connection.";
m_connection = conn;
roomListModel = new RoomListModel(m_connection);
emit roomListModelChanged();
connect(m_connection, &QMatrixClient::Connection::connected, this, &Controller::connected);
connect(m_connection, &QMatrixClient::Connection::resolveError, this, &Controller::reconnect);
connect(m_connection, &QMatrixClient::Connection::syncError, this, &Controller::reconnect);
connect(m_connection, &QMatrixClient::Connection::syncDone, this, &Controller::resync);
emit connectionChanged();
}
void Controller::logout() {
userID = "";
token = "";

View File

@ -15,13 +15,11 @@ class Controller : public QObject
Q_OBJECT
Q_PROPERTY(RoomListModel *roomListModel READ getRoomListModel NOTIFY roomListModelChanged)
Q_PROPERTY(QMatrixClient::Connection *connection READ getConnection WRITE setConnection NOTIFY connectionChanged)
Q_PROPERTY(bool isLogin READ getIsLogin WRITE setIsLogin NOTIFY isLoginChanged)
Q_PROPERTY(QString userID READ getUserID WRITE setUserID NOTIFY userIDChanged)
Q_PROPERTY(QByteArray token READ getToken WRITE setToken NOTIFY tokenChanged)
private:
QMatrixClient::Connection* m_connection = new QMatrixClient::Connection();
public:
explicit Controller(QObject *parent = nullptr);
~Controller();
@ -33,9 +31,13 @@ public:
// All the non-Q_INVOKABLE functions.
// All the Q_PROPERTYs.
RoomListModel* roomListModel = new RoomListModel(m_connection);
RoomListModel* roomListModel;
RoomListModel* getRoomListModel() { return roomListModel; }
QMatrixClient::Connection* m_connection;
QMatrixClient::Connection* getConnection() { return m_connection; }
void setConnection(QMatrixClient::Connection* conn);
bool isLogin = false;
bool getIsLogin() { return isLogin; }
void setIsLogin(bool n) {
@ -70,6 +72,7 @@ private:
signals:
void roomListModelChanged();
void connectionChanged();
void isLoginChanged();
void userIDChanged();
void tokenChanged();

71
matrix/imageprovider.cpp Normal file
View File

@ -0,0 +1,71 @@
#include "imageprovider.h"
#include "connection.h"
#include "jobs/mediathumbnailjob.h"
#include <QtCore/QWaitCondition>
#include <QtCore/QDebug>
#include <QMetaObject>
using QMatrixClient::MediaThumbnailJob;
ImageProvider::ImageProvider(QObject *parent)
: QQuickImageProvider(QQmlImageProviderBase::Image,
QQmlImageProviderBase::ForceAsynchronousImageLoading)
{
#if (QT_VERSION < QT_VERSION_CHECK(5, 10, 0))
qRegisterMetaType<MediaThumbnailJob*>();
#endif
}
QImage ImageProvider::requestImage(const QString& id,
QSize* pSize, const QSize& requestedSize)
{
if (!id.startsWith("mxc://"))
{
qWarning() << "ImageProvider: won't fetch an invalid id:" << id
<< "doesn't follow server/mediaId pattern";
return {};
}
QUrl mxcUri { id };
qDebug() << "ImageProvider::requestImage:" << mxcUri.toString();
MediaThumbnailJob* job = nullptr;
QReadLocker locker(&m_lock);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
QMetaObject::invokeMethod(m_connection,
[=] { return m_connection->getThumbnail(mxcUri, requestedSize); },
Qt::BlockingQueuedConnection, &job);
#else
QMetaObject::invokeMethod(m_connection, "getThumbnail",
Qt::BlockingQueuedConnection, Q_RETURN_ARG(MediaThumbnailJob*, job),
Q_ARG(QUrl, mxcUri), Q_ARG(QSize, requestedSize));
#endif
if (!job)
{
qDebug() << "ImageProvider: failed to send a request";
return {};
}
QImage result;
{
QWaitCondition condition; // The most compact way to block on a signal
job->connect(job, &MediaThumbnailJob::finished, job, [&] {
result = job->thumbnail();
condition.wakeAll();
});
condition.wait(&m_lock);
}
if( pSize != nullptr )
*pSize = result.size();
return result;
}
void ImageProvider::setConnection(QMatrixClient::Connection* connection)
{
QWriteLocker locker(&m_lock);
m_connection = connection;
}

28
matrix/imageprovider.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef IMAGEPROVIDER_H
#define IMAGEPROVIDER_H
#include <QtQuick/QQuickImageProvider>
#include <QtCore/QReadWriteLock>
namespace QMatrixClient {
class Connection;
}
class ImageProvider: public QQuickImageProvider
{
public:
explicit ImageProvider(QObject *parent = nullptr);
QImage requestImage(const QString& id, QSize* pSize,
const QSize& requestedSize) override;
void setConnection(QMatrixClient::Connection* connection);
void initializeEngine(QQmlEngine *engine, const char *uri);
private:
QMatrixClient::Connection* m_connection;
QReadWriteLock m_lock;
};
#endif // IMAGEPROVIDER_H

View File

@ -53,8 +53,8 @@ QVariant RoomListModel::data(const QModelIndex& index, int role) const {
if(role == ValueRole) {
return room->topic();
}
if(role == IconRole) {
return room->avatar(48);
if(role == AvatarRole) {
return room->avatarUrl();
}
return QVariant();
}
@ -63,7 +63,7 @@ QHash<int, QByteArray> RoomListModel::roleNames() const {
QHash<int, QByteArray> roles;
roles[NameRole] = "name";
roles[ValueRole] = "value";
roles[IconRole] = "icon";
roles[AvatarRole] = "avatar";
return roles;
}
@ -75,8 +75,3 @@ void RoomListModel::namesChanged(QMatrixClient::Room* room) {
void RoomListModel::unreadMessagesChanged(QMatrixClient::Room* room) {
}
RoomModel::RoomModel(QString name, QString value) {
m_name = name;
m_value = value;
}

View File

@ -12,28 +12,6 @@ namespace QMatrixClient {
class Room;
}
class RoomModel : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ getName)
Q_PROPERTY(QString value READ getValue)
public:
explicit RoomModel(QString name, QString value);
QString getName() { return m_name; }
QString getValue() { return m_value; }
signals:
void nameChanged();
void valueChanged();
private:
QString m_name;
QString m_value;
};
class RoomListModel : public QAbstractListModel
{
Q_OBJECT
@ -43,7 +21,7 @@ public:
~RoomListModel();
enum RoomModelRoles {
NameRole, ValueRole, IconRole
NameRole, ValueRole, AvatarRole
};
QHash<int, QByteArray> roleNames() const;

View File

@ -81,6 +81,7 @@ Item {
Text {
z: 10
text: "Here? No, not here."
color: "#424242"
anchors.centerIn: parent
visible: listView.count === 0
}
@ -113,7 +114,7 @@ Item {
ImageStatus {
width: parent.height
height: parent.height
source: "qrc:/asset/img/avatar.png"
source: "image://mxc/" + avatar
}
Column {

View File

@ -18,17 +18,16 @@ ApplicationWindow {
title: qsTr("Matrique")
Controller {
id: controller
onIsLoginChanged: console.log("Status:", isLogin)
id: matrixController
connection: m_connection
}
Settings {
id: settings
// Settings {
// id: settings
property alias userID: controller.userID
property alias token: controller.token
}
// property var userID
// property var token
// }
FontLoader { id: materialFont; source: "qrc:/asset/font/material.ttf" }
@ -51,7 +50,7 @@ ApplicationWindow {
page: Room {
id: roomPage
roomListModel: controller.roomListModel
roomListModel: matrixController.roomListModel//BUG: It will cause random crash as roomListModel may not be initialized.
}
}
@ -72,7 +71,7 @@ ApplicationWindow {
page: Login {
id: loginPage
controller: controller
controller: matrixController
}
}