Code reformatting && tooltip.
This commit is contained in:
parent
d6b5cba61f
commit
6bd059ce63
52
main.cpp
52
main.cpp
|
@ -1,50 +1,50 @@
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
#include <QQmlApplicationEngine>
|
|
||||||
#include <QNetworkProxy>
|
#include <QNetworkProxy>
|
||||||
|
#include <QQmlApplicationEngine>
|
||||||
#include <QQmlContext>
|
#include <QQmlContext>
|
||||||
|
|
||||||
#include "room.h"
|
|
||||||
#include "matrix/controller.h"
|
#include "matrix/controller.h"
|
||||||
#include "matrix/roomlistmodel.h"
|
|
||||||
#include "matrix/imageprovider.h"
|
#include "matrix/imageprovider.h"
|
||||||
#include "matrix/messageeventmodel.h"
|
#include "matrix/messageeventmodel.h"
|
||||||
|
#include "matrix/roomlistmodel.h"
|
||||||
|
#include "room.h"
|
||||||
|
|
||||||
using namespace QMatrixClient;
|
using namespace QMatrixClient;
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[]) {
|
||||||
{
|
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QGuiApplication app(argc, argv);
|
QGuiApplication app(argc, argv);
|
||||||
|
|
||||||
// Enable this if you need proxy.
|
// Enable this if you need proxy.
|
||||||
// QNetworkProxy proxy;
|
// QNetworkProxy proxy;
|
||||||
// proxy.setType(QNetworkProxy::HttpProxy);
|
// proxy.setType(QNetworkProxy::HttpProxy);
|
||||||
// proxy.setHostName("localhost");
|
// proxy.setHostName("localhost");
|
||||||
// proxy.setPort(1082);
|
// proxy.setPort(1082);
|
||||||
// QNetworkProxy::setApplicationProxy(proxy);
|
// QNetworkProxy::setApplicationProxy(proxy);
|
||||||
|
|
||||||
qmlRegisterType<Room>(); qRegisterMetaType<Room*> ("Room*");
|
qmlRegisterType<Room>();
|
||||||
|
qRegisterMetaType<Room *>("Room*");
|
||||||
|
|
||||||
qmlRegisterType<Controller>("Matrique", 0, 1, "Controller");
|
qmlRegisterType<Controller>("Matrique", 0, 1, "Controller");
|
||||||
qmlRegisterType<RoomListModel>("Matrique", 0, 1, "RoomListModel");
|
qmlRegisterType<RoomListModel>("Matrique", 0, 1, "RoomListModel");
|
||||||
qmlRegisterType<MessageEventModel>("Matrique", 0, 1, "MessageEventModel");
|
qmlRegisterType<MessageEventModel>("Matrique", 0, 1, "MessageEventModel");
|
||||||
qRegisterMetaType<User*>("User*");
|
qRegisterMetaType<User *>("User*");
|
||||||
|
|
||||||
QQmlApplicationEngine engine;
|
QQmlApplicationEngine engine;
|
||||||
|
|
||||||
ImageProvider* m_provider = new ImageProvider();
|
ImageProvider *m_provider = new ImageProvider();
|
||||||
|
|
||||||
engine.rootContext()->setContextProperty("imageProvider", m_provider->getConnection());
|
engine.rootContext()->setContextProperty("imageProvider",
|
||||||
|
m_provider->getConnection());
|
||||||
|
|
||||||
engine.addImageProvider(QLatin1String("mxc"), m_provider);
|
engine.addImageProvider(QLatin1String("mxc"), m_provider);
|
||||||
|
|
||||||
engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));
|
engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));
|
||||||
|
|
||||||
if (engine.rootObjects().isEmpty())
|
if (engine.rootObjects().isEmpty()) return -1;
|
||||||
return -1;
|
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,67 +3,71 @@
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
|
|
||||||
Controller::Controller(QObject *parent) : QObject(parent) {
|
Controller::Controller(QObject *parent) : QObject(parent) {
|
||||||
connect(m_connection, &QMatrixClient::Connection::connected, this, &Controller::connected);
|
connect(m_connection, &QMatrixClient::Connection::connected, this,
|
||||||
connect(m_connection, &QMatrixClient::Connection::resolveError, this, &Controller::reconnect);
|
&Controller::connected);
|
||||||
connect(m_connection, &QMatrixClient::Connection::syncError, this, &Controller::reconnect);
|
connect(m_connection, &QMatrixClient::Connection::resolveError, this,
|
||||||
connect(m_connection, &QMatrixClient::Connection::syncDone, this, &Controller::resync);
|
&Controller::reconnect);
|
||||||
connect(m_connection, &QMatrixClient::Connection::connected, this, &Controller::connectionChanged);
|
connect(m_connection, &QMatrixClient::Connection::syncError, this,
|
||||||
|
&Controller::reconnect);
|
||||||
|
connect(m_connection, &QMatrixClient::Connection::syncDone, this,
|
||||||
|
&Controller::resync);
|
||||||
|
connect(m_connection, &QMatrixClient::Connection::connected, this,
|
||||||
|
&Controller::connectionChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller::~Controller() {
|
Controller::~Controller() { m_connection->stopSync(); }
|
||||||
m_connection->stopSync();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Controller::login() {
|
void Controller::login() {
|
||||||
if (!isLogin) {
|
if (!isLogin) {
|
||||||
qDebug() << "UserID:" << userID;
|
qDebug() << "UserID:" << userID;
|
||||||
qDebug() << "Token:" << token;
|
qDebug() << "Token:" << token;
|
||||||
|
|
||||||
m_connection->setHomeserver(QUrl(homeserver));
|
m_connection->setHomeserver(QUrl(homeserver));
|
||||||
m_connection->connectWithToken(userID, token, "");
|
m_connection->connectWithToken(userID, token, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::loginWithCredentials(QString serverAddr, QString user, QString pass) {
|
void Controller::loginWithCredentials(QString serverAddr, QString user,
|
||||||
if(!isLogin) {
|
QString pass) {
|
||||||
qDebug() << "Server:" << serverAddr;
|
if (!isLogin) {
|
||||||
qDebug() << "User:" << user;
|
qDebug() << "Server:" << serverAddr;
|
||||||
qDebug() << "Pass:" << pass;
|
qDebug() << "User:" << user;
|
||||||
|
qDebug() << "Pass:" << pass;
|
||||||
|
|
||||||
if(!user.isEmpty() && !pass.isEmpty()) {
|
if (!user.isEmpty() && !pass.isEmpty()) {
|
||||||
qDebug() << "Using given credential.";
|
qDebug() << "Using given credential.";
|
||||||
m_connection->setHomeserver(QUrl(serverAddr));
|
m_connection->setHomeserver(QUrl(serverAddr));
|
||||||
m_connection->connectToServer(user, pass, "");
|
m_connection->connectToServer(user, pass, "");
|
||||||
}
|
|
||||||
} else {
|
|
||||||
qDebug() << "You are already logged in.";
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
qDebug() << "You are already logged in.";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::logout() {
|
void Controller::logout() {
|
||||||
qDebug() << "Logging out.";
|
qDebug() << "Logging out.";
|
||||||
setUserID("");
|
setUserID("");
|
||||||
setToken("");
|
setToken("");
|
||||||
setIsLogin(false);
|
setIsLogin(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::connected() {
|
void Controller::connected() {
|
||||||
qDebug() << "Logged in.";
|
qDebug() << "Logged in.";
|
||||||
setHomeserver(m_connection->homeserver().toString());
|
setHomeserver(m_connection->homeserver().toString());
|
||||||
setUserID(m_connection->userId());
|
setUserID(m_connection->userId());
|
||||||
setToken(m_connection->accessToken());
|
setToken(m_connection->accessToken());
|
||||||
m_connection->loadState();
|
m_connection->loadState();
|
||||||
resync();
|
resync();
|
||||||
setIsLogin(true);
|
setIsLogin(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::resync() {
|
void Controller::resync() {
|
||||||
qDebug() << "Syncing Matrix.";
|
qDebug() << "Syncing Matrix.";
|
||||||
m_connection->sync(30000);
|
m_connection->sync(30000);
|
||||||
m_connection->saveState();
|
m_connection->saveState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::reconnect() {
|
void Controller::reconnect() {
|
||||||
qDebug() << "Connection lost. Reconnecting...";
|
qDebug() << "Connection lost. Reconnecting...";
|
||||||
m_connection->connectWithToken(userID, token, "");
|
m_connection->connectWithToken(userID, token, "");
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,99 +3,101 @@
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
#include "user.h"
|
|
||||||
#include "roomlistmodel.h"
|
#include "roomlistmodel.h"
|
||||||
|
#include "user.h"
|
||||||
|
|
||||||
namespace QMatrixClient {
|
namespace QMatrixClient {
|
||||||
class Connection;
|
class Connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Controller : public QObject
|
class Controller : public QObject {
|
||||||
{
|
Q_OBJECT
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
Q_PROPERTY(QMatrixClient::Connection* connection READ getConnection NOTIFY connectionChanged)
|
Q_PROPERTY(QMatrixClient::Connection* connection READ getConnection NOTIFY
|
||||||
Q_PROPERTY(bool isLogin READ getIsLogin WRITE setIsLogin NOTIFY isLoginChanged)
|
connectionChanged)
|
||||||
Q_PROPERTY(QString homeserver READ getHomeserver WRITE setHomeserver NOTIFY homeserverChanged)
|
Q_PROPERTY(
|
||||||
Q_PROPERTY(QString userID READ getUserID WRITE setUserID NOTIFY userIDChanged)
|
bool isLogin READ getIsLogin WRITE setIsLogin NOTIFY isLoginChanged)
|
||||||
Q_PROPERTY(QByteArray token READ getToken WRITE setToken NOTIFY tokenChanged)
|
Q_PROPERTY(QString homeserver READ getHomeserver WRITE setHomeserver NOTIFY
|
||||||
Q_PROPERTY(bool busy READ getBusy WRITE setBusy NOTIFY busyChanged)
|
homeserverChanged)
|
||||||
|
Q_PROPERTY(QString userID READ getUserID WRITE setUserID NOTIFY userIDChanged)
|
||||||
|
Q_PROPERTY(QByteArray token READ getToken WRITE setToken NOTIFY tokenChanged)
|
||||||
|
Q_PROPERTY(bool busy READ getBusy WRITE setBusy NOTIFY busyChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Controller(QObject *parent = nullptr);
|
explicit Controller(QObject* parent = nullptr);
|
||||||
~Controller();
|
~Controller();
|
||||||
|
|
||||||
// All the Q_INVOKABLEs.
|
// All the Q_INVOKABLEs.
|
||||||
Q_INVOKABLE void login();
|
Q_INVOKABLE void login();
|
||||||
Q_INVOKABLE void loginWithCredentials(QString, QString, QString);
|
Q_INVOKABLE void loginWithCredentials(QString, QString, QString);
|
||||||
Q_INVOKABLE void logout();
|
Q_INVOKABLE void logout();
|
||||||
|
|
||||||
// All the non-Q_INVOKABLE functions.
|
// All the non-Q_INVOKABLE functions.
|
||||||
|
|
||||||
// All the Q_PROPERTYs.
|
// All the Q_PROPERTYs.
|
||||||
QMatrixClient::Connection* m_connection = new QMatrixClient::Connection();
|
QMatrixClient::Connection* m_connection = new QMatrixClient::Connection();
|
||||||
QMatrixClient::Connection* getConnection() { return m_connection; }
|
QMatrixClient::Connection* getConnection() { return m_connection; }
|
||||||
|
|
||||||
bool isLogin = false;
|
bool isLogin = false;
|
||||||
bool getIsLogin() { return isLogin; }
|
bool getIsLogin() { return isLogin; }
|
||||||
void setIsLogin(bool n) {
|
void setIsLogin(bool n) {
|
||||||
if(n != isLogin) {
|
if (n != isLogin) {
|
||||||
isLogin = n;
|
isLogin = n;
|
||||||
emit isLoginChanged();
|
emit isLoginChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString userID;
|
QString userID;
|
||||||
QString getUserID() { return userID; }
|
QString getUserID() { return userID; }
|
||||||
void setUserID(QString n) {
|
void setUserID(QString n) {
|
||||||
if(n != userID) {
|
if (n != userID) {
|
||||||
userID = n;
|
userID = n;
|
||||||
emit userIDChanged();
|
emit userIDChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray token;
|
QByteArray token;
|
||||||
QByteArray getToken() { return token; }
|
QByteArray getToken() { return token; }
|
||||||
void setToken(QByteArray n) {
|
void setToken(QByteArray n) {
|
||||||
if(n != token) {
|
if (n != token) {
|
||||||
token = n;
|
token = n;
|
||||||
emit tokenChanged();
|
emit tokenChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString homeserver;
|
QString homeserver;
|
||||||
QString getHomeserver() { return homeserver; }
|
QString getHomeserver() { return homeserver; }
|
||||||
void setHomeserver(QString n) {
|
void setHomeserver(QString n) {
|
||||||
if (n != homeserver) {
|
if (n != homeserver) {
|
||||||
homeserver = n;
|
homeserver = n;
|
||||||
emit homeserverChanged();
|
emit homeserverChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool busy = false;
|
bool busy = false;
|
||||||
bool getBusy() { return busy; }
|
bool getBusy() { return busy; }
|
||||||
void setBusy(bool b) {
|
void setBusy(bool b) {
|
||||||
if (b != busy) {
|
if (b != busy) {
|
||||||
busy = b;
|
busy = b;
|
||||||
emit busyChanged();
|
emit busyChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void connected();
|
void connected();
|
||||||
void resync();
|
void resync();
|
||||||
void reconnect();
|
void reconnect();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void connectionChanged();
|
void connectionChanged();
|
||||||
void isLoginChanged();
|
void isLoginChanged();
|
||||||
void userIDChanged();
|
void userIDChanged();
|
||||||
void tokenChanged();
|
void tokenChanged();
|
||||||
void homeserverChanged();
|
void homeserverChanged();
|
||||||
void busyChanged();
|
void busyChanged();
|
||||||
void errorOccured();
|
void errorOccured();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CONTROLLER_H
|
#endif // CONTROLLER_H
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#include "imageprovider.h"
|
#include "imageprovider.h"
|
||||||
|
|
||||||
#include <QtCore/QWaitCondition>
|
|
||||||
#include <QtCore/QDebug>
|
|
||||||
#include <QMetaObject>
|
#include <QMetaObject>
|
||||||
|
#include <QtCore/QDebug>
|
||||||
|
#include <QtCore/QWaitCondition>
|
||||||
|
|
||||||
#include "jobs/mediathumbnailjob.h"
|
#include "jobs/mediathumbnailjob.h"
|
||||||
|
|
||||||
|
@ -11,58 +11,57 @@
|
||||||
using QMatrixClient::MediaThumbnailJob;
|
using QMatrixClient::MediaThumbnailJob;
|
||||||
|
|
||||||
ImageProvider::ImageProvider(QObject* parent)
|
ImageProvider::ImageProvider(QObject* parent)
|
||||||
: QQuickImageProvider(QQmlImageProviderBase::Image,
|
: QQuickImageProvider(
|
||||||
QQmlImageProviderBase::ForceAsynchronousImageLoading)
|
QQmlImageProviderBase::Image,
|
||||||
{
|
QQmlImageProviderBase::ForceAsynchronousImageLoading) {
|
||||||
#if (QT_VERSION < QT_VERSION_CHECK(5, 10, 0))
|
#if (QT_VERSION < QT_VERSION_CHECK(5, 10, 0))
|
||||||
qRegisterMetaType<MediaThumbnailJob*>();
|
qRegisterMetaType<MediaThumbnailJob*>();
|
||||||
#endif
|
#endif
|
||||||
m_connection = new ImageProviderConnection();
|
m_connection = new ImageProviderConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
QImage ImageProvider::requestImage(const QString& id,
|
QImage ImageProvider::requestImage(const QString& id, QSize* pSize,
|
||||||
QSize* pSize, const QSize& requestedSize)
|
const QSize& requestedSize) {
|
||||||
{
|
if (!id.startsWith("mxc://")) {
|
||||||
if (!id.startsWith("mxc://"))
|
qWarning() << "ImageProvider: won't fetch an invalid id:" << id
|
||||||
{
|
<< "doesn't follow server/mediaId pattern";
|
||||||
qWarning() << "ImageProvider: won't fetch an invalid id:" << id
|
return {};
|
||||||
<< "doesn't follow server/mediaId pattern";
|
}
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
QUrl mxcUri { id };
|
QUrl mxcUri{id};
|
||||||
qDebug() << "ImageProvider::requestImage:" << mxcUri.toString();
|
|
||||||
|
|
||||||
MediaThumbnailJob* job = nullptr;
|
MediaThumbnailJob* job = nullptr;
|
||||||
QReadLocker locker(&m_lock);
|
QReadLocker locker(&m_lock);
|
||||||
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
|
||||||
QMetaObject::invokeMethod(m_connection,
|
QMetaObject::invokeMethod(
|
||||||
[=] { return m_connection->getConnection()->getThumbnail(mxcUri, requestedSize); },
|
m_connection,
|
||||||
Qt::BlockingQueuedConnection, &job);
|
[=] {
|
||||||
|
return m_connection->getConnection()->getThumbnail(mxcUri,
|
||||||
|
requestedSize);
|
||||||
|
},
|
||||||
|
Qt::BlockingQueuedConnection, &job);
|
||||||
#else
|
#else
|
||||||
QMetaObject::invokeMethod(m_connection, "getThumbnail",
|
QMetaObject::invokeMethod(m_connection, "getThumbnail",
|
||||||
Qt::BlockingQueuedConnection, Q_RETURN_ARG(MediaThumbnailJob*, job),
|
Qt::BlockingQueuedConnection,
|
||||||
Q_ARG(QUrl, mxcUri), Q_ARG(QSize, requestedSize));
|
Q_RETURN_ARG(MediaThumbnailJob*, job),
|
||||||
|
Q_ARG(QUrl, mxcUri), Q_ARG(QSize, requestedSize));
|
||||||
#endif
|
#endif
|
||||||
if (!job)
|
if (!job) {
|
||||||
{
|
qDebug() << "ImageProvider: failed to send a request";
|
||||||
qDebug() << "ImageProvider: failed to send a request";
|
return {};
|
||||||
return {};
|
}
|
||||||
}
|
QImage result;
|
||||||
QImage result;
|
{
|
||||||
{
|
QWaitCondition condition; // The most compact way to block on a signal
|
||||||
QWaitCondition condition; // The most compact way to block on a signal
|
job->connect(job, &MediaThumbnailJob::finished, job, [&] {
|
||||||
job->connect(job, &MediaThumbnailJob::finished, job, [&] {
|
result = job->thumbnail();
|
||||||
result = job->thumbnail();
|
condition.wakeAll();
|
||||||
condition.wakeAll();
|
});
|
||||||
});
|
condition.wait(&m_lock);
|
||||||
condition.wait(&m_lock);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(pSize != nullptr)
|
if (pSize != nullptr) *pSize = result.size();
|
||||||
*pSize = result.size();
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,28 +1,27 @@
|
||||||
#ifndef IMAGEPROVIDER_H
|
#ifndef IMAGEPROVIDER_H
|
||||||
#define IMAGEPROVIDER_H
|
#define IMAGEPROVIDER_H
|
||||||
|
|
||||||
#include <QtQuick/QQuickImageProvider>
|
|
||||||
#include <QtCore/QReadWriteLock>
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QtCore/QReadWriteLock>
|
||||||
|
#include <QtQuick/QQuickImageProvider>
|
||||||
|
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
#include "imageproviderconnection.h"
|
#include "imageproviderconnection.h"
|
||||||
|
|
||||||
class ImageProvider: public QQuickImageProvider
|
class ImageProvider : public QQuickImageProvider {
|
||||||
{
|
public:
|
||||||
public:
|
explicit ImageProvider(QObject* parent = nullptr);
|
||||||
explicit ImageProvider(QObject* parent = nullptr);
|
|
||||||
|
|
||||||
QImage requestImage(const QString& id, QSize* pSize,
|
QImage requestImage(const QString& id, QSize* pSize,
|
||||||
const QSize& requestedSize) override;
|
const QSize& requestedSize) override;
|
||||||
|
|
||||||
void initializeEngine(QQmlEngine *engine, const char *uri);
|
void initializeEngine(QQmlEngine* engine, const char* uri);
|
||||||
|
|
||||||
ImageProviderConnection* getConnection() { return m_connection; }
|
ImageProviderConnection* getConnection() { return m_connection; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QReadWriteLock m_lock;
|
QReadWriteLock m_lock;
|
||||||
ImageProviderConnection* m_connection;
|
ImageProviderConnection* m_connection;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // IMAGEPROVIDER_H
|
#endif // IMAGEPROVIDER_H
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
#include "imageproviderconnection.h"
|
#include "imageproviderconnection.h"
|
||||||
|
|
||||||
ImageProviderConnection::ImageProviderConnection(QObject* parent) : QObject(parent) {
|
ImageProviderConnection::ImageProviderConnection(QObject* parent)
|
||||||
|
: QObject(parent) {}
|
||||||
|
|
||||||
}
|
ImageProviderConnection::~ImageProviderConnection() {}
|
||||||
|
|
||||||
ImageProviderConnection::~ImageProviderConnection() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,25 +5,26 @@
|
||||||
|
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
|
|
||||||
class ImageProviderConnection : public QObject
|
class ImageProviderConnection : public QObject {
|
||||||
{
|
Q_OBJECT
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
Q_PROPERTY(QMatrixClient::Connection* connection READ getConnection WRITE setConnection NOTIFY connectionChanged)
|
Q_PROPERTY(QMatrixClient::Connection* connection READ getConnection WRITE
|
||||||
|
setConnection NOTIFY connectionChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ImageProviderConnection(QObject* parent = nullptr);
|
explicit ImageProviderConnection(QObject* parent = nullptr);
|
||||||
~ImageProviderConnection();
|
~ImageProviderConnection();
|
||||||
|
|
||||||
QMatrixClient::Connection* getConnection() { return m_connection; }
|
QMatrixClient::Connection* getConnection() { return m_connection; }
|
||||||
void setConnection(QMatrixClient::Connection* connection) {
|
void setConnection(QMatrixClient::Connection* connection) {
|
||||||
emit connectionChanged();
|
emit connectionChanged();
|
||||||
m_connection = connection;
|
m_connection = connection;
|
||||||
}
|
}
|
||||||
private:
|
|
||||||
QMatrixClient::Connection* m_connection;
|
private:
|
||||||
signals:
|
QMatrixClient::Connection* m_connection;
|
||||||
void connectionChanged();
|
signals:
|
||||||
|
void connectionChanged();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // IMAGEPROVIDERCONNECTION_H
|
#endif // IMAGEPROVIDERCONNECTION_H
|
||||||
|
|
|
@ -1,452 +1,379 @@
|
||||||
#include "messageeventmodel.h"
|
#include "messageeventmodel.h"
|
||||||
|
|
||||||
#include <QtCore/QSettings>
|
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
#include <QtQml> // for qmlRegisterType()
|
#include <QtCore/QSettings>
|
||||||
|
#include <QtQml> // for qmlRegisterType()
|
||||||
|
|
||||||
#include "events/roommemberevent.h"
|
|
||||||
#include "events/simplestateevents.h"
|
|
||||||
#include "events/redactionevent.h"
|
#include "events/redactionevent.h"
|
||||||
#include "events/roomavatarevent.h"
|
#include "events/roomavatarevent.h"
|
||||||
|
#include "events/roommemberevent.h"
|
||||||
|
#include "events/simplestateevents.h"
|
||||||
|
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
#include "user.h"
|
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
#include "user.h"
|
||||||
|
|
||||||
MessageEventModel::MessageEventModel(QObject* parent)
|
MessageEventModel::MessageEventModel(QObject* parent)
|
||||||
: QAbstractListModel(parent)
|
: QAbstractListModel(parent) {
|
||||||
{
|
qmlRegisterType<QMatrixClient::FileTransferInfo>();
|
||||||
qmlRegisterType<QMatrixClient::FileTransferInfo>();
|
qRegisterMetaType<QMatrixClient::FileTransferInfo>();
|
||||||
qRegisterMetaType<QMatrixClient::FileTransferInfo>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageEventModel::~MessageEventModel()
|
MessageEventModel::~MessageEventModel() {}
|
||||||
{
|
|
||||||
|
|
||||||
|
void MessageEventModel::setRoom(QMatrixClient::Room* room) {
|
||||||
|
if (room == m_currentRoom) return;
|
||||||
|
|
||||||
|
beginResetModel();
|
||||||
|
if (m_currentRoom) {
|
||||||
|
m_currentRoom->disconnect(this);
|
||||||
|
qDebug() << "Disconnected from" << m_currentRoom->id();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_currentRoom = room;
|
||||||
|
if (room) {
|
||||||
|
lastReadEventId = room->readMarkerEventId();
|
||||||
|
using namespace QMatrixClient;
|
||||||
|
connect(m_currentRoom, &Room::aboutToAddNewMessages, this,
|
||||||
|
[=](RoomEventsRange events) {
|
||||||
|
beginInsertRows(QModelIndex(), 0, int(events.size()) - 1);
|
||||||
|
});
|
||||||
|
connect(m_currentRoom, &Room::aboutToAddHistoricalMessages, this,
|
||||||
|
[=](RoomEventsRange events) {
|
||||||
|
if (rowCount() > 0) nextNewerRow = rowCount() - 1;
|
||||||
|
beginInsertRows(QModelIndex(), rowCount(),
|
||||||
|
rowCount() + int(events.size()) - 1);
|
||||||
|
});
|
||||||
|
connect(m_currentRoom, &Room::addedMessages, this, [=] {
|
||||||
|
if (nextNewerRow > -1) {
|
||||||
|
const auto idx = index(nextNewerRow);
|
||||||
|
emit dataChanged(idx, idx);
|
||||||
|
nextNewerRow = -1;
|
||||||
|
}
|
||||||
|
endInsertRows();
|
||||||
|
});
|
||||||
|
connect(m_currentRoom, &Room::readMarkerMoved, this, [this] {
|
||||||
|
refreshEventRoles(
|
||||||
|
std::exchange(lastReadEventId, m_currentRoom->readMarkerEventId()),
|
||||||
|
{ReadMarkerRole});
|
||||||
|
refreshEventRoles(lastReadEventId, {ReadMarkerRole});
|
||||||
|
});
|
||||||
|
connect(
|
||||||
|
m_currentRoom, &Room::replacedEvent, this,
|
||||||
|
[this](const RoomEvent* newEvent) { refreshEvent(newEvent->id()); });
|
||||||
|
connect(m_currentRoom, &Room::fileTransferProgress, this,
|
||||||
|
&MessageEventModel::refreshEvent);
|
||||||
|
connect(m_currentRoom, &Room::fileTransferCompleted, this,
|
||||||
|
&MessageEventModel::refreshEvent);
|
||||||
|
connect(m_currentRoom, &Room::fileTransferFailed, this,
|
||||||
|
&MessageEventModel::refreshEvent);
|
||||||
|
connect(m_currentRoom, &Room::fileTransferCancelled, this,
|
||||||
|
&MessageEventModel::refreshEvent);
|
||||||
|
qDebug() << "Connected to room" << room->id() << "as"
|
||||||
|
<< room->localUser()->id();
|
||||||
|
} else
|
||||||
|
lastReadEventId.clear();
|
||||||
|
endResetModel();
|
||||||
|
emit roomChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageEventModel::setRoom(QMatrixClient::Room* room)
|
void MessageEventModel::refreshEvent(const QString& eventId) {
|
||||||
{
|
refreshEventRoles(eventId, {});
|
||||||
if (room == m_currentRoom)
|
|
||||||
return;
|
|
||||||
|
|
||||||
beginResetModel();
|
|
||||||
if( m_currentRoom )
|
|
||||||
{
|
|
||||||
m_currentRoom->disconnect( this );
|
|
||||||
qDebug() << "Disconnected from" << m_currentRoom->id();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_currentRoom = room;
|
|
||||||
if( room )
|
|
||||||
{
|
|
||||||
lastReadEventId = room->readMarkerEventId();
|
|
||||||
using namespace QMatrixClient;
|
|
||||||
connect(m_currentRoom, &Room::aboutToAddNewMessages, this,
|
|
||||||
[=](RoomEventsRange events)
|
|
||||||
{
|
|
||||||
beginInsertRows(QModelIndex(), 0, int(events.size()) - 1);
|
|
||||||
});
|
|
||||||
connect(m_currentRoom, &Room::aboutToAddHistoricalMessages, this,
|
|
||||||
[=](RoomEventsRange events)
|
|
||||||
{
|
|
||||||
if (rowCount() > 0)
|
|
||||||
nextNewerRow = rowCount() - 1;
|
|
||||||
beginInsertRows(QModelIndex(), rowCount(),
|
|
||||||
rowCount() + int(events.size()) - 1);
|
|
||||||
});
|
|
||||||
connect(m_currentRoom, &Room::addedMessages, this,
|
|
||||||
[=] {
|
|
||||||
if (nextNewerRow > -1)
|
|
||||||
{
|
|
||||||
const auto idx = index(nextNewerRow);
|
|
||||||
emit dataChanged(idx, idx);
|
|
||||||
nextNewerRow = -1;
|
|
||||||
}
|
|
||||||
endInsertRows();
|
|
||||||
});
|
|
||||||
connect(m_currentRoom, &Room::readMarkerMoved, this, [this] {
|
|
||||||
refreshEventRoles(
|
|
||||||
std::exchange(lastReadEventId,
|
|
||||||
m_currentRoom->readMarkerEventId()),
|
|
||||||
{ReadMarkerRole});
|
|
||||||
refreshEventRoles(lastReadEventId, {ReadMarkerRole});
|
|
||||||
});
|
|
||||||
connect(m_currentRoom, &Room::replacedEvent, this,
|
|
||||||
[this] (const RoomEvent* newEvent) {
|
|
||||||
refreshEvent(newEvent->id());
|
|
||||||
});
|
|
||||||
connect(m_currentRoom, &Room::fileTransferProgress,
|
|
||||||
this, &MessageEventModel::refreshEvent);
|
|
||||||
connect(m_currentRoom, &Room::fileTransferCompleted,
|
|
||||||
this, &MessageEventModel::refreshEvent);
|
|
||||||
connect(m_currentRoom, &Room::fileTransferFailed,
|
|
||||||
this, &MessageEventModel::refreshEvent);
|
|
||||||
connect(m_currentRoom, &Room::fileTransferCancelled,
|
|
||||||
this, &MessageEventModel::refreshEvent);
|
|
||||||
qDebug() << "Connected to room" << room->id()
|
|
||||||
<< "as" << room->localUser()->id();
|
|
||||||
} else
|
|
||||||
lastReadEventId.clear();
|
|
||||||
endResetModel();
|
|
||||||
emit roomChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MessageEventModel::refreshEvent(const QString& eventId)
|
|
||||||
{
|
|
||||||
refreshEventRoles(eventId, {});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageEventModel::refreshEventRoles(const QString& eventId,
|
void MessageEventModel::refreshEventRoles(const QString& eventId,
|
||||||
const QVector<int> roles)
|
const QVector<int> roles) {
|
||||||
{
|
const auto it = m_currentRoom->findInTimeline(eventId);
|
||||||
const auto it = m_currentRoom->findInTimeline(eventId);
|
if (it != m_currentRoom->timelineEdge()) {
|
||||||
if (it != m_currentRoom->timelineEdge())
|
const auto row = it - m_currentRoom->messageEvents().rbegin();
|
||||||
{
|
emit dataChanged(index(row), index(row), roles);
|
||||||
const auto row = it - m_currentRoom->messageEvents().rbegin();
|
}
|
||||||
emit dataChanged(index(row), index(row), roles);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool hasValidTimestamp(const QMatrixClient::TimelineItem& ti)
|
inline bool hasValidTimestamp(const QMatrixClient::TimelineItem& ti) {
|
||||||
{
|
return ti->timestamp().isValid();
|
||||||
return ti->timestamp().isValid();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QDateTime MessageEventModel::makeMessageTimestamp(QMatrixClient::Room::rev_iter_t baseIt) const
|
QDateTime MessageEventModel::makeMessageTimestamp(
|
||||||
{
|
QMatrixClient::Room::rev_iter_t baseIt) const {
|
||||||
const auto& timeline = m_currentRoom->messageEvents();
|
const auto& timeline = m_currentRoom->messageEvents();
|
||||||
auto ts = baseIt->event()->timestamp();
|
auto ts = baseIt->event()->timestamp();
|
||||||
if (ts.isValid())
|
if (ts.isValid()) return ts;
|
||||||
return ts;
|
|
||||||
|
|
||||||
// The event is most likely redacted or just invalid.
|
// The event is most likely redacted or just invalid.
|
||||||
// Look for the nearest date around and slap zero time to it.
|
// Look for the nearest date around and slap zero time to it.
|
||||||
using QMatrixClient::TimelineItem;
|
using QMatrixClient::TimelineItem;
|
||||||
auto rit = std::find_if(baseIt, timeline.rend(),
|
auto rit = std::find_if(baseIt, timeline.rend(), hasValidTimestamp);
|
||||||
hasValidTimestamp);
|
if (rit != timeline.rend())
|
||||||
if (rit != timeline.rend())
|
return {rit->event()->timestamp().date(), {0, 0}, Qt::LocalTime};
|
||||||
return { rit->event()->timestamp().date(), {0,0}, Qt::LocalTime };
|
auto it = std::find_if(baseIt.base(), timeline.end(), hasValidTimestamp);
|
||||||
auto it = std::find_if(baseIt.base(), timeline.end(), hasValidTimestamp);
|
if (it != timeline.end())
|
||||||
if (it != timeline.end())
|
return {it->event()->timestamp().date(), {0, 0}, Qt::LocalTime};
|
||||||
return { it->event()->timestamp().date(), {0,0}, Qt::LocalTime };
|
|
||||||
|
|
||||||
// What kind of room is that?..
|
// What kind of room is that?..
|
||||||
qCritical() << "No valid timestamps in the room timeline!";
|
qCritical() << "No valid timestamps in the room timeline!";
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
QString MessageEventModel::makeDateString(QMatrixClient::Room::rev_iter_t baseIt) const
|
QString MessageEventModel::makeDateString(
|
||||||
{
|
QMatrixClient::Room::rev_iter_t baseIt) const {
|
||||||
auto date = makeMessageTimestamp(baseIt).toLocalTime().date();
|
auto date = makeMessageTimestamp(baseIt).toLocalTime().date();
|
||||||
if (QMatrixClient::SettingsGroup("UI")
|
if (QMatrixClient::SettingsGroup("UI")
|
||||||
.value("banner_human_friendly_date", true).toBool())
|
.value("banner_human_friendly_date", true)
|
||||||
{
|
.toBool()) {
|
||||||
if (date == QDate::currentDate())
|
if (date == QDate::currentDate()) return tr("Today");
|
||||||
return tr("Today");
|
if (date == QDate::currentDate().addDays(-1)) return tr("Yesterday");
|
||||||
if (date == QDate::currentDate().addDays(-1))
|
if (date == QDate::currentDate().addDays(-2))
|
||||||
return tr("Yesterday");
|
return tr("The day before yesterday");
|
||||||
if (date == QDate::currentDate().addDays(-2))
|
if (date > QDate::currentDate().addDays(-7)) return date.toString("dddd");
|
||||||
return tr("The day before yesterday");
|
}
|
||||||
if (date > QDate::currentDate().addDays(-7))
|
return date.toString(Qt::DefaultLocaleShortDate);
|
||||||
return date.toString("dddd");
|
|
||||||
}
|
|
||||||
return date.toString(Qt::DefaultLocaleShortDate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int MessageEventModel::rowCount(const QModelIndex& parent) const
|
int MessageEventModel::rowCount(const QModelIndex& parent) const {
|
||||||
{
|
if (!m_currentRoom || parent.isValid()) return 0;
|
||||||
if(!m_currentRoom || parent.isValid())
|
return m_currentRoom->timelineSize();
|
||||||
return 0;
|
|
||||||
return m_currentRoom->timelineSize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant MessageEventModel::data(const QModelIndex& index, int role) const
|
QVariant MessageEventModel::data(const QModelIndex& index, int role) const {
|
||||||
{
|
if (!m_currentRoom || index.row() < 0 ||
|
||||||
if( !m_currentRoom ||
|
index.row() >= m_currentRoom->timelineSize())
|
||||||
index.row() < 0 || index.row() >= m_currentRoom->timelineSize())
|
|
||||||
return QVariant();
|
|
||||||
|
|
||||||
const auto timelineIt = m_currentRoom->messageEvents().rbegin() + index.row();
|
|
||||||
const auto& ti = *timelineIt;
|
|
||||||
|
|
||||||
using namespace QMatrixClient;
|
|
||||||
if( role == Qt::DisplayRole )
|
|
||||||
{
|
|
||||||
if (ti->isRedacted())
|
|
||||||
{
|
|
||||||
auto reason = ti->redactedBecause()->reason();
|
|
||||||
if (reason.isEmpty())
|
|
||||||
return tr("Redacted");
|
|
||||||
else
|
|
||||||
return tr("Redacted: %1")
|
|
||||||
.arg(ti->redactedBecause()->reason());
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ti->type() == EventType::RoomMessage )
|
|
||||||
{
|
|
||||||
using namespace MessageEventContent;
|
|
||||||
|
|
||||||
auto* e = ti.viewAs<RoomMessageEvent>();
|
|
||||||
if (e->hasTextContent() && e->mimeType().name() != "text/plain")
|
|
||||||
return static_cast<const TextContent*>(e->content())->body;
|
|
||||||
if (e->hasFileContent())
|
|
||||||
{
|
|
||||||
auto fileCaption = e->content()->fileInfo()->originalName;
|
|
||||||
if (fileCaption.isEmpty())
|
|
||||||
fileCaption = m_currentRoom->prettyPrint(e->plainBody());
|
|
||||||
if (fileCaption.isEmpty())
|
|
||||||
return tr("a file");
|
|
||||||
}
|
|
||||||
return m_currentRoom->prettyPrint(e->plainBody());
|
|
||||||
}
|
|
||||||
if( ti->type() == EventType::RoomMember )
|
|
||||||
{
|
|
||||||
auto* e = ti.viewAs<RoomMemberEvent>();
|
|
||||||
// FIXME: Rewind to the name that was at the time of this event
|
|
||||||
QString subjectName = m_currentRoom->roomMembername(e->userId());
|
|
||||||
// The below code assumes senderName output in AuthorRole
|
|
||||||
switch( e->membership() )
|
|
||||||
{
|
|
||||||
case MembershipType::Invite:
|
|
||||||
if (e->repeatsState())
|
|
||||||
return tr("reinvited %1 to the room").arg(subjectName);
|
|
||||||
// [[fallthrough]]
|
|
||||||
case MembershipType::Join:
|
|
||||||
{
|
|
||||||
if (e->repeatsState())
|
|
||||||
return tr("joined the room (repeated)");
|
|
||||||
if (!e->prev_content() ||
|
|
||||||
e->membership() != e->prev_content()->membership)
|
|
||||||
{
|
|
||||||
return e->membership() == MembershipType::Invite
|
|
||||||
? tr("invited %1 to the room").arg(subjectName)
|
|
||||||
: tr("joined the room");
|
|
||||||
}
|
|
||||||
QString text {};
|
|
||||||
if (e->displayName() != e->prev_content()->displayName)
|
|
||||||
{
|
|
||||||
if (e->displayName().isEmpty())
|
|
||||||
text = tr("cleared the display name");
|
|
||||||
else
|
|
||||||
text = tr("changed the display name to %1")
|
|
||||||
.arg(e->displayName());
|
|
||||||
}
|
|
||||||
if (e->avatarUrl() != e->prev_content()->avatarUrl)
|
|
||||||
{
|
|
||||||
if (!text.isEmpty())
|
|
||||||
text += " and ";
|
|
||||||
if (e->avatarUrl().isEmpty())
|
|
||||||
text += tr("cleared the avatar");
|
|
||||||
else
|
|
||||||
text += tr("updated the avatar");
|
|
||||||
}
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
case MembershipType::Leave:
|
|
||||||
if (e->prev_content() &&
|
|
||||||
e->prev_content()->membership == MembershipType::Ban)
|
|
||||||
{
|
|
||||||
if (e->senderId() != e->userId())
|
|
||||||
return tr("unbanned %1").arg(subjectName);
|
|
||||||
else
|
|
||||||
return tr("self-unbanned");
|
|
||||||
}
|
|
||||||
if (e->senderId() != e->userId())
|
|
||||||
return tr("has put %1 out of the room").arg(subjectName);
|
|
||||||
else
|
|
||||||
return tr("left the room");
|
|
||||||
case MembershipType::Ban:
|
|
||||||
if (e->senderId() != e->userId())
|
|
||||||
return tr("banned %1 from the room").arg(subjectName);
|
|
||||||
else
|
|
||||||
return tr("self-banned from the room");
|
|
||||||
case MembershipType::Knock:
|
|
||||||
return tr("knocked");
|
|
||||||
case MembershipType::Undefined:
|
|
||||||
return tr("made something unknown");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if( ti->type() == EventType::RoomAliases )
|
|
||||||
{
|
|
||||||
auto* e = ti.viewAs<RoomAliasesEvent>();
|
|
||||||
return tr("set aliases to: %1").arg(e->aliases().join(", "));
|
|
||||||
}
|
|
||||||
if( ti->type() == EventType::RoomCanonicalAlias )
|
|
||||||
{
|
|
||||||
auto* e = ti.viewAs<RoomCanonicalAliasEvent>();
|
|
||||||
if (e->alias().isEmpty())
|
|
||||||
return tr("cleared the room main alias");
|
|
||||||
else
|
|
||||||
return tr("set the room main alias to: %1").arg(e->alias());
|
|
||||||
}
|
|
||||||
if( ti->type() == EventType::RoomName )
|
|
||||||
{
|
|
||||||
auto* e = ti.viewAs<RoomNameEvent>();
|
|
||||||
if (e->name().isEmpty())
|
|
||||||
return tr("cleared the room name");
|
|
||||||
else
|
|
||||||
return tr("set the room name to: %1").arg(e->name());
|
|
||||||
}
|
|
||||||
if( ti->type() == EventType::RoomTopic )
|
|
||||||
{
|
|
||||||
auto* e = ti.viewAs<RoomTopicEvent>();
|
|
||||||
if (e->topic().isEmpty())
|
|
||||||
return tr("cleared the topic");
|
|
||||||
else
|
|
||||||
return tr("set the topic to: %1").arg(e->topic());
|
|
||||||
}
|
|
||||||
if( ti->type() == EventType::RoomAvatar )
|
|
||||||
{
|
|
||||||
return tr("changed the room avatar");
|
|
||||||
}
|
|
||||||
if( ti->type() == EventType::RoomEncryption )
|
|
||||||
{
|
|
||||||
return tr("activated End-to-End Encryption");
|
|
||||||
}
|
|
||||||
return tr("Unknown Event");
|
|
||||||
}
|
|
||||||
|
|
||||||
if( role == Qt::ToolTipRole )
|
|
||||||
{
|
|
||||||
return ti->originalJson();
|
|
||||||
}
|
|
||||||
|
|
||||||
if( role == EventTypeRole )
|
|
||||||
{
|
|
||||||
if (ti->isStateEvent())
|
|
||||||
return "state";
|
|
||||||
|
|
||||||
if (ti->type() == EventType::RoomMessage)
|
|
||||||
{
|
|
||||||
switch (ti.viewAs<RoomMessageEvent>()->msgtype())
|
|
||||||
{
|
|
||||||
case MessageEventType::Emote:
|
|
||||||
return "emote";
|
|
||||||
case MessageEventType::Notice:
|
|
||||||
return "notice";
|
|
||||||
case MessageEventType::Image:
|
|
||||||
return "image";
|
|
||||||
case MessageEventType::File:
|
|
||||||
case MessageEventType::Audio:
|
|
||||||
case MessageEventType::Video:
|
|
||||||
return "file";
|
|
||||||
default:
|
|
||||||
return "message";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "other";
|
|
||||||
}
|
|
||||||
|
|
||||||
if( role == TimeRole )
|
|
||||||
return makeMessageTimestamp(timelineIt);
|
|
||||||
|
|
||||||
if( role == SectionRole )
|
|
||||||
return makeDateString(timelineIt); // FIXME: move date rendering to QML
|
|
||||||
|
|
||||||
if( role == AuthorRole )
|
|
||||||
{
|
|
||||||
auto userId = ti->senderId();
|
|
||||||
// FIXME: It shouldn't be User, it should be its state "as of event"
|
|
||||||
return QVariant::fromValue(m_currentRoom->user(userId));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (role == ContentTypeRole)
|
|
||||||
{
|
|
||||||
if (ti->type() == EventType::RoomMessage)
|
|
||||||
{
|
|
||||||
const auto& contentType =
|
|
||||||
ti.viewAs<RoomMessageEvent>()->mimeType().name();
|
|
||||||
return contentType == "text/plain" ? "text/html" : contentType;
|
|
||||||
}
|
|
||||||
return "text/plain";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (role == ContentRole)
|
|
||||||
{
|
|
||||||
if (ti->isRedacted())
|
|
||||||
{
|
|
||||||
auto reason = ti->redactedBecause()->reason();
|
|
||||||
if (reason.isEmpty())
|
|
||||||
return tr("Redacted");
|
|
||||||
else
|
|
||||||
return tr("Redacted: %1")
|
|
||||||
.arg(ti->redactedBecause()->reason());
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ti->type() == EventType::RoomMessage )
|
|
||||||
{
|
|
||||||
using namespace MessageEventContent;
|
|
||||||
|
|
||||||
auto* e = ti.viewAs<RoomMessageEvent>();
|
|
||||||
switch (e->msgtype())
|
|
||||||
{
|
|
||||||
case MessageEventType::Image:
|
|
||||||
case MessageEventType::File:
|
|
||||||
case MessageEventType::Audio:
|
|
||||||
case MessageEventType::Video:
|
|
||||||
return QVariant::fromValue(e->content()->originalJson);
|
|
||||||
default:
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( role == ReadMarkerRole )
|
|
||||||
return ti->id() == lastReadEventId;
|
|
||||||
|
|
||||||
if( role == SpecialMarksRole )
|
|
||||||
{
|
|
||||||
if (ti->isStateEvent() && ti.viewAs<StateEventBase>()->repeatsState())
|
|
||||||
return "hidden";
|
|
||||||
return ti->isRedacted() ? "redacted" : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
if( role == EventIdRole )
|
|
||||||
return ti->id();
|
|
||||||
|
|
||||||
if( role == LongOperationRole )
|
|
||||||
{
|
|
||||||
if (ti->type() == EventType::RoomMessage &&
|
|
||||||
ti.viewAs<RoomMessageEvent>()->hasFileContent())
|
|
||||||
{
|
|
||||||
auto info = m_currentRoom->fileTransferInfo(ti->id());
|
|
||||||
return QVariant::fromValue(info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto aboveEventIt = timelineIt + 1; // FIXME: shouldn't be here, because #312
|
|
||||||
if (aboveEventIt != m_currentRoom->timelineEdge())
|
|
||||||
{
|
|
||||||
if( role == AboveSectionRole )
|
|
||||||
return makeDateString(aboveEventIt);
|
|
||||||
|
|
||||||
if( role == AboveAuthorRole )
|
|
||||||
return QVariant::fromValue(
|
|
||||||
m_currentRoom->user((*aboveEventIt)->senderId()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
|
||||||
|
const auto timelineIt = m_currentRoom->messageEvents().rbegin() + index.row();
|
||||||
|
const auto& ti = *timelineIt;
|
||||||
|
|
||||||
|
using namespace QMatrixClient;
|
||||||
|
if (role == Qt::DisplayRole) {
|
||||||
|
if (ti->isRedacted()) {
|
||||||
|
auto reason = ti->redactedBecause()->reason();
|
||||||
|
if (reason.isEmpty())
|
||||||
|
return tr("Redacted");
|
||||||
|
else
|
||||||
|
return tr("Redacted: %1").arg(ti->redactedBecause()->reason());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ti->type() == EventType::RoomMessage) {
|
||||||
|
using namespace MessageEventContent;
|
||||||
|
|
||||||
|
auto* e = ti.viewAs<RoomMessageEvent>();
|
||||||
|
if (e->hasTextContent() && e->mimeType().name() != "text/plain")
|
||||||
|
return static_cast<const TextContent*>(e->content())->body;
|
||||||
|
if (e->hasFileContent()) {
|
||||||
|
auto fileCaption = e->content()->fileInfo()->originalName;
|
||||||
|
if (fileCaption.isEmpty())
|
||||||
|
fileCaption = m_currentRoom->prettyPrint(e->plainBody());
|
||||||
|
if (fileCaption.isEmpty()) return tr("a file");
|
||||||
|
}
|
||||||
|
return m_currentRoom->prettyPrint(e->plainBody());
|
||||||
|
}
|
||||||
|
if (ti->type() == EventType::RoomMember) {
|
||||||
|
auto* e = ti.viewAs<RoomMemberEvent>();
|
||||||
|
// FIXME: Rewind to the name that was at the time of this event
|
||||||
|
QString subjectName = m_currentRoom->roomMembername(e->userId());
|
||||||
|
// The below code assumes senderName output in AuthorRole
|
||||||
|
switch (e->membership()) {
|
||||||
|
case MembershipType::Invite:
|
||||||
|
if (e->repeatsState())
|
||||||
|
return tr("reinvited %1 to the room").arg(subjectName);
|
||||||
|
// [[fallthrough]]
|
||||||
|
case MembershipType::Join: {
|
||||||
|
if (e->repeatsState()) return tr("joined the room (repeated)");
|
||||||
|
if (!e->prev_content() ||
|
||||||
|
e->membership() != e->prev_content()->membership) {
|
||||||
|
return e->membership() == MembershipType::Invite
|
||||||
|
? tr("invited %1 to the room").arg(subjectName)
|
||||||
|
: tr("joined the room");
|
||||||
|
}
|
||||||
|
QString text{};
|
||||||
|
if (e->displayName() != e->prev_content()->displayName) {
|
||||||
|
if (e->displayName().isEmpty())
|
||||||
|
text = tr("cleared the display name");
|
||||||
|
else
|
||||||
|
text = tr("changed the display name to %1").arg(e->displayName());
|
||||||
|
}
|
||||||
|
if (e->avatarUrl() != e->prev_content()->avatarUrl) {
|
||||||
|
if (!text.isEmpty()) text += " and ";
|
||||||
|
if (e->avatarUrl().isEmpty())
|
||||||
|
text += tr("cleared the avatar");
|
||||||
|
else
|
||||||
|
text += tr("updated the avatar");
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
case MembershipType::Leave:
|
||||||
|
if (e->prev_content() &&
|
||||||
|
e->prev_content()->membership == MembershipType::Ban) {
|
||||||
|
if (e->senderId() != e->userId())
|
||||||
|
return tr("unbanned %1").arg(subjectName);
|
||||||
|
else
|
||||||
|
return tr("self-unbanned");
|
||||||
|
}
|
||||||
|
if (e->senderId() != e->userId())
|
||||||
|
return tr("has put %1 out of the room").arg(subjectName);
|
||||||
|
else
|
||||||
|
return tr("left the room");
|
||||||
|
case MembershipType::Ban:
|
||||||
|
if (e->senderId() != e->userId())
|
||||||
|
return tr("banned %1 from the room").arg(subjectName);
|
||||||
|
else
|
||||||
|
return tr("self-banned from the room");
|
||||||
|
case MembershipType::Knock:
|
||||||
|
return tr("knocked");
|
||||||
|
case MembershipType::Undefined:
|
||||||
|
return tr("made something unknown");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ti->type() == EventType::RoomAliases) {
|
||||||
|
auto* e = ti.viewAs<RoomAliasesEvent>();
|
||||||
|
return tr("set aliases to: %1").arg(e->aliases().join(", "));
|
||||||
|
}
|
||||||
|
if (ti->type() == EventType::RoomCanonicalAlias) {
|
||||||
|
auto* e = ti.viewAs<RoomCanonicalAliasEvent>();
|
||||||
|
if (e->alias().isEmpty())
|
||||||
|
return tr("cleared the room main alias");
|
||||||
|
else
|
||||||
|
return tr("set the room main alias to: %1").arg(e->alias());
|
||||||
|
}
|
||||||
|
if (ti->type() == EventType::RoomName) {
|
||||||
|
auto* e = ti.viewAs<RoomNameEvent>();
|
||||||
|
if (e->name().isEmpty())
|
||||||
|
return tr("cleared the room name");
|
||||||
|
else
|
||||||
|
return tr("set the room name to: %1").arg(e->name());
|
||||||
|
}
|
||||||
|
if (ti->type() == EventType::RoomTopic) {
|
||||||
|
auto* e = ti.viewAs<RoomTopicEvent>();
|
||||||
|
if (e->topic().isEmpty())
|
||||||
|
return tr("cleared the topic");
|
||||||
|
else
|
||||||
|
return tr("set the topic to: %1").arg(e->topic());
|
||||||
|
}
|
||||||
|
if (ti->type() == EventType::RoomAvatar) {
|
||||||
|
return tr("changed the room avatar");
|
||||||
|
}
|
||||||
|
if (ti->type() == EventType::RoomEncryption) {
|
||||||
|
return tr("activated End-to-End Encryption");
|
||||||
|
}
|
||||||
|
return tr("Unknown Event");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (role == Qt::ToolTipRole) {
|
||||||
|
return ti->originalJson();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (role == EventTypeRole) {
|
||||||
|
if (ti->isStateEvent()) return "state";
|
||||||
|
|
||||||
|
if (ti->type() == EventType::RoomMessage) {
|
||||||
|
switch (ti.viewAs<RoomMessageEvent>()->msgtype()) {
|
||||||
|
case MessageEventType::Emote:
|
||||||
|
return "emote";
|
||||||
|
case MessageEventType::Notice:
|
||||||
|
return "notice";
|
||||||
|
case MessageEventType::Image:
|
||||||
|
return "image";
|
||||||
|
case MessageEventType::File:
|
||||||
|
case MessageEventType::Audio:
|
||||||
|
case MessageEventType::Video:
|
||||||
|
return "file";
|
||||||
|
default:
|
||||||
|
return "message";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "other";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (role == TimeRole) return makeMessageTimestamp(timelineIt);
|
||||||
|
|
||||||
|
if (role == SectionRole)
|
||||||
|
return makeDateString(timelineIt); // FIXME: move date rendering to QML
|
||||||
|
|
||||||
|
if (role == AuthorRole) {
|
||||||
|
auto userId = ti->senderId();
|
||||||
|
// FIXME: It shouldn't be User, it should be its state "as of event"
|
||||||
|
return QVariant::fromValue(m_currentRoom->user(userId));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (role == ContentTypeRole) {
|
||||||
|
if (ti->type() == EventType::RoomMessage) {
|
||||||
|
const auto& contentType =
|
||||||
|
ti.viewAs<RoomMessageEvent>()->mimeType().name();
|
||||||
|
return contentType == "text/plain" ? "text/html" : contentType;
|
||||||
|
}
|
||||||
|
return "text/plain";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (role == ContentRole) {
|
||||||
|
if (ti->isRedacted()) {
|
||||||
|
auto reason = ti->redactedBecause()->reason();
|
||||||
|
if (reason.isEmpty())
|
||||||
|
return tr("Redacted");
|
||||||
|
else
|
||||||
|
return tr("Redacted: %1").arg(ti->redactedBecause()->reason());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ti->type() == EventType::RoomMessage) {
|
||||||
|
using namespace MessageEventContent;
|
||||||
|
|
||||||
|
auto* e = ti.viewAs<RoomMessageEvent>();
|
||||||
|
switch (e->msgtype()) {
|
||||||
|
case MessageEventType::Image:
|
||||||
|
case MessageEventType::File:
|
||||||
|
case MessageEventType::Audio:
|
||||||
|
case MessageEventType::Video:
|
||||||
|
return QVariant::fromValue(e->content()->originalJson);
|
||||||
|
default:;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (role == ReadMarkerRole) return ti->id() == lastReadEventId;
|
||||||
|
|
||||||
|
if (role == SpecialMarksRole) {
|
||||||
|
if (ti->isStateEvent() && ti.viewAs<StateEventBase>()->repeatsState())
|
||||||
|
return "hidden";
|
||||||
|
return ti->isRedacted() ? "redacted" : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (role == EventIdRole) return ti->id();
|
||||||
|
|
||||||
|
if (role == LongOperationRole) {
|
||||||
|
if (ti->type() == EventType::RoomMessage &&
|
||||||
|
ti.viewAs<RoomMessageEvent>()->hasFileContent()) {
|
||||||
|
auto info = m_currentRoom->fileTransferInfo(ti->id());
|
||||||
|
return QVariant::fromValue(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto aboveEventIt = timelineIt + 1; // FIXME: shouldn't be here, because #312
|
||||||
|
if (aboveEventIt != m_currentRoom->timelineEdge()) {
|
||||||
|
if (role == AboveSectionRole) return makeDateString(aboveEventIt);
|
||||||
|
|
||||||
|
if (role == AboveAuthorRole)
|
||||||
|
return QVariant::fromValue(
|
||||||
|
m_currentRoom->user((*aboveEventIt)->senderId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QHash<int, QByteArray> MessageEventModel::roleNames() const {
|
||||||
QHash<int, QByteArray> MessageEventModel::roleNames() const
|
QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
|
||||||
{
|
roles[EventTypeRole] = "eventType";
|
||||||
QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
|
roles[EventIdRole] = "eventId";
|
||||||
roles[EventTypeRole] = "eventType";
|
roles[TimeRole] = "time";
|
||||||
roles[EventIdRole] = "eventId";
|
roles[SectionRole] = "section";
|
||||||
roles[TimeRole] = "time";
|
roles[AboveSectionRole] = "aboveSection";
|
||||||
roles[SectionRole] = "section";
|
roles[AuthorRole] = "author";
|
||||||
roles[AboveSectionRole] = "aboveSection";
|
roles[AboveAuthorRole] = "aboveAuthor";
|
||||||
roles[AuthorRole] = "author";
|
roles[ContentRole] = "content";
|
||||||
roles[AboveAuthorRole] = "aboveAuthor";
|
roles[ContentTypeRole] = "contentType";
|
||||||
roles[ContentRole] = "content";
|
roles[HighlightRole] = "highlight";
|
||||||
roles[ContentTypeRole] = "contentType";
|
roles[ReadMarkerRole] = "readMarker";
|
||||||
roles[HighlightRole] = "highlight";
|
roles[SpecialMarksRole] = "marks";
|
||||||
roles[ReadMarkerRole] = "readMarker";
|
roles[LongOperationRole] = "progressInfo";
|
||||||
roles[SpecialMarksRole] = "marks";
|
roles[EventResolvedTypeRole] = "eventResolvedType";
|
||||||
roles[LongOperationRole] = "progressInfo";
|
return roles;
|
||||||
roles[EventResolvedTypeRole] = "eventResolvedType";
|
|
||||||
return roles;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,54 +4,55 @@
|
||||||
#include <QtCore/QAbstractListModel>
|
#include <QtCore/QAbstractListModel>
|
||||||
#include "room.h"
|
#include "room.h"
|
||||||
|
|
||||||
class MessageEventModel: public QAbstractListModel
|
class MessageEventModel : public QAbstractListModel {
|
||||||
{
|
Q_OBJECT
|
||||||
Q_OBJECT
|
Q_PROPERTY(
|
||||||
Q_PROPERTY(QMatrixClient::Room* room READ getRoom WRITE setRoom NOTIFY roomChanged)
|
QMatrixClient::Room* room READ getRoom WRITE setRoom NOTIFY roomChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum EventRoles {
|
enum EventRoles {
|
||||||
EventTypeRole = Qt::UserRole + 1,
|
EventTypeRole = Qt::UserRole + 1,
|
||||||
EventIdRole,
|
EventIdRole,
|
||||||
TimeRole,
|
TimeRole,
|
||||||
SectionRole,
|
SectionRole,
|
||||||
AboveSectionRole,
|
AboveSectionRole,
|
||||||
AuthorRole,
|
AuthorRole,
|
||||||
AboveAuthorRole,
|
AboveAuthorRole,
|
||||||
ContentRole,
|
ContentRole,
|
||||||
ContentTypeRole,
|
ContentTypeRole,
|
||||||
HighlightRole,
|
HighlightRole,
|
||||||
ReadMarkerRole,
|
ReadMarkerRole,
|
||||||
SpecialMarksRole,
|
SpecialMarksRole,
|
||||||
LongOperationRole,
|
LongOperationRole,
|
||||||
// For debugging
|
// For debugging
|
||||||
EventResolvedTypeRole,
|
EventResolvedTypeRole,
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit MessageEventModel(QObject* parent = nullptr);
|
explicit MessageEventModel(QObject* parent = nullptr);
|
||||||
~MessageEventModel();
|
~MessageEventModel();
|
||||||
|
|
||||||
QMatrixClient::Room* getRoom() { return m_currentRoom; }
|
QMatrixClient::Room* getRoom() { return m_currentRoom; }
|
||||||
void setRoom(QMatrixClient::Room* room);
|
void setRoom(QMatrixClient::Room* room);
|
||||||
|
|
||||||
Q_INVOKABLE int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
Q_INVOKABLE int rowCount(
|
||||||
QVariant data(const QModelIndex& index, int role) const override;
|
const QModelIndex& parent = QModelIndex()) const override;
|
||||||
QHash<int, QByteArray> roleNames() const;
|
QVariant data(const QModelIndex& index, int role) const override;
|
||||||
|
QHash<int, QByteArray> roleNames() const;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void refreshEvent(const QString& eventId);
|
void refreshEvent(const QString& eventId);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QMatrixClient::Room* m_currentRoom = nullptr;
|
QMatrixClient::Room* m_currentRoom = nullptr;
|
||||||
QString lastReadEventId;
|
QString lastReadEventId;
|
||||||
int nextNewerRow = -1;
|
int nextNewerRow = -1;
|
||||||
|
|
||||||
QDateTime makeMessageTimestamp(QMatrixClient::Room::rev_iter_t baseIt) const;
|
QDateTime makeMessageTimestamp(QMatrixClient::Room::rev_iter_t baseIt) const;
|
||||||
QString makeDateString(QMatrixClient::Room::rev_iter_t baseIt) const;
|
QString makeDateString(QMatrixClient::Room::rev_iter_t baseIt) const;
|
||||||
void refreshEventRoles(const QString& eventId, const QVector<int> roles);
|
void refreshEventRoles(const QString& eventId, const QVector<int> roles);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void roomChanged();
|
void roomChanged();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MESSAGEEVENTMODEL_H
|
#endif // MESSAGEEVENTMODEL_H
|
||||||
|
|
|
@ -1,103 +1,83 @@
|
||||||
#include "roomlistmodel.h"
|
#include "roomlistmodel.h"
|
||||||
|
|
||||||
|
#include <QtCore/QDebug>
|
||||||
#include <QtGui/QBrush>
|
#include <QtGui/QBrush>
|
||||||
#include <QtGui/QColor>
|
#include <QtGui/QColor>
|
||||||
#include <QtCore/QDebug>
|
|
||||||
|
|
||||||
RoomListModel::RoomListModel(QObject* parent)
|
RoomListModel::RoomListModel(QObject* parent) : QAbstractListModel(parent) {}
|
||||||
: QAbstractListModel(parent)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
RoomListModel::~RoomListModel() {}
|
||||||
|
|
||||||
RoomListModel::~RoomListModel()
|
void RoomListModel::setConnection(QMatrixClient::Connection* connection) {
|
||||||
{
|
beginResetModel();
|
||||||
}
|
m_connection = connection;
|
||||||
|
m_rooms.clear();
|
||||||
void RoomListModel::setConnection(QMatrixClient::Connection* connection)
|
connect(connection, &QMatrixClient::Connection::newRoom, this,
|
||||||
{
|
&RoomListModel::addRoom);
|
||||||
beginResetModel();
|
for (QMatrixClient::Room* room : connection->roomMap().values()) {
|
||||||
m_connection = connection;
|
connect(room, &QMatrixClient::Room::namesChanged, this,
|
||||||
m_rooms.clear();
|
&RoomListModel::namesChanged);
|
||||||
connect( connection, &QMatrixClient::Connection::newRoom, this, &RoomListModel::addRoom );
|
|
||||||
for( QMatrixClient::Room* room: connection->roomMap().values() ) {
|
|
||||||
connect( room, &QMatrixClient::Room::namesChanged, this, &RoomListModel::namesChanged );
|
|
||||||
m_rooms.append(room);
|
|
||||||
}
|
|
||||||
endResetModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
QMatrixClient::Room* RoomListModel::roomAt(int row)
|
|
||||||
{
|
|
||||||
return m_rooms.at(row);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RoomListModel::addRoom(QMatrixClient::Room* room)
|
|
||||||
{
|
|
||||||
beginInsertRows(QModelIndex(), m_rooms.count(), m_rooms.count());
|
|
||||||
connect( room, &QMatrixClient::Room::namesChanged, this, &RoomListModel::namesChanged );
|
|
||||||
m_rooms.append(room);
|
m_rooms.append(room);
|
||||||
endInsertRows();
|
}
|
||||||
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
int RoomListModel::rowCount(const QModelIndex& parent) const
|
QMatrixClient::Room* RoomListModel::roomAt(int row) { return m_rooms.at(row); }
|
||||||
{
|
|
||||||
if( parent.isValid() )
|
void RoomListModel::addRoom(QMatrixClient::Room* room) {
|
||||||
return 0;
|
beginInsertRows(QModelIndex(), m_rooms.count(), m_rooms.count());
|
||||||
return m_rooms.count();
|
connect(room, &QMatrixClient::Room::namesChanged, this,
|
||||||
|
&RoomListModel::namesChanged);
|
||||||
|
m_rooms.append(room);
|
||||||
|
endInsertRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant RoomListModel::data(const QModelIndex& index, int role) const
|
int RoomListModel::rowCount(const QModelIndex& parent) const {
|
||||||
{
|
if (parent.isValid()) return 0;
|
||||||
if( !index.isValid() )
|
return m_rooms.count();
|
||||||
return QVariant();
|
}
|
||||||
|
|
||||||
if( index.row() >= m_rooms.count() )
|
QVariant RoomListModel::data(const QModelIndex& index, int role) const {
|
||||||
{
|
if (!index.isValid()) return QVariant();
|
||||||
qDebug() << "UserListModel: something wrong here...";
|
|
||||||
return QVariant();
|
if (index.row() >= m_rooms.count()) {
|
||||||
}
|
qDebug() << "UserListModel: something wrong here...";
|
||||||
QMatrixClient::Room* room = m_rooms.at(index.row());
|
return QVariant();
|
||||||
if( role == Qt::DisplayRole )
|
}
|
||||||
{
|
QMatrixClient::Room* room = m_rooms.at(index.row());
|
||||||
return room->displayName();
|
if (role == Qt::DisplayRole) {
|
||||||
}
|
return room->displayName();
|
||||||
if( role == Qt::ForegroundRole )
|
}
|
||||||
{
|
if (role == Qt::ForegroundRole) {
|
||||||
if( room->highlightCount() > 0 )
|
if (room->highlightCount() > 0) return QBrush(QColor("orange"));
|
||||||
return QBrush(QColor("orange"));
|
return QVariant();
|
||||||
return QVariant();
|
}
|
||||||
}
|
if (role == Qt::DecorationRole) {
|
||||||
if( role == Qt::DecorationRole )
|
if (room->avatarUrl().toString() != "") {
|
||||||
{
|
return room->avatarUrl();
|
||||||
if ( room->avatarUrl().toString() != "" ) {
|
|
||||||
return room->avatarUrl();
|
|
||||||
}
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
if ( role == Qt::StatusTipRole )
|
|
||||||
{
|
|
||||||
return room->topic();
|
|
||||||
}
|
}
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
}
|
||||||
|
if (role == Qt::StatusTipRole) {
|
||||||
|
return room->topic();
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoomListModel::namesChanged(QMatrixClient::Room* room)
|
void RoomListModel::namesChanged(QMatrixClient::Room* room) {
|
||||||
{
|
int row = m_rooms.indexOf(room);
|
||||||
int row = m_rooms.indexOf(room);
|
emit dataChanged(index(row), index(row));
|
||||||
emit dataChanged(index(row), index(row));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoomListModel::unreadMessagesChanged(QMatrixClient::Room* room)
|
void RoomListModel::unreadMessagesChanged(QMatrixClient::Room* room) {
|
||||||
{
|
int row = m_rooms.indexOf(room);
|
||||||
int row = m_rooms.indexOf(room);
|
emit dataChanged(index(row), index(row));
|
||||||
emit dataChanged(index(row), index(row));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QHash<int, QByteArray> RoomListModel::roleNames() const {
|
QHash<int, QByteArray> RoomListModel::roleNames() const {
|
||||||
QHash<int, QByteArray> roles;
|
QHash<int, QByteArray> roles;
|
||||||
roles[Qt::DisplayRole] = "name";
|
roles[Qt::DisplayRole] = "name";
|
||||||
roles[Qt::DecorationRole] = "avatar";
|
roles[Qt::DecorationRole] = "avatar";
|
||||||
roles[Qt::StatusTipRole] = "topic";
|
roles[Qt::StatusTipRole] = "topic";
|
||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,39 +2,41 @@
|
||||||
#define ROOMLISTMODEL_H
|
#define ROOMLISTMODEL_H
|
||||||
|
|
||||||
#include <QtCore/QAbstractListModel>
|
#include <QtCore/QAbstractListModel>
|
||||||
#include "room.h"
|
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
|
#include "room.h"
|
||||||
|
|
||||||
class RoomListModel: public QAbstractListModel
|
class RoomListModel : public QAbstractListModel {
|
||||||
{
|
Q_OBJECT
|
||||||
Q_OBJECT
|
Q_PROPERTY(QMatrixClient::Connection* connection READ getConnection WRITE
|
||||||
Q_PROPERTY(QMatrixClient::Connection *connection READ getConnection WRITE setConnection)
|
setConnection)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RoomListModel(QObject* parent=0);
|
RoomListModel(QObject* parent = 0);
|
||||||
virtual ~RoomListModel();
|
virtual ~RoomListModel();
|
||||||
|
|
||||||
QMatrixClient::Connection* getConnection() {return m_connection;}
|
QMatrixClient::Connection* getConnection() { return m_connection; }
|
||||||
void setConnection(QMatrixClient::Connection* connection);
|
void setConnection(QMatrixClient::Connection* connection);
|
||||||
|
|
||||||
Q_INVOKABLE QMatrixClient::Room* roomAt(int row);
|
Q_INVOKABLE QMatrixClient::Room* roomAt(int row);
|
||||||
|
|
||||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
QVariant data(const QModelIndex& index,
|
||||||
Q_INVOKABLE int rowCount(const QModelIndex& parent=QModelIndex()) const override;
|
int role = Qt::DisplayRole) const override;
|
||||||
|
Q_INVOKABLE int rowCount(
|
||||||
|
const QModelIndex& parent = QModelIndex()) const override;
|
||||||
|
|
||||||
QHash<int, QByteArray> roleNames() const;
|
QHash<int, QByteArray> roleNames() const;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void namesChanged(QMatrixClient::Room* room);
|
void namesChanged(QMatrixClient::Room* room);
|
||||||
void unreadMessagesChanged(QMatrixClient::Room* room);
|
void unreadMessagesChanged(QMatrixClient::Room* room);
|
||||||
void addRoom(QMatrixClient::Room* room);
|
void addRoom(QMatrixClient::Room* room);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QMatrixClient::Connection* m_connection = nullptr;
|
QMatrixClient::Connection* m_connection = nullptr;
|
||||||
QList<QMatrixClient::Room*> m_rooms;
|
QList<QMatrixClient::Room*> m_rooms;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void connectionChanged();
|
void connectionChanged();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ROOMLISTMODEL_H
|
#endif // ROOMLISTMODEL_H
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import QtQuick 2.10
|
import QtQuick 2.11
|
||||||
import QtQuick.Layouts 1.3
|
import QtQuick.Layouts 1.11
|
||||||
import QtGraphicalEffects 1.0
|
import QtGraphicalEffects 1.0
|
||||||
import QtQuick.Controls 2.3
|
import QtQuick.Controls 2.4
|
||||||
import QtQuick.Controls.Material 2.3
|
import QtQuick.Controls.Material 2.4
|
||||||
import Qt.labs.settings 1.0
|
import Qt.labs.settings 1.0
|
||||||
import "qrc:/qml/component"
|
import "qrc:/qml/component"
|
||||||
|
|
||||||
|
@ -60,13 +60,13 @@ Page {
|
||||||
id: mainCol
|
id: mainCol
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
|
||||||
ImageStatus {
|
// ImageStatus {
|
||||||
Layout.preferredWidth: 96
|
// Layout.preferredWidth: 96
|
||||||
Layout.preferredHeight: 96
|
// Layout.preferredHeight: 96
|
||||||
Layout.alignment: Qt.AlignHCenter
|
// Layout.alignment: Qt.AlignHCenter
|
||||||
|
|
||||||
source: "qrc:/asset/img/avatar.png"
|
// source: "qrc:/asset/img/avatar.png"
|
||||||
}
|
// }
|
||||||
|
|
||||||
TextField {
|
TextField {
|
||||||
id: serverField
|
id: serverField
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import QtQuick 2.11
|
import QtQuick 2.11
|
||||||
import QtQuick.Controls 2.3
|
import QtQuick.Controls 2.4
|
||||||
import QtQuick.Layouts 1.3
|
import QtQuick.Layouts 1.11
|
||||||
import Matrique 0.1
|
import Matrique 0.1
|
||||||
|
|
||||||
import "qrc:/qml/form"
|
import "qrc:/qml/form"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import QtQuick 2.3
|
import QtQuick 2.11
|
||||||
import QtQuick.Controls 2.3
|
import QtQuick.Controls 2.4
|
||||||
|
|
||||||
ItemDelegate {
|
ItemDelegate {
|
||||||
id: itemDelegate
|
id: itemDelegate
|
||||||
|
|
|
@ -1,17 +1,22 @@
|
||||||
import QtQuick 2.11
|
import QtQuick 2.11
|
||||||
import QtQuick.Controls 2.4
|
import QtQuick.Controls 2.4
|
||||||
import QtGraphicalEffects 1.0
|
import QtGraphicalEffects 1.0
|
||||||
|
import QtQuick.Controls.Material 2.4
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
property bool opaqueBackground: false
|
property bool opaqueBackground: false
|
||||||
property alias source: avatar.source
|
property bool round: true
|
||||||
|
property string source: ""
|
||||||
|
property string displayText: ""
|
||||||
|
readonly property bool showImage: source
|
||||||
|
readonly property bool showInitial: !showImage && displayText
|
||||||
|
|
||||||
id: item
|
id: item
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: item.width
|
width: item.width
|
||||||
height: item.width
|
height: item.width
|
||||||
radius: item.width / 2
|
radius: round ? item.width / 2 : 0
|
||||||
color: "white"
|
color: "white"
|
||||||
visible: opaqueBackground
|
visible: opaqueBackground
|
||||||
}
|
}
|
||||||
|
@ -20,6 +25,8 @@ Item {
|
||||||
id: avatar
|
id: avatar
|
||||||
width: item.width
|
width: item.width
|
||||||
height: item.width
|
height: item.width
|
||||||
|
visible: showImage
|
||||||
|
source: item.source
|
||||||
|
|
||||||
mipmap: true
|
mipmap: true
|
||||||
layer.enabled: true
|
layer.enabled: true
|
||||||
|
@ -35,9 +42,42 @@ Item {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
width: avatar.width
|
width: avatar.width
|
||||||
height: avatar.width
|
height: avatar.width
|
||||||
radius: avatar.width / 2
|
radius: round? avatar.width / 2 : 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
anchors.fill: parent
|
||||||
|
color: "white"
|
||||||
|
visible: showInitial
|
||||||
|
text: showInitial ? getInitials(displayText)[0] : ""
|
||||||
|
font.pixelSize: 22
|
||||||
|
font.bold: true
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
background: Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: round? width / 2 : 0
|
||||||
|
color: showInitial ? stringToColor(displayText) : Material.accent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getInitials(text) {
|
||||||
|
return text.toUpperCase().replace(/[^a-zA-Z- ]/g, "").match(/\b\w/g);
|
||||||
|
}
|
||||||
|
|
||||||
|
function stringToColor(str) {
|
||||||
|
var hash = 0;
|
||||||
|
for (var i = 0; i < str.length; i++) {
|
||||||
|
hash = str.charCodeAt(i) + ((hash << 5) - hash);
|
||||||
|
}
|
||||||
|
var colour = '#';
|
||||||
|
for (var i = 0; i < 3; i++) {
|
||||||
|
var value = (hash >> (i * 8)) & 0xFF;
|
||||||
|
colour += ('00' + value.toString(16)).substr(-2);
|
||||||
|
}
|
||||||
|
return colour;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import QtQuick 2.10
|
import QtQuick 2.11
|
||||||
import QtQuick.Controls 2.3
|
import QtQuick.Controls 2.4
|
||||||
import QtQuick.Layouts 1.3
|
import QtQuick.Layouts 1.11
|
||||||
import QtQuick.Controls.Material 2.3
|
import QtQuick.Controls.Material 2.4
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
property alias icon: iconText.text
|
property alias icon: iconText.text
|
||||||
|
@ -17,5 +17,5 @@ Item {
|
||||||
color: item.color
|
color: item.color
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import QtQuick 2.10
|
import QtQuick 2.11
|
||||||
import QtQuick.Controls 2.3
|
import QtQuick.Controls 2.4
|
||||||
import QtQuick.Layouts 1.3
|
import QtQuick.Layouts 1.11
|
||||||
import QtQuick.Controls.Material 2.3
|
import QtQuick.Controls.Material 2.4
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import QtQuick 2.10
|
import QtQuick 2.11
|
||||||
import QtQuick.Controls 2.3
|
import QtQuick.Controls 2.4
|
||||||
import QtQuick.Layouts 1.3
|
import QtQuick.Layouts 1.11
|
||||||
import QtQuick.Controls.Material 2.3
|
import QtQuick.Controls.Material 2.4
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
property var page
|
property var page
|
||||||
|
@ -29,7 +29,7 @@ Item {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if(page != null && stackView.currentItem !== page) {
|
if(!page && stackView.currentItem !== page) {
|
||||||
if(stackView.depth === 1) {
|
if(stackView.depth === 1) {
|
||||||
stackView.replace(page)
|
stackView.replace(page)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import QtQuick 2.10
|
import QtQuick 2.11
|
||||||
import QtQuick.Controls 2.3
|
import QtQuick.Controls 2.4
|
||||||
import QtQuick.Layouts 1.3
|
import QtQuick.Layouts 1.4
|
||||||
import QtQuick.Controls.Material 2.3
|
import QtQuick.Controls.Material 2.4
|
||||||
import "qrc:/qml/component"
|
import "qrc:/qml/component"
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
|
|
@ -2,8 +2,8 @@ import QtQuick 2.11
|
||||||
import QtQuick.Controls 2.4
|
import QtQuick.Controls 2.4
|
||||||
import QtQuick.Layouts 1.11
|
import QtQuick.Layouts 1.11
|
||||||
import QtGraphicalEffects 1.0
|
import QtGraphicalEffects 1.0
|
||||||
import QtQuick.Controls.Material 2.3
|
import QtQuick.Controls.Material 2.4
|
||||||
import QtQml.Models 2.3
|
import QtQml.Models 2.4
|
||||||
import Matrique 0.1
|
import Matrique 0.1
|
||||||
|
|
||||||
import "qrc:/qml/component"
|
import "qrc:/qml/component"
|
||||||
|
@ -27,6 +27,10 @@ Item {
|
||||||
height: 80
|
height: 80
|
||||||
onClicked: listView.currentIndex = index
|
onClicked: listView.currentIndex = index
|
||||||
|
|
||||||
|
ToolTip.visible: pressed
|
||||||
|
ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
|
||||||
|
ToolTip.text: name
|
||||||
|
|
||||||
contentItem: RowLayout {
|
contentItem: RowLayout {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: 16
|
anchors.margins: 16
|
||||||
|
@ -36,7 +40,8 @@ Item {
|
||||||
Layout.preferredWidth: height
|
Layout.preferredWidth: height
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
|
|
||||||
source: avatar == null || avatar == "" ? "qrc:/asset/img/avatar.png" : "image://mxc/" + avatar
|
source: avatar ? "image://mxc/" + avatar : ""
|
||||||
|
displayText: name
|
||||||
opaqueBackground: true
|
opaqueBackground: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,10 +57,10 @@ Item {
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
|
|
||||||
text: {
|
text: {
|
||||||
if (name != "") {
|
if (name) {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
if (alias != "") {
|
if (alias) {
|
||||||
return alias;
|
return alias;
|
||||||
}
|
}
|
||||||
return id
|
return id
|
||||||
|
@ -69,7 +74,7 @@ Item {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
|
|
||||||
text: topic === "" ? "No topic yet." : topic
|
text: topic ? topic : "No topic yet."
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
wrapMode: Text.NoWrap
|
wrapMode: Text.NoWrap
|
||||||
}
|
}
|
||||||
|
@ -133,7 +138,7 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: searchField.activeFocus || searchField.text != "" ? parent.width : 0
|
width: searchField.activeFocus || searchField.text ? parent.width : 0
|
||||||
height: parent.height
|
height: parent.height
|
||||||
color: "white"
|
color: "white"
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import QtQuick 2.10
|
import QtQuick 2.11
|
||||||
import QtQuick.Controls 2.3
|
import QtQuick.Controls 2.4
|
||||||
import QtQuick.Layouts 1.3
|
import QtQuick.Layouts 1.11
|
||||||
import QtQuick.Controls.Material 2.3
|
import QtQuick.Controls.Material 2.4
|
||||||
import QtGraphicalEffects 1.0
|
import QtGraphicalEffects 1.0
|
||||||
import Matrique 0.1
|
import Matrique 0.1
|
||||||
import "qrc:/qml/component"
|
import "qrc:/qml/component"
|
||||||
|
@ -16,7 +16,7 @@ Item {
|
||||||
|
|
||||||
background: Item {
|
background: Item {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
visible: currentRoom == null
|
visible: !currentRoom
|
||||||
Pane {
|
Pane {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ Item {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
spacing: 0
|
spacing: 0
|
||||||
|
|
||||||
visible: currentRoom != null
|
visible: currentRoom
|
||||||
|
|
||||||
Pane {
|
Pane {
|
||||||
z: 10
|
z: 10
|
||||||
|
@ -52,7 +52,8 @@ Item {
|
||||||
ImageStatus {
|
ImageStatus {
|
||||||
Layout.preferredWidth: parent.height
|
Layout.preferredWidth: parent.height
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
source: currentRoom != null && currentRoom.avatarUrl != "" ? "image://mxc/" + currentRoom.avatarUrl : "qrc:/asset/img/avatar.png"
|
source: currentRoom && currentRoom.avatarUrl != "" ? "image://mxc/" + currentRoom.avatarUrl : null
|
||||||
|
displayText: currentRoom ? currentRoom.displayName : ""
|
||||||
}
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
|
@ -61,7 +62,7 @@ Item {
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
text: currentRoom != null ? currentRoom.displayName : ""
|
text: currentRoom ? currentRoom.displayName : ""
|
||||||
font.pointSize: 16
|
font.pointSize: 16
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
wrapMode: Text.NoWrap
|
wrapMode: Text.NoWrap
|
||||||
|
@ -69,7 +70,7 @@ Item {
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
text: currentRoom != null ? currentRoom.topic : ""
|
text: currentRoom ? currentRoom.topic : ""
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
wrapMode: Text.NoWrap
|
wrapMode: Text.NoWrap
|
||||||
}
|
}
|
||||||
|
@ -88,12 +89,14 @@ Item {
|
||||||
displayMarginEnd: 40
|
displayMarginEnd: 40
|
||||||
verticalLayoutDirection: ListView.BottomToTop
|
verticalLayoutDirection: ListView.BottomToTop
|
||||||
spacing: 12
|
spacing: 12
|
||||||
|
|
||||||
model: MessageEventModel{
|
model: MessageEventModel{
|
||||||
id: messageEventModel
|
id: messageEventModel
|
||||||
room: currentRoom
|
room: currentRoom
|
||||||
|
|
||||||
onModelReset: currentRoom.getPreviousContent(50)
|
onModelReset: currentRoom.getPreviousContent(50)
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate: Row {
|
delegate: Row {
|
||||||
readonly property bool sentByMe: author === currentRoom.localUser
|
readonly property bool sentByMe: author === currentRoom.localUser
|
||||||
|
|
||||||
|
@ -102,18 +105,28 @@ Item {
|
||||||
anchors.right: sentByMe ? parent.right : undefined
|
anchors.right: sentByMe ? parent.right : undefined
|
||||||
spacing: 6
|
spacing: 6
|
||||||
|
|
||||||
Image {
|
ImageStatus {
|
||||||
id: avatar
|
id: avatar
|
||||||
width: height
|
width: height
|
||||||
height: 40
|
height: 40
|
||||||
mipmap: true
|
round: false
|
||||||
visible: !sentByMe
|
visible: !sentByMe
|
||||||
source: author.avatarUrl != "" ? "image://mxc/" + author.avatarUrl : "qrc:/asset/img/avatar.png"
|
source: author.avatarUrl != "" ? "image://mxc/" + author.avatarUrl : null
|
||||||
|
displayText: author.displayName
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: mouseArea
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
ToolTip.visible: pressed
|
||||||
|
ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
|
||||||
|
ToolTip.text: author.displayName
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: Math.min(messageText.implicitWidth + 24,
|
width: Math.min(messageText.implicitWidth + 24,
|
||||||
messageListView.width - (!sentByMe ? avatar.width + messageRow.spacing : 0))
|
messageListView.width - (!sentByMe ? avatar.width + messageRow.spacing : 0))
|
||||||
height: messageText.implicitHeight + 24
|
height: messageText.implicitHeight + 24
|
||||||
color: sentByMe ? "lightgrey" : Material.accent
|
color: sentByMe ? "lightgrey" : Material.accent
|
||||||
|
|
||||||
|
@ -121,6 +134,7 @@ Item {
|
||||||
id: messageText
|
id: messageText
|
||||||
text: display
|
text: display
|
||||||
color: sentByMe ? "black" : "white"
|
color: sentByMe ? "black" : "white"
|
||||||
|
linkColor: sentByMe ? Material.accent : "white"
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: 12
|
anchors.margins: 12
|
||||||
wrapMode: Label.Wrap
|
wrapMode: Label.Wrap
|
||||||
|
|
25
qml/main.qml
25
qml/main.qml
|
@ -1,6 +1,6 @@
|
||||||
import QtQuick 2.11
|
import QtQuick 2.11
|
||||||
import QtQuick.Controls 2.4
|
import QtQuick.Controls 2.4
|
||||||
import QtQuick.Layouts 1.4
|
import QtQuick.Layouts 1.11
|
||||||
import QtQuick.Controls.Material 2.4
|
import QtQuick.Controls.Material 2.4
|
||||||
import QtGraphicalEffects 1.0
|
import QtGraphicalEffects 1.0
|
||||||
import Qt.labs.settings 1.0
|
import Qt.labs.settings 1.0
|
||||||
|
@ -28,16 +28,16 @@ ApplicationWindow {
|
||||||
property alias token: matriqueController.token
|
property alias token: matriqueController.token
|
||||||
}
|
}
|
||||||
|
|
||||||
// Platform.SystemTrayIcon {
|
// Platform.SystemTrayIcon {
|
||||||
// visible: true
|
// visible: true
|
||||||
// iconSource: "qrc:/asset/img/icon.png"
|
// iconSource: "qrc:/asset/img/icon.png"
|
||||||
|
|
||||||
// onActivated: {
|
// onActivated: {
|
||||||
// window.show()
|
// window.show()
|
||||||
// window.raise()
|
// window.raise()
|
||||||
// window.requestActivate()
|
// window.requestActivate()
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
Controller {
|
Controller {
|
||||||
id: matriqueController
|
id: matriqueController
|
||||||
|
@ -118,7 +118,8 @@ ApplicationWindow {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: 15
|
anchors.margins: 15
|
||||||
|
|
||||||
source: matriqueController.connection.localUser != null ? "image://mxc/" + matriqueController.connection.localUser.avatarUrl : "qrc:/asset/img/avatar.png"
|
source: matriqueController.connection.localUser && matriqueController.connection.localUser.avatarUrl ? "image://mxc/" + matriqueController.connection.localUser.avatarUrl : ""
|
||||||
|
displayText: matriqueController.connection.localUser && matriqueController.connection.localUser.displayText ? matriqueController.connection.localUser.displayText : "N"
|
||||||
opaqueBackground: false
|
opaqueBackground: false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,7 +159,7 @@ ApplicationWindow {
|
||||||
imageProvider.connection = matriqueController.connection
|
imageProvider.connection = matriqueController.connection
|
||||||
|
|
||||||
console.log(matriqueController.homeserver, matriqueController.userID, matriqueController.token)
|
console.log(matriqueController.homeserver, matriqueController.userID, matriqueController.token)
|
||||||
if (matriqueController.userID != "" && matriqueController.token != "") {
|
if (matriqueController.userID && matriqueController.token) {
|
||||||
console.log("Perform auto-login.");
|
console.log("Perform auto-login.");
|
||||||
matriqueController.login();
|
matriqueController.login();
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue