Support Qt 5.11 and fix image provider.

square-messages
Black Hat 2018-07-07 17:38:20 +08:00
parent a850224c98
commit 17fa7cc7da
24 changed files with 666 additions and 808 deletions

View File

@ -3,6 +3,7 @@
#include <QNetworkProxy>
#include <QQmlContext>
#include "room.h"
#include "matrix/controller.h"
#include "matrix/roomlistmodel.h"
#include "matrix/imageprovider.h"
@ -19,11 +20,13 @@ int main(int argc, char *argv[])
QGuiApplication app(argc, argv);
// Enable this if you need proxy.
QNetworkProxy proxy;
proxy.setType(QNetworkProxy::HttpProxy);
proxy.setHostName("localhost");
proxy.setPort(1082);
QNetworkProxy::setApplicationProxy(proxy);
// QNetworkProxy proxy;
// proxy.setType(QNetworkProxy::HttpProxy);
// proxy.setHostName("localhost");
// proxy.setPort(1082);
// QNetworkProxy::setApplicationProxy(proxy);
qmlRegisterType<Room>(); qRegisterMetaType<Room*> ("Room*");
qmlRegisterType<Controller>("Matrique", 0, 1, "Controller");
qmlRegisterType<RoomListModel>("Matrique", 0, 1, "RoomListModel");
@ -31,13 +34,12 @@ int main(int argc, char *argv[])
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.rootContext()->setContextProperty("imageProvider", m_provider->getConnection());
engine.addImageProvider(QLatin1String("mxc"), m_provider);
engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;

View File

@ -18,8 +18,7 @@ SOURCES += main.cpp \
matrix/controller.cpp \
matrix/roomlistmodel.cpp \
matrix/imageprovider.cpp \
matrix/messageeventmodel.cpp \
matrix/matriqueroom.cpp
matrix/messageeventmodel.cpp
RESOURCES += \
res.qrc
@ -53,5 +52,4 @@ HEADERS += \
matrix/controller.h \
matrix/roomlistmodel.h \
matrix/imageprovider.h \
matrix/messageeventmodel.h \
matrix/matriqueroom.h
matrix/messageeventmodel.h

View File

@ -3,51 +3,52 @@
#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() {
}
void Controller::login(QString home, QString user, QString pass) {
if(!isLogin) {
if(home.isEmpty()) home = "matrix.org";
void Controller::login() {
if (!isLogin) {
qDebug() << "UserID:" << userID;
qDebug() << "Token:" << token;
qDebug() << "Home:" << home;
m_connection->setHomeserver(QUrl(homeserver));
m_connection->connectWithToken(userID, token, "");
}
}
void Controller::loginWithCredentials(QString serverAddr, QString user, QString pass) {
if(!isLogin) {
qDebug() << "Server:" << serverAddr;
qDebug() << "User:" << user;
qDebug() << "Pass:" << pass;
if(!userID.isEmpty() && !token.isEmpty()) {
qDebug() << "Using token.";
m_connection->connectWithToken(userID, token, "");
} else if(!user.isEmpty() && !pass.isEmpty()) {
if(!user.isEmpty() && !pass.isEmpty()) {
qDebug() << "Using given credential.";
m_connection->connectToServer("@"+user+":"+home, pass, "");
m_connection->setHomeserver(QUrl(serverAddr));
m_connection->connectToServer(user, pass, "");
}
} else {
qDebug() << "You are already logged in.";
}
}
void Controller::setConnection(QMatrixClient::Connection* conn) {
m_connection = conn;
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 = "";
qDebug() << "Logging out.";
setUserID("");
setToken("");
setIsLogin(false);
}
void Controller::connected() {
qDebug() << "Logged in.";
setHomeserver(m_connection->homeserver().toString());
setUserID(m_connection->userId());
setToken(m_connection->accessToken());
m_connection->loadState();

View File

@ -2,9 +2,7 @@
#define CONTROLLER_H
#include <QObject>
#include "libqmatrixclient/connection.h"
#include "roomlistmodel.h"
namespace QMatrixClient {
@ -15,25 +13,27 @@ class Controller : public QObject
{
Q_OBJECT
Q_PROPERTY(QMatrixClient::Connection *connection READ getConnection WRITE setConnection NOTIFY connectionChanged)
Q_PROPERTY(QMatrixClient::Connection* connection READ getConnection NOTIFY connectionChanged)
Q_PROPERTY(bool isLogin READ getIsLogin WRITE setIsLogin NOTIFY isLoginChanged)
Q_PROPERTY(QString homeserver READ getHomeserver WRITE setHomeserver NOTIFY 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:
explicit Controller(QObject *parent = nullptr);
~Controller();
// All the Q_INVOKABLEs.
Q_INVOKABLE void login(QString, QString, QString);
Q_INVOKABLE void login();
Q_INVOKABLE void loginWithCredentials(QString, QString, QString);
Q_INVOKABLE void logout();
// All the non-Q_INVOKABLE functions.
// All the Q_PROPERTYs.
QMatrixClient::Connection* m_connection;
QMatrixClient::Connection* m_connection = new QMatrixClient::Connection();
QMatrixClient::Connection* getConnection() { return m_connection; }
void setConnection(QMatrixClient::Connection* conn);
bool isLogin = false;
bool getIsLogin() { return isLogin; }
@ -62,6 +62,24 @@ class Controller : public QObject
}
}
QString homeserver;
QString getHomeserver() { return homeserver; }
void setHomeserver(QString n) {
if (n != homeserver) {
homeserver = n;
emit homeserverChanged();
}
}
bool busy = false;
bool getBusy() { return busy; }
void setBusy(bool b) {
if (b != busy) {
busy = b;
emit busyChanged();
}
}
private:
void connected();
void resync();
@ -72,7 +90,9 @@ class Controller : public QObject
void isLoginChanged();
void userIDChanged();
void tokenChanged();
void homeServerChanged();
void homeserverChanged();
void busyChanged();
void errorOccured();
public slots:
};

View File

@ -10,13 +10,22 @@
using QMatrixClient::MediaThumbnailJob;
ImageProvider::ImageProvider(QObject *parent)
ImageProviderConnection::ImageProviderConnection(QObject* parent) : QObject(parent) {
}
ImageProviderConnection::~ImageProviderConnection() {
}
ImageProvider::ImageProvider(QObject* parent)
: QQuickImageProvider(QQmlImageProviderBase::Image,
QQmlImageProviderBase::ForceAsynchronousImageLoading)
{
#if (QT_VERSION < QT_VERSION_CHECK(5, 10, 0))
qRegisterMetaType<MediaThumbnailJob*>();
#endif
m_connection = new ImageProviderConnection();
}
QImage ImageProvider::requestImage(const QString& id,
@ -34,9 +43,10 @@ QImage ImageProvider::requestImage(const QString& id,
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); },
[=] { return m_connection->getConnection()->getThumbnail(mxcUri, requestedSize); },
Qt::BlockingQueuedConnection, &job);
#else
QMetaObject::invokeMethod(m_connection, "getThumbnail",
@ -64,9 +74,3 @@ QImage ImageProvider::requestImage(const QString& id,
return result;
}
void ImageProvider::setConnection(QMatrixClient::Connection* connection)
{
QWriteLocker locker(&m_lock);
m_connection = connection;
}

View File

@ -3,26 +3,47 @@
#include <QtQuick/QQuickImageProvider>
#include <QtCore/QReadWriteLock>
#include <QObject>
namespace QMatrixClient {
class Connection;
}
#include "libqmatrixclient/connection.h"
class ImageProviderConnection: public QObject
{
Q_OBJECT
Q_PROPERTY(QMatrixClient::Connection* connection READ getConnection WRITE setConnection NOTIFY connectionChanged)
public:
explicit ImageProviderConnection(QObject* parent = nullptr);
~ImageProviderConnection();
QMatrixClient::Connection* getConnection() { return m_connection; }
Q_INVOKABLE void setConnection(QMatrixClient::Connection* connection) {
qDebug() << "Connection changed.";
emit connectionChanged();
m_connection = connection;
}
private:
QMatrixClient::Connection* m_connection;
signals:
void connectionChanged();
};
class ImageProvider: public QQuickImageProvider
{
public:
explicit ImageProvider(QObject *parent = nullptr);
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);
ImageProviderConnection* getConnection() { return m_connection; }
private:
QMatrixClient::Connection* m_connection;
QReadWriteLock m_lock;
ImageProviderConnection* m_connection;
};
#endif // IMAGEPROVIDER_H

View File

@ -23,7 +23,6 @@ QHash<int, QByteArray> MessageEventModel::roleNames() const
roles[AuthorRole] = "author";
roles[ContentRole] = "content";
roles[ContentTypeRole] = "contentType";
roles[HighlightRole] = "highlight";
roles[ReadMarkerRole] = "readMarker";
roles[SpecialMarksRole] = "marks";
roles[LongOperationRole] = "progressInfo";
@ -38,7 +37,7 @@ MessageEventModel::MessageEventModel(QObject* parent)
qRegisterMetaType<QMatrixClient::FileTransferInfo>();
}
void MessageEventModel::changeRoom(MatriqueRoom* room)
void MessageEventModel::changeRoom(QMatrixClient::Room* room)
{
if (room == m_currentRoom)
return;
@ -114,7 +113,7 @@ inline bool hasValidTimestamp(const QMatrixClient::TimelineItem& ti)
return ti->timestamp().isValid();
}
QDateTime MessageEventModel::makeMessageTimestamp(MatriqueRoom::rev_iter_t baseIt) const
QDateTime MessageEventModel::makeMessageTimestamp(QMatrixClient::Room::rev_iter_t baseIt) const
{
const auto& timeline = m_currentRoom->messageEvents();
auto ts = baseIt->event()->timestamp();
@ -137,7 +136,7 @@ QDateTime MessageEventModel::makeMessageTimestamp(MatriqueRoom::rev_iter_t baseI
return {};
}
QString MessageEventModel::makeDateString(MatriqueRoom::rev_iter_t baseIt) const
QString MessageEventModel::makeDateString(QMatrixClient::Room::rev_iter_t baseIt) const
{
auto date = makeMessageTimestamp(baseIt).toLocalTime().date();
if (QMatrixClient::SettingsGroup("UI")
@ -402,9 +401,6 @@ QVariant MessageEventModel::data(const QModelIndex& index, int role) const
}
}
if(role == HighlightRole)
return m_currentRoom->isEventHighlighted(event);
if(role == ReadMarkerRole)
return event->id() == lastReadEventId;

View File

@ -2,8 +2,7 @@
#define MESSAGEEVENTMODEL_H
#include <QtCore/QAbstractListModel>
#include "matriqueroom.h"
#include "room.h"
class MessageEventModel: public QAbstractListModel
{
@ -13,7 +12,7 @@ class MessageEventModel: public QAbstractListModel
// has to be re-calculated anyway).
// XXX: A better way would be to make [Room::]Timeline a list model
// itself, leaving only representation of the model to a client.
Q_PROPERTY(MatriqueRoom* room MEMBER m_currentRoom CONSTANT)
Q_PROPERTY(QMatrixClient::Room* room MEMBER m_currentRoom CONSTANT)
public:
enum EventRoles {
@ -25,7 +24,6 @@ class MessageEventModel: public QAbstractListModel
AuthorRole,
ContentRole,
ContentTypeRole,
HighlightRole,
ReadMarkerRole,
SpecialMarksRole,
LongOperationRole,
@ -33,7 +31,7 @@ class MessageEventModel: public QAbstractListModel
explicit MessageEventModel(QObject* parent = nullptr);
void changeRoom(MatriqueRoom* room);
void changeRoom(QMatrixClient::Room* room);
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
@ -43,11 +41,11 @@ class MessageEventModel: public QAbstractListModel
void refreshEvent(const QString& eventId);
private:
MatriqueRoom* m_currentRoom;
QMatrixClient::Room* m_currentRoom;
QString lastReadEventId;
QDateTime makeMessageTimestamp(MatriqueRoom::rev_iter_t baseIt) const;
QString makeDateString(MatriqueRoom::rev_iter_t baseIt) const;
QDateTime makeMessageTimestamp(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);
};

View File

@ -1,131 +1,43 @@
#include "roomlistmodel.h"
#include <QtGui/QIcon>
#include "matriqueroom.h"
#include "connection.h"
#include "user.h"
#include <QtGui/QBrush>
#include <QtGui/QColor>
#include <QtCore/QDebug>
RoomListModel::RoomListModel(QObject* parent)
: QAbstractListModel(parent)
{ }
{
m_connection = 0;
}
RoomListModel::~RoomListModel()
{
}
void RoomListModel::setConnection(QMatrixClient::Connection* connection)
{
Q_ASSERT(connection);
using QMatrixClient::Room;
beginResetModel();
m_connection = connection;
connect( connection, &QMatrixClient::Connection::loggedOut,
this, [=]{ deleteConnection(connection); } );
connect( connection, &QMatrixClient::Connection::invitedRoom,
this, &RoomListModel::updateRoom);
connect( connection, &QMatrixClient::Connection::joinedRoom,
this, &RoomListModel::updateRoom);
connect( connection, &QMatrixClient::Connection::leftRoom,
this, &RoomListModel::updateRoom);
connect( connection, &QMatrixClient::Connection::aboutToDeleteRoom,
this, &RoomListModel::deleteRoom);
for( auto r: connection->roomMap() )
doAddRoom(r);
m_rooms.clear();
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();
}
void RoomListModel::deleteConnection(QMatrixClient::Connection* connection) {
QMatrixClient::Room* RoomListModel::roomAt(int row)
{
return m_rooms.at(row);
}
MatriqueRoom* RoomListModel::roomAt(QModelIndex index) const
void RoomListModel::addRoom(QMatrixClient::Room* room)
{
return m_rooms.at(index.row());
}
QModelIndex RoomListModel::indexOf(MatriqueRoom* room) const
{
return index(m_rooms.indexOf(room), 0);
}
void RoomListModel::updateRoom(QMatrixClient::Room* room,
QMatrixClient::Room* prev)
{
// There are two cases when this method is called:
// 1. (prev == nullptr) adding a new room to the room list
// 2. (prev != nullptr) accepting/rejecting an invitation or inviting to
// the previously left room (in both cases prev has the previous state).
if (prev == room)
{
qCritical() << "RoomListModel::updateRoom: room tried to replace itself";
refresh(static_cast<MatriqueRoom*>(room));
return;
}
if (prev && room->id() != prev->id())
{
qCritical() << "RoomListModel::updateRoom: attempt to update room"
<< room->id() << "to" << prev->id();
// That doesn't look right but technically we still can do it.
}
// Ok, we're through with pre-checks, now for the real thing.
auto* newRoom = static_cast<MatriqueRoom*>(room);
const auto it = std::find_if(m_rooms.begin(), m_rooms.end(),
[=](const MatriqueRoom* r) { return r == prev || r == newRoom; });
if (it != m_rooms.end())
{
const int row = it - m_rooms.begin();
// There's no guarantee that prev != newRoom
if (*it == prev && *it != newRoom)
{
prev->disconnect(this);
m_rooms.replace(row, newRoom);
connectRoomSignals(newRoom);
}
emit dataChanged(index(row), index(row));
}
else
{
beginInsertRows(QModelIndex(), m_rooms.count(), m_rooms.count());
doAddRoom(newRoom);
endInsertRows();
}
}
void RoomListModel::deleteRoom(QMatrixClient::Room* room)
{
auto i = m_rooms.indexOf(static_cast<MatriqueRoom*>(room));
if (i == -1)
return; // Already deleted, nothing to do
beginRemoveRows(QModelIndex(), i, i);
m_rooms.removeAt(i);
endRemoveRows();
}
void RoomListModel::doAddRoom(QMatrixClient::Room* r)
{
if (auto* room = static_cast<MatriqueRoom*>(r))
{
m_rooms.append(room);
connectRoomSignals(room);
} else
{
qCritical() << "Attempt to add nullptr to the room list";
Q_ASSERT(false);
}
}
void RoomListModel::connectRoomSignals(MatriqueRoom* room)
{
connect(room, &MatriqueRoom::displaynameChanged,
this, [=]{ displaynameChanged(room); } );
connect( room, &MatriqueRoom::unreadMessagesChanged,
this, [=]{ unreadMessagesChanged(room); } );
connect( room, &MatriqueRoom::notificationCountChanged,
this, [=]{ unreadMessagesChanged(room); } );
connect( room, &MatriqueRoom::joinStateChanged,
this, [=]{ refresh(room); });
connect( room, &MatriqueRoom::avatarChanged,
this, [=]{ refresh(room, { Qt::DecorationRole }); });
beginInsertRows(QModelIndex(), m_rooms.count(), m_rooms.count());
connect( room, &QMatrixClient::Room::namesChanged, this, &RoomListModel::namesChanged );
m_rooms.append(room);
endInsertRows();
}
int RoomListModel::rowCount(const QModelIndex& parent) const
@ -145,83 +57,47 @@ QVariant RoomListModel::data(const QModelIndex& index, int role) const
qDebug() << "UserListModel: something wrong here...";
return QVariant();
}
auto room = m_rooms.at(index.row());
using QMatrixClient::JoinState;
switch (role)
QMatrixClient::Room* room = m_rooms.at(index.row());
if( role == Qt::DisplayRole )
{
case Qt::DisplayRole:
return room->displayName();
case Qt::DecorationRole:
{
if(room->avatarUrl().toString() != "") {
qInfo() << "Room avatar:" << room->avatarUrl();
return room->avatarUrl();
} else if(room->users().length() == 2) {
QMatrixClient::User* user = room->users().at(0);
qInfo() << "User avatar:" << user->avatarUrl();
return user->avatarUrl();
}
}
case Qt::StatusTipRole:
{
return room->topic();
}
case Qt::ToolTipRole:
{
int hlCount = room->highlightCount();
auto result = QStringLiteral("<b>%1</b><br>").arg(room->displayName());
result += tr("Main alias: %1<br>").arg(room->canonicalAlias());
result += tr("Members: %1<br>").arg(room->memberCount());
if (hlCount > 0)
result += tr("Unread mentions: %1<br>").arg(hlCount);
result += tr("ID: %1<br>").arg(room->id());
switch (room->joinState())
{
case JoinState::Join:
result += tr("You joined this room");
break;
case JoinState::Leave:
result += tr("You left this room");
break;
default:
result += tr("You were invited into this room");
}
return result;
}
case HasUnreadRole:
return room->hasUnreadMessages();
case HighlightCountRole:
return room->highlightCount();
case JoinStateRole:
return toCString(room->joinState()); // FIXME: better make the enum QVariant-convertible
default:
return QVariant();
return room->displayName();
}
if( role == Qt::ForegroundRole )
{
if( room->highlightCount() > 0 )
return QBrush(QColor("orange"));
return QVariant();
}
if( role == Qt::DecorationRole )
{
if(room->avatarUrl().toString() != "") {
return room->avatarUrl();
}
return QVariant();
}
if (role == Qt::StatusTipRole )
{
return room->topic();
}
return QVariant();
}
void RoomListModel::namesChanged(QMatrixClient::Room* room)
{
int row = m_rooms.indexOf(room);
emit dataChanged(index(row), index(row));
}
void RoomListModel::unreadMessagesChanged(QMatrixClient::Room* room)
{
int row = m_rooms.indexOf(room);
emit dataChanged(index(row), index(row));
}
QHash<int, QByteArray> RoomListModel::roleNames() const {
QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "name";
roles[Qt::DecorationRole] = "avatar";
roles[Qt::StatusTipRole] = "value";
roles[Qt::StatusTipRole] = "topic";
return roles;
}
void RoomListModel::displaynameChanged(MatriqueRoom* room)
{
refresh(room);
}
void RoomListModel::unreadMessagesChanged(MatriqueRoom* room)
{
refresh(room);
}
void RoomListModel::refresh(MatriqueRoom* room, const QVector<int>& roles)
{
int row = m_rooms.indexOf(room);
if (row == -1)
qCritical() << "Room" << room->id() << "not found in the room list";
else
emit dataChanged(index(row), index(row), roles);
}

View File

@ -2,55 +2,39 @@
#define ROOMLISTMODEL_H
#include <QtCore/QAbstractListModel>
#include "matriqueroom.h"
namespace QMatrixClient
{
class Connection;
class Room;
}
#include "room.h"
#include "connection.h"
class RoomListModel: public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY(QMatrixClient::Connection *connection READ getConnection WRITE setConnection)
public:
enum Roles {
HasUnreadRole = Qt::UserRole + 1,
HighlightCountRole, JoinStateRole
};
RoomListModel(QObject* parent=0);
virtual ~RoomListModel();
explicit RoomListModel(QObject* parent = nullptr);
QMatrixClient::Connection* getConnection() { return m_connection; }
QMatrixClient::Connection* getConnection() {return m_connection;}
void setConnection(QMatrixClient::Connection* connection);
void deleteConnection(QMatrixClient::Connection* connection);
MatriqueRoom* roomAt(QModelIndex index) const;
QModelIndex indexOf(MatriqueRoom* room) const;
Q_INVOKABLE QMatrixClient::Room* roomAt(int row);
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
Q_INVOKABLE int rowCount(const QModelIndex& parent=QModelIndex()) const override;
QVariant data(const QModelIndex& index, int role) const override;
QHash<int, QByteArray> roleNames() const;
int rowCount(const QModelIndex& parent) const override;
private slots:
void displaynameChanged(MatriqueRoom* room);
void unreadMessagesChanged(MatriqueRoom* room);
void refresh(MatriqueRoom* room, const QVector<int>& roles = {});
void updateRoom(QMatrixClient::Room* room,
QMatrixClient::Room* prev);
void deleteRoom(QMatrixClient::Room* room);
void namesChanged(QMatrixClient::Room* room);
void unreadMessagesChanged(QMatrixClient::Room* room);
void addRoom(QMatrixClient::Room* room);
private:
QMatrixClient::Connection* m_connection;
QList<MatriqueRoom*> m_rooms;
QList<QMatrixClient::Room*> m_rooms;
void doAddRoom(QMatrixClient::Room* r);
void connectRoomSignals(MatriqueRoom* room);
signals:
void connectionChanged();
};
#endif // ROOMLISTMODEL_H

View File

@ -1,20 +0,0 @@
import QtQuick 2.10
import QtQuick.Controls 2.3
import "qrc:/qml/form"
Page {
property var contactListModel
ListForm {
id: roomListForm
height: parent.height
width: 320
listModel: contactListModel
}
DetailForm {
id: detailForm
anchors.fill: parent
anchors.leftMargin: roomListForm.width
}
}

View File

@ -9,18 +9,6 @@ import "qrc:/qml/component"
Page {
property var controller
property alias homeserver: settings.server
property alias username: settings.user
property alias password: settings.pass
Settings {
id: settings
property alias server: serverField.text
property alias user: usernameField.text
property alias pass: passwordField.text
}
Row {
anchors.fill: parent
@ -68,29 +56,33 @@ Page {
height: parent.height
padding: 64
Column {
id: main_col
spacing: 8
anchors.fill: parent
ColumnLayout {
id: mainCol
width: parent.width
ImageStatus {
width: 96
height: width
Layout.preferredWidth: 96
Layout.preferredHeight: 96
Layout.alignment: Qt.AlignHCenter
source: "qrc:/asset/img/avatar.png"
anchors.horizontalCenter: parent.horizontalCenter
}
TextField {
id: serverField
width: parent.width
height: 48
placeholderText: "Server"
Layout.fillWidth: true
leftPadding: 16
topPadding: 0
bottomPadding: 0
placeholderText: "Server"
background: Rectangle {
color: "#eaeaea"
implicitHeight: 48
color: Material.theme == Material.Light ? "#eaeaea" : "#242424"
border.color: parent.activeFocus ? Material.accent : "transparent"
border.width: 2
}
@ -98,15 +90,19 @@ Page {
TextField {
id: usernameField
width: parent.width
height: 48
placeholderText: "Username"
Layout.fillWidth: true
leftPadding: 16
topPadding: 0
bottomPadding: 0
placeholderText: "Username"
background: Rectangle {
color: "#eaeaea"
implicitHeight: 48
color: Material.theme == Material.Light ? "#eaeaea" : "#242424"
border.color: parent.activeFocus ? Material.accent : "transparent"
border.width: 2
}
@ -114,15 +110,20 @@ Page {
TextField {
id: passwordField
width: parent.width
height: 48
placeholderText: "Password"
Layout.fillWidth: true
leftPadding: 16
topPadding: 0
bottomPadding: 0
placeholderText: "Password"
echoMode: TextInput.Password
background: Rectangle {
color: "#eaeaea"
implicitHeight: 48
color: Material.theme == Material.Light ? "#eaeaea" : "#242424"
border.color: parent.activeFocus ? Material.accent : "transparent"
border.width: 2
}
@ -130,20 +131,13 @@ Page {
Button {
id: loginButton
Layout.fillWidth: true
text: "LOGIN"
highlighted: true
width: parent.width
onClicked: controller.login(homeserver, username, password)
}
Button {
id: logoutButton
text: "LOGOUT"
flat: true
width: parent.width
onClicked: controller.logout()
onClicked: controller.loginWithCredentials(serverField.text, usernameField.text, passwordField.text)
}
}
}

View File

@ -1,24 +1,47 @@
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import Matrique 0.1
import "qrc:/qml/form"
import Matrique 0.1
Page {
property RoomListModel roomListModel
property alias connection: roomListModel.connection
ListForm {
id: roomListForm
height: parent.height
width: 320
listModel: roomListModel
id: page
RoomListModel {
id: roomListModel
}
RoomForm {
id: roomForm
RowLayout {
anchors.fill: parent
anchors.leftMargin: roomListForm.width
roomIndex: roomListForm.currentIndex
spacing: 0
ListForm {
id: roomListForm
Layout.fillHeight: true
// Layout.preferredWidth: {
// if (page.width > 560) {
// return page.width * 0.4;
// } else {
// return 80;
// }
// }
Layout.preferredWidth: 320
Layout.maximumWidth: 360
listModel: roomListModel
}
RoomForm {
id: roomForm
Layout.fillWidth: true
Layout.fillHeight: true
currentRoom: roomListForm.currentIndex != -1 ? roomListModel.roomAt(roomListForm.currentIndex) : null
}
}
}

View File

@ -1,58 +0,0 @@
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtQuick.Controls.Material 2.3
Page {
property alias theme: themeSwitch.checked
header: TabBar {
id: settingBar
width: parent.width
z: 10
currentIndex: settingBar.currentIndex
TabButton {
text: qsTr("Overview")
}
TabButton {
text: qsTr("Interface")
}
TabButton {
text: qsTr("Network")
}
TabButton {
text: qsTr("Sync")
}
}
SwipeView {
id: settingSwipe
currentIndex: settingBar.currentIndex
anchors.fill: parent
Page {
}
Page {
Column {
width: parent.width
Switch {
id: themeSwitch
text: qsTr("Dark Theme")
}
}
}
Page {
}
Page {
}
}
}

View File

@ -1,76 +0,0 @@
import QtQuick 2.10
import QtQuick.Controls 2.3
Rectangle {
id: root
property Connection currentConnection: null
property var currentRoom: null
function setRoom(room) {
currentRoom = room
messageModel.changeRoom(room)
}
function setConnection(conn) {
currentConnection = conn
messageModel.setConnection(conn)
}
function sendLine(text) {
if(!currentRoom || !currentConnection) return
currentConnection.postMessage(currentRoom, "m.text", text)
}
ListView {
id: chatView
anchors.fill: parent
flickableDirection: Flickable.VerticalFlick
verticalLayoutDirection: ListView.BottomToTop
model: MessageEventModel { id: messageModel }
delegate: Row {
id: message
width: parent.width
spacing: 8
Label {
id: timelabel
text: time.toLocaleTimeString("hh:mm:ss")
color: "grey"
}
Label {
width: 64
elide: Text.ElideRight
text: eventType == "message" ? author : "***"
color: eventType == "message" ? "grey" : "lightgrey"
horizontalAlignment: Text.AlignRight
}
Label {
text: content
wrapMode: Text.Wrap
width: parent.width - (x - parent.x) - spacing
color: eventType == "message" ? "black" : "lightgrey"
}
}
section {
property: "date"
labelPositioning: ViewSection.CurrentLabelAtStart
delegate: Rectangle {
width: parent.width
height: childrenRect.height
Label {
width: parent.width
text: section.toLocaleString(Qt.locale())
color: "grey"
horizontalAlignment: Text.AlignRight
}
}
}
onAtYBeginningChanged: {
if(currentRoom && atYBeginning) currentRoom.getPreviousContent()
}
}
}

View File

@ -1,30 +1,31 @@
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtQuick 2.11
import QtQuick.Controls 2.4
import QtGraphicalEffects 1.0
Item {
property bool statusIndicator: false
property bool opaqueBackground: false
property alias source: avatar.source
id: item
Rectangle {
width: parent.width
height: parent.width
radius: parent.width / 2
width: item.width
height: item.width
radius: item.width / 2
color: "white"
visible: opaqueBackground
}
Image {
id: avatar
width: parent.width
height: parent.width
width: item.width
height: item.width
mipmap: true
layer.enabled: true
fillMode: Image.PreserveAspectCrop
sourceSize.width: parent.width
sourceSize.height: parent.width
sourceSize.width: item.width
sourceSize.height: item.width
layer.effect: OpacityMask {
maskSource: Item {
@ -38,15 +39,5 @@ Item {
}
}
}
Rectangle {
width: parent.width
height: parent.width
radius: parent.width / 2
color: "transparent"
border.color: "#4caf50"
border.width: 4
visible: statusIndicator
}
}
}

View File

@ -1,10 +1,11 @@
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import QtQuick.Controls.Material 2.3
Item {
property alias icon: iconText.text
property var color: "white"
property var color: Material.theme == Material.Light ? "black" : "white"
id: item

View File

@ -3,15 +3,9 @@ import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import QtQuick.Controls.Material 2.3
Drawer {
property SwipeView swipeView
interactive: false
position: 1.0
visible: true
modal: false
background: Rectangle {
Item {
Rectangle {
anchors.fill: parent
color: Material.accent
}
}

View File

@ -4,7 +4,7 @@ import QtQuick.Layouts 1.3
import QtQuick.Controls.Material 2.3
Item {
property Item page
property var page
property alias contentItem: buttonDelegate.contentItem
signal clicked

View File

@ -50,28 +50,14 @@ Item {
width: parent.height
height: parent.height
contentItem: Text {
text: "\ue0b7"
font.pointSize: 16
font.family: materialFont.name
color: "white"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
contentItem: MaterialIcon { icon: "\ue0b7" }
}
ItemDelegate {
width: parent.height
height: parent.height
contentItem: Text {
text: "\ue62e"
font.pointSize: 16
font.family: materialFont.name
color: "white"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
contentItem: MaterialIcon { icon: "\ue62e" }
}
}
}

View File

@ -1,13 +1,97 @@
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import QtQuick 2.11
import QtQuick.Controls 2.4
import QtQuick.Layouts 1.11
import QtGraphicalEffects 1.0
import QtQuick.Controls.Material 2.3
import QtQml.Models 2.3
import Matrique 0.1
import "qrc:/qml/component"
Item {
property var listModel
property alias listModel: delegateModel.model
property alias currentIndex: listView.currentIndex
readonly property bool mini: width <= 80 // Used as an indicator of whether the listform should be displayed as "Mini mode".
DelegateModel {
id: delegateModel
groups: [
DelegateModelGroup {
name: "filterGroup"; includeByDefault: true
}
]
filterOnGroup: "filterGroup"
delegate: ItemDelegate {
width: parent.width
height: 80
onClicked: listView.currentIndex = index
contentItem: RowLayout {
anchors.fill: parent
anchors.margins: 16
spacing: 16
ImageStatus {
Layout.preferredWidth: height
Layout.fillHeight: true
source: avatar == null || avatar == "" ? "qrc:/asset/img/avatar.png" : "image://mxc/" + avatar
opaqueBackground: true
}
ColumnLayout {
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignHCenter
Label {
Layout.fillWidth: true
Layout.fillHeight: true
text: {
if (name != "") {
return name;
}
if (alias != "") {
return alias;
}
return id
}
font.pointSize: 16
elide: Text.ElideRight
wrapMode: Text.NoWrap
}
Label {
Layout.fillWidth: true
Layout.fillHeight: true
text: topic === "" ? "No topic yet." : topic
elide: Text.ElideRight
wrapMode: Text.NoWrap
}
}
}
}
function applyFilter(filterName){
var roomCount = listModel.rowCount();
for (var i = 0; i < roomCount; i++){
var roomName = "";
if (listModel.roomAt(i).name != "") {
roomName = listModel.roomAt(i).name;
} else if (model.alias != "") {
roomName = listModel.roomAt(i).alias;
} else {
roomName = listModel.roomAt(i).id;
}
if (roomName.toLowerCase().indexOf(filterName.toLowerCase()) !== -1) {
items.addGroups(i, 1, "filterGroup");
} else {items.removeGroups(i, 1, "filterGroup");}
}
}
}
ColumnLayout {
anchors.fill: parent
@ -22,10 +106,10 @@ Item {
}
TextField {
id: serverField
id: searchField
width: parent.width
height: 36
leftPadding: 16
leftPadding: mini ? 4 : 16
topPadding: 0
bottomPadding: 0
anchors.verticalCenter: parent.verticalCenter
@ -34,19 +118,17 @@ Item {
Row {
anchors.fill: parent
Text {
width: parent.height
height: parent.height
text: "\ue8b6"
font.pointSize: 16
font.family: materialFont.name
MaterialIcon {
icon: "\ue8b6"
color: "white"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
width: mini ? parent.width : parent.height
height: parent.height
}
Text {
height: parent.height
visible: !mini
text: "Search"
color: "white"
font.pointSize: 12
@ -56,15 +138,19 @@ Item {
}
Rectangle {
width: serverField.activeFocus || serverField.text != "" ? parent.width : 0
width: searchField.activeFocus || searchField.text != "" ? parent.width : 0
height: parent.height
color: "white"
Behavior on width {
PropertyAnimation { easing.type: Easing.InOutQuad; duration: 200 }
PropertyAnimation { easing.type: Easing.InOutCubic; duration: 200 }
}
}
}
onTextChanged: {
delegateModel.applyFilter(text);
}
}
}
@ -77,13 +163,12 @@ Item {
anchors.fill: parent
Rectangle {
anchors.fill: parent
color: "#eaeaea"
color: Material.theme == Material.Light ? "#eaeaea" : "#242424"
}
Text {
Label {
z: 10
text: "Here? No, not here."
color: "#424242"
text: mini ? "Empty" : "Here? No, not here."
anchors.centerIn: parent
visible: listView.count === 0
}
@ -94,53 +179,15 @@ Item {
width: parent.width
height: parent.height
model: listModel
highlight: Rectangle {
color: Material.accent
opacity: 0.2
}
highlightMoveDuration: 250
ScrollBar.vertical: ScrollBar { id: scrollBar }
delegate: ItemDelegate {
width: parent.width
height: 80
onClicked: listView.currentIndex = index
contentItem: Row {
width: parent.width - 32
height: parent.height - 32
spacing: 16
ImageStatus {
width: parent.height
height: parent.height
source: avatar == "" ? "qrc:/asset/img/avatar.png" : "image://mxc/" + avatar
opaqueBackground: true
}
Column {
width: parent.width - parent.height - parent.spacing
height: parent.height
Text {
width: parent.width
text: name
color: "#424242"
font.pointSize: 16
elide: Text.ElideRight
wrapMode: Text.NoWrap
}
Text {
width: parent.width
text: value
color: "#424242"
elide: Text.ElideRight
wrapMode: Text.NoWrap
}
}
}
}
model: delegateModel
}
}
}

View File

@ -3,123 +3,171 @@ import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import QtQuick.Controls.Material 2.3
import QtGraphicalEffects 1.0
import Matrique 0.1
import "qrc:/qml/component"
Item {
property int roomIndex
id: item
property var currentRoom
ColumnLayout {
Pane {
anchors.fill: parent
spacing: 0
padding: 0
Pane {
z: 10
padding: 16
Layout.fillWidth: true
Layout.preferredHeight: 80
background: Rectangle {
color: "#eaeaea"
background: Item {
anchors.fill: parent
visible: currentRoom == null
Pane {
anchors.fill: parent
}
Row {
anchors.fill: parent
spacing: 16
ImageStatus {
width: parent.height
height: parent.height
source: "qrc:/asset/img/avatar.png"
}
Column {
height: parent.height
Text {
text: "Astolfo"
font.pointSize: 18
color: "#424242"
}
Text {
text: "Rider of Black"
color: "#424242"
}
}
Label {
z: 10
text: "Please choose a room."
anchors.centerIn: parent
}
}
Pane {
Layout.fillWidth: true
Layout.fillHeight: true
}
ColumnLayout {
anchors.fill: parent
spacing: 0
Pane {
z: 10
padding: 16
visible: currentRoom != null
Layout.fillWidth: true
Layout.preferredHeight: 80
Pane {
z: 10
padding: 16
RowLayout {
anchors.fill: parent
spacing: 0
Layout.fillWidth: true
Layout.preferredHeight: 80
ItemDelegate {
Layout.preferredWidth: height
Layout.fillHeight: true
background: Rectangle {
color: Material.theme == Material.Light ? "#eaeaea" : "#242424"
}
contentItem: Text {
text: "\ue226"
// color: "#424242"
font.pointSize: 16
font.family: materialFont.name
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
RowLayout {
anchors.fill: parent
spacing: 16
ImageStatus {
Layout.preferredWidth: parent.height
Layout.fillHeight: true
source: "qrc:/asset/img/avatar.png"
}
ColumnLayout {
Layout.fillWidth: true
Layout.fillHeight: true
Label {
Layout.fillWidth: true
text: currentRoom != null ? currentRoom.name : ""
font.pointSize: 16
elide: Text.ElideRight
wrapMode: Text.NoWrap
}
Label {
Layout.fillWidth: true
text: currentRoom != null ? currentRoom.topic : ""
elide: Text.ElideRight
wrapMode: Text.NoWrap
}
}
}
}
ListView {
id: messageListView
Layout.fillWidth: true
Layout.fillHeight: true
Layout.leftMargin: 16
Layout.rightMargin: 16
displayMarginBeginning: 40
displayMarginEnd: 40
verticalLayoutDirection: ListView.BottomToTop
spacing: 12
// model: MessageEventModel{ currentRoom: item.currentRoom }
model: 10
delegate: Row {
readonly property bool sentByMe: index % 2 == 0
id: messageRow
height: 40
anchors.right: sentByMe ? parent.right : undefined
spacing: 6
Rectangle {
id: avatar
width: height
height: parent.height
color: "grey"
visible: !sentByMe
}
Rectangle {
width: Math.min(messageText.implicitWidth + 24,
messageListView.width - (!sentByMe ? avatar.width + messageRow.spacing : 0))
height: parent.height
color: sentByMe ? "lightgrey" : Material.accent
Label {
id: messageText
text: index
color: sentByMe ? "black" : "white"
anchors.fill: parent
anchors.margins: 12
wrapMode: Label.Wrap
}
}
}
TextField {
Layout.fillWidth: true
Layout.fillHeight: true
placeholderText: "Send a Message"
leftPadding: 16
topPadding: 0
bottomPadding: 0
ScrollBar.vertical: ScrollBar { /*anchors.left: messageListView.right*/ }
}
background: Rectangle {
color: "#eaeaea"
}
}
Pane {
z: 10
padding: 16
ItemDelegate {
Layout.preferredWidth: height
Layout.fillHeight: true
Layout.fillWidth: true
Layout.preferredHeight: 80
contentItem: Text {
text: "\ue24e"
// color: parent.pressed ? Material.accent : "#424242"
font.pointSize: 16
font.family: materialFont.name
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
RowLayout {
anchors.fill: parent
spacing: 0
ItemDelegate {
Layout.preferredWidth: height
Layout.fillHeight: true
contentItem: MaterialIcon { icon: "\ue226" }
}
background: Rectangle {
color: "#eaeaea"
TextField {
Layout.fillWidth: true
Layout.fillHeight: true
placeholderText: "Send a Message"
leftPadding: 16
topPadding: 0
bottomPadding: 0
selectByMouse: true
background: Rectangle {
color: Material.theme == Material.Light ? "#eaeaea" : "#242424"
}
}
}
ItemDelegate {
Layout.preferredWidth: height
Layout.fillHeight: true
ItemDelegate {
Layout.preferredWidth: height
Layout.fillHeight: true
contentItem: Text {
text: "\ue163"
// color: "#424242"
font.pointSize: 16
font.family: materialFont.name
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
contentItem: MaterialIcon { icon: "\ue24e" }
background: Rectangle {
color: Material.theme == Material.Light ? "#eaeaea" : "#242424"
}
}
}
}

View File

@ -1,138 +1,167 @@
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import QtQuick.Controls.Material 2.2
import QtQuick 2.11
import QtQuick.Controls 2.4
import QtQuick.Layouts 1.4
import QtQuick.Controls.Material 2.4
import QtGraphicalEffects 1.0
import Qt.labs.settings 1.0
import "qrc:/qml/component"
import "qrc:/qml/form"
import Qt.labs.platform 1.0 as Platform
import Matrique 0.1
import "component"
import "form"
ApplicationWindow {
id: window
visible: true
width: 960
height: 640
minimumWidth: 320
minimumHeight: 320
title: qsTr("Matrique")
Material.theme: settingPage.theme ? Material.Dark : Material.Light
Controller {
id: matrixController
connection: m_connection
}
RoomListModel {
id: roomListModel
connection: m_connection
}
Settings {
id: settings
property alias userID: matrixController.userID
property alias token: matrixController.token
}
FontLoader { id: materialFont; source: "qrc:/asset/font/material.ttf" }
SideNav {
id: sideNav
width: 80
height: window.height
Settings {
id: setting
property alias homeserver: matriqueController.homeserver
property alias userID: matriqueController.userID
property alias token: matriqueController.token
}
ColumnLayout {
anchors.fill: parent
spacing: 0
// Platform.SystemTrayIcon {
// visible: true
// iconSource: "qrc:/asset/img/icon.png"
SideNavButton {
contentItem: ImageStatus {
width: parent.width
height: parent.width
source: "qrc:/asset/img/avatar.png"
anchors.horizontalCenter: parent.horizontalCenter
statusIndicator: true
opaqueBackground: false
}
// onActivated: {
// window.show()
// window.raise()
// window.requestActivate()
// }
// }
page: Room {
id: roomPage
roomListModel: roomListModel
}
}
Rectangle {
color: "transparent"
Layout.fillHeight: true
}
SideNavButton {
contentItem: Text {
text: "\ue853"
font.pointSize: 16
font.family: materialFont.name
color: "white"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
page: Login {
id: loginPage
controller: matrixController
}
}
SideNavButton {
contentItem: Text {
text: "\ue5d2"
font.pointSize: 16
font.family: materialFont.name
color: "white"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
page: Contact {
id: contactPage
contactListModel: roomListModel
}
}
SideNavButton {
contentItem: Text {
text: "\ue8b8"
font.pointSize: 16
font.family: materialFont.name
color: "white"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
page: Setting {
id: settingPage
}
}
SideNavButton {
contentItem: Text {
text: "\ue879"
font.pointSize: 16
font.family: materialFont.name
color: "white"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
onClicked: Qt.quit()
}
Controller {
id: matriqueController
onErrorOccured: {
errorDialog.text = err;
errorDialog.open();
}
}
StackView {
id: stackView
Popup {
property bool busy: matriqueController.busy
id: busyPopup
x: (window.width - width) / 2
y: (window.height - height) / 2
modal: true
focus: true
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
BusyIndicator { running: true }
onBusyChanged: {
if(busyPopup.busy) { busyPopup.open(); }
else { busyPopup.close(); }
}
}
Dialog {
property alias text: errorLabel.text
id: errorDialog
width: 360
modal: true
title: "ERROR"
x: (window.width - width) / 2
y: (window.height - height) / 2
standardButtons: Dialog.Ok
Label {
id: errorLabel
width: parent.width
text: "Label"
wrapMode: Text.Wrap
}
}
Component {
id: loginPage
Login { controller: matriqueController }
}
Room {
id: roomPage
connection: matriqueController.connection
}
RowLayout {
anchors.fill: parent
anchors.leftMargin: sideNav.width
initialItem: roomPage
spacing: 0
SideNav {
id: sideNav
Layout.preferredWidth: 80
Layout.fillHeight: true
ColumnLayout {
anchors.fill: parent
spacing: 0
SideNavButton {
id: statusNavButton
contentItem: ImageStatus {
anchors.fill: parent
anchors.margins: 15
source: "qrc:/asset/img/avatar.png"
opaqueBackground: false
}
page: roomPage
}
Rectangle {
color: "transparent"
Layout.fillHeight: true
}
SideNavButton {
contentItem: MaterialIcon { icon: "\ue8b8"; color: "white" }
onClicked: matriqueController.logout()
}
SideNavButton {
contentItem: MaterialIcon { icon: "\ue879"; color: "white" }
onClicked: Qt.quit()
}
}
}
StackView {
id: stackView
initialItem: roomPage
Layout.fillWidth: true
Layout.fillHeight: true
}
}
Component.onCompleted: {
imageProvider.setConnection(matriqueController.connection)
imageProvider.connection = matriqueController.connection
console.log(matriqueController.homeserver, matriqueController.userID, matriqueController.token)
if (matriqueController.userID != "" && matriqueController.token != "") {
console.log("Perform auto-login.");
matriqueController.login();
} else {
stackView.replace(loginPage);
}
}
}

View File

@ -6,7 +6,6 @@
<file>asset/font/material.ttf</file>
<file>qml/Login.qml</file>
<file>qml/main.qml</file>
<file>qml/Setting.qml</file>
<file>qml/component/ButtonDelegate.qml</file>
<file>qml/component/ImageStatus.qml</file>
<file>qml/component/SideNav.qml</file>
@ -14,8 +13,8 @@
<file>qml/Room.qml</file>
<file>qml/form/DetailForm.qml</file>
<file>qml/form/ListForm.qml</file>
<file>qml/Contact.qml</file>
<file>qml/component/ChatRoom.qml</file>
<file>qml/component/SideNavButton.qml</file>
<file>qml/component/MaterialIcon.qml</file>
<file>asset/img/icon.png</file>
</qresource>
</RCC>