Uses MatriqueRoom inherited from QMatrixClient::Room and rewrite related
objects.
This commit is contained in:
parent
6640b172d5
commit
3a7f182c52
|
@ -25,7 +25,8 @@ SOURCES += src/main.cpp \
|
||||||
src/imageprovider.cpp \
|
src/imageprovider.cpp \
|
||||||
src/messageeventmodel.cpp \
|
src/messageeventmodel.cpp \
|
||||||
src/imageproviderconnection.cpp \
|
src/imageproviderconnection.cpp \
|
||||||
src/emojimodel.cpp
|
src/emojimodel.cpp \
|
||||||
|
src/matriqueroom.cpp
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
res.qrc
|
res.qrc
|
||||||
|
@ -66,7 +67,8 @@ HEADERS += \
|
||||||
src/imageprovider.h \
|
src/imageprovider.h \
|
||||||
src/messageeventmodel.h \
|
src/messageeventmodel.h \
|
||||||
src/imageproviderconnection.h \
|
src/imageproviderconnection.h \
|
||||||
src/emojimodel.h
|
src/emojimodel.h \
|
||||||
|
src/matriqueroom.h
|
||||||
|
|
||||||
unix:!mac {
|
unix:!mac {
|
||||||
metainfo.files = $$PWD/org.eu.encom.matrique.appdata.xml
|
metainfo.files = $$PWD/org.eu.encom.matrique.appdata.xml
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
Matrique is a glossy cross-platform client for Matrix, the decentralized communication protocol for instant messaging.
|
Matrique is a glossy cross-platform client for Matrix, the decentralized communication protocol for instant messaging.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
The source code is generally available at <a href="https://gitlab.com/b0/matrique" target="_blank">Gitlab</a>
|
The source code is generally available at https://gitlab.com/b0/matrique
|
||||||
</p>
|
</p>
|
||||||
</description>
|
</description>
|
||||||
<screenshots>
|
<screenshots>
|
||||||
|
|
|
@ -12,8 +12,6 @@ AvatarContainer {
|
||||||
|
|
||||||
id: messageRow
|
id: messageRow
|
||||||
|
|
||||||
Audio { id: audioPlayer }
|
|
||||||
|
|
||||||
DownloadableContent {
|
DownloadableContent {
|
||||||
id: downloadable
|
id: downloadable
|
||||||
|
|
||||||
|
@ -37,7 +35,7 @@ AvatarContainer {
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (downloadable.downloaded)
|
if (downloadable.downloaded)
|
||||||
play()
|
matriqueController.playAudio(progressInfo.localPath)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
playOnFinished = true
|
playOnFinished = true
|
||||||
|
@ -46,11 +44,7 @@ AvatarContainer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onDownloadedChanged: downloaded && playOnFinished ? play() : {}
|
onDownloadedChanged: downloaded && playOnFinished ? matriqueController.playAudio(progressInfo.localPath) : {}
|
||||||
}
|
}
|
||||||
|
|
||||||
function play() {
|
|
||||||
audioPlayer.source = progressInfo.localPath
|
|
||||||
audioPlayer.play()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ Item {
|
||||||
onDownloadedChanged: downloaded && openOnFinished ? openSavedFile() : {}
|
onDownloadedChanged: downloaded && openOnFinished ? openSavedFile() : {}
|
||||||
|
|
||||||
function saveFileAs() {
|
function saveFileAs() {
|
||||||
matriqueController.saveFileAs(currentRoom, eventId)
|
currentRoom.saveFileAs(eventId)
|
||||||
}
|
}
|
||||||
|
|
||||||
function downloadAndOpen()
|
function downloadAndOpen()
|
||||||
|
|
|
@ -303,20 +303,7 @@ Item {
|
||||||
|
|
||||||
contentItem: MaterialIcon { icon: "\ue226" }
|
contentItem: MaterialIcon { icon: "\ue226" }
|
||||||
|
|
||||||
onClicked: {
|
onClicked: currentRoom.chooseAndUploadFile()
|
||||||
var fileTransferProgressCallback = function(id, sent, total) {
|
|
||||||
inputField.progress = sent / total
|
|
||||||
}
|
|
||||||
var completedCallback = function(id, localFile, mxcUrl) {
|
|
||||||
inputField.progress = 0
|
|
||||||
currentRoom.fileTransferCompleted.disconnect(fileTransferProgressCallback)
|
|
||||||
currentRoom.fileTransferCompleted.disconnect(completedCallback)
|
|
||||||
}
|
|
||||||
|
|
||||||
currentRoom.fileTransferProgress.connect(fileTransferProgressCallback)
|
|
||||||
currentRoom.fileTransferCompleted.connect(completedCallback)
|
|
||||||
matriqueController.uploadFile(currentRoom)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TextField {
|
TextField {
|
||||||
|
@ -340,14 +327,6 @@ Item {
|
||||||
|
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
color: Material.theme == Material.Light ? "#eaeaea" : "#242424"
|
color: Material.theme == Material.Light ? "#eaeaea" : "#242424"
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
z: 5
|
|
||||||
width: inputField.width * inputField.progress
|
|
||||||
height: parent.height
|
|
||||||
color: Material.accent
|
|
||||||
opacity: 0.4
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function postMessage(text) {
|
function postMessage(text) {
|
||||||
|
|
|
@ -217,8 +217,8 @@ Item {
|
||||||
|
|
||||||
contentItem: Label { text: "Accept this invitation?" }
|
contentItem: Label { text: "Accept this invitation?" }
|
||||||
|
|
||||||
onAccepted: matriqueController.acceptRoom(currentRoom)
|
onAccepted: currentRoom.acceptInvitation()
|
||||||
onRejected: matriqueController.rejectRoom(currentRoom)
|
onRejected: currentRoom.rejectInvitation()
|
||||||
}
|
}
|
||||||
|
|
||||||
Menu {
|
Menu {
|
||||||
|
@ -243,7 +243,7 @@ Item {
|
||||||
}
|
}
|
||||||
MenuItem {
|
MenuItem {
|
||||||
text: "Leave Room"
|
text: "Leave Room"
|
||||||
onTriggered: matriqueController.forgetRoom(currentRoom.id)
|
onTriggered: currentRoom.forget()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,10 +36,13 @@ Page {
|
||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
text: "Logout"
|
text: "Logout"
|
||||||
highlighted: true
|
highlighted: true
|
||||||
|
|
||||||
onClicked: matriqueController.logout()
|
onClicked: {
|
||||||
|
matriqueController.logout()
|
||||||
|
Qt.quit()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,17 @@
|
||||||
#include "controller.h"
|
#include "controller.h"
|
||||||
|
|
||||||
#include "connection.h"
|
#include "matriqueroom.h"
|
||||||
|
|
||||||
#include "events/eventcontent.h"
|
#include "events/eventcontent.h"
|
||||||
#include "events/roommessageevent.h"
|
#include "events/roommessageevent.h"
|
||||||
|
|
||||||
#include "csapi/create_room.h"
|
|
||||||
#include "csapi/joining.h"
|
#include "csapi/joining.h"
|
||||||
#include "csapi/leaving.h"
|
|
||||||
|
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
#include <QFile>
|
|
||||||
#include <QFileDialog>
|
|
||||||
#include <QImage>
|
|
||||||
|
|
||||||
Controller::Controller(QObject* parent) : QObject(parent) {
|
Controller::Controller(QObject* parent) : QObject(parent) {
|
||||||
|
Connection::setRoomType<MatriqueRoom>();
|
||||||
|
|
||||||
connect(m_connection, &Connection::connected, this, &Controller::connected);
|
connect(m_connection, &Connection::connected, this, &Controller::connected);
|
||||||
connect(m_connection, &Connection::resolveError, this,
|
connect(m_connection, &Connection::resolveError, this,
|
||||||
&Controller::reconnect);
|
&Controller::reconnect);
|
||||||
|
@ -33,15 +31,15 @@ Controller::~Controller() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::login() {
|
void Controller::login() {
|
||||||
if (!isLogin) {
|
if (!m_isLogin) {
|
||||||
m_connection->setHomeserver(QUrl(homeserver));
|
m_connection->setHomeserver(QUrl(m_homeserver));
|
||||||
m_connection->connectWithToken(userID, token, "");
|
m_connection->connectWithToken(m_userID, m_token, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::loginWithCredentials(QString serverAddr, QString user,
|
void Controller::loginWithCredentials(QString serverAddr, QString user,
|
||||||
QString pass) {
|
QString pass) {
|
||||||
if (!isLogin) {
|
if (!m_isLogin) {
|
||||||
if (!user.isEmpty() && !pass.isEmpty()) {
|
if (!user.isEmpty() && !pass.isEmpty()) {
|
||||||
m_connection->setHomeserver(QUrl(serverAddr));
|
m_connection->setHomeserver(QUrl(serverAddr));
|
||||||
m_connection->connectToServer(user, pass, "");
|
m_connection->connectToServer(user, pass, "");
|
||||||
|
@ -71,48 +69,7 @@ void Controller::resync() { m_connection->sync(30000); }
|
||||||
|
|
||||||
void Controller::reconnect() {
|
void Controller::reconnect() {
|
||||||
qDebug() << "Connection lost. Reconnecting...";
|
qDebug() << "Connection lost. Reconnecting...";
|
||||||
m_connection->connectWithToken(userID, token, "");
|
m_connection->connectWithToken(m_userID, m_token, "");
|
||||||
}
|
|
||||||
|
|
||||||
void Controller::uploadFile(Room* room) {
|
|
||||||
if (!room) return;
|
|
||||||
auto localFile = QFileDialog::getOpenFileUrl(Q_NULLPTR, tr("Save File as"));
|
|
||||||
if (!localFile.isEmpty()) {
|
|
||||||
room->uploadFile(localFile.toString(), localFile, getMIME(localFile));
|
|
||||||
QMetaObject::Connection* const connection = new QMetaObject::Connection;
|
|
||||||
*connection = connect(room, &Room::fileTransferCompleted,
|
|
||||||
[=](QString id, QUrl localFile, QUrl mxcUrl) {
|
|
||||||
disconnect(*connection);
|
|
||||||
postFile(room, localFile, mxcUrl);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Controller::postFile(Room* room, const QUrl& localFile,
|
|
||||||
const QUrl& mxcUrl) {
|
|
||||||
const QString mime = getMIME(localFile);
|
|
||||||
const QString fileName = localFile.fileName();
|
|
||||||
QString msgType = "m.file";
|
|
||||||
if (mime.startsWith("image")) msgType = "m.image";
|
|
||||||
if (mime.startsWith("video")) msgType = "m.video";
|
|
||||||
if (mime.startsWith("audio")) msgType = "m.audio";
|
|
||||||
QJsonObject json{QJsonObject{{"msgtype", msgType},
|
|
||||||
{"body", fileName},
|
|
||||||
{"filename", fileName},
|
|
||||||
{"url", mxcUrl.url()}}};
|
|
||||||
room->postJson("m.room.message", json);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Controller::getMIME(const QUrl& fileUrl) const {
|
|
||||||
const QString mime = m_db.mimeTypeForFile(fileUrl.toLocalFile()).name();
|
|
||||||
return mime;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Controller::forgetRoom(const QString& roomID) {
|
|
||||||
ForgetRoomJob* forgetRoomJob = m_connection->forgetRoom(roomID);
|
|
||||||
setBusy(true);
|
|
||||||
forgetRoomJob->connect(forgetRoomJob, &ForgetRoomJob::finished,
|
|
||||||
[=] { setBusy(false); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::joinRoom(const QString& alias) {
|
void Controller::joinRoom(const QString& alias) {
|
||||||
|
@ -123,8 +80,9 @@ void Controller::joinRoom(const QString& alias) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::createRoom(const QString& name, const QString& topic) {
|
void Controller::createRoom(const QString& name, const QString& topic) {
|
||||||
CreateRoomJob* createRoomJob = m_connection->createRoom(
|
CreateRoomJob* createRoomJob =
|
||||||
Connection::PublishRoom, "", name, topic, QStringList());
|
((Connection*)m_connection)
|
||||||
|
->createRoom(Connection::PublishRoom, "", name, topic, QStringList());
|
||||||
setBusy(true);
|
setBusy(true);
|
||||||
createRoomJob->connect(createRoomJob, &CreateRoomJob::finished,
|
createRoomJob->connect(createRoomJob, &CreateRoomJob::finished,
|
||||||
[=] { setBusy(false); });
|
[=] { setBusy(false); });
|
||||||
|
@ -138,17 +96,9 @@ void Controller::copyToClipboard(const QString& text) {
|
||||||
m_clipboard->setText(text);
|
m_clipboard->setText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::saveFileAs(Room* room, QString eventId) {
|
void Controller::playAudio(QUrl localFile) {
|
||||||
if (!room) return;
|
QMediaPlayer* player = new QMediaPlayer;
|
||||||
auto fileName = QFileDialog::getSaveFileName(
|
player->setMedia(localFile);
|
||||||
Q_NULLPTR, tr("Save File as"), room->fileNameToDownload(eventId));
|
player->play();
|
||||||
if (!fileName.isEmpty())
|
connect(player, &QMediaPlayer::stateChanged, [=] { player->deleteLater(); });
|
||||||
room->downloadFile(eventId, QUrl::fromLocalFile(fileName));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Controller::acceptRoom(Room* room) { room->setJoinState(JoinState::Join); }
|
|
||||||
|
|
||||||
void Controller::rejectRoom(Room* room) {
|
|
||||||
room->setJoinState(JoinState::Leave);
|
|
||||||
forgetRoom(room->id());
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,10 @@
|
||||||
#define CONTROLLER_H
|
#define CONTROLLER_H
|
||||||
|
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
#include "roomlistmodel.h"
|
|
||||||
#include "user.h"
|
#include "user.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QMimeDatabase>
|
#include <QMediaPlayer>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
using namespace QMatrixClient;
|
using namespace QMatrixClient;
|
||||||
|
@ -14,14 +13,13 @@ using namespace QMatrixClient;
|
||||||
class Controller : public QObject {
|
class Controller : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
Q_PROPERTY(Connection* connection READ getConnection CONSTANT)
|
Q_PROPERTY(Connection* connection READ connection CONSTANT)
|
||||||
Q_PROPERTY(
|
Q_PROPERTY(bool isLogin READ isLogin WRITE setIsLogin NOTIFY isLoginChanged)
|
||||||
bool isLogin READ getIsLogin WRITE setIsLogin NOTIFY isLoginChanged)
|
Q_PROPERTY(QString homeserver READ homeserver WRITE setHomeserver NOTIFY
|
||||||
Q_PROPERTY(QString homeserver READ getHomeserver WRITE setHomeserver NOTIFY
|
|
||||||
homeserverChanged)
|
homeserverChanged)
|
||||||
Q_PROPERTY(QString userID READ getUserID WRITE setUserID NOTIFY userIDChanged)
|
Q_PROPERTY(QString userID READ userID WRITE setUserID NOTIFY userIDChanged)
|
||||||
Q_PROPERTY(QByteArray token READ getToken WRITE setToken NOTIFY tokenChanged)
|
Q_PROPERTY(QByteArray token READ token WRITE setToken NOTIFY tokenChanged)
|
||||||
Q_PROPERTY(bool busy READ getBusy WRITE setBusy NOTIFY busyChanged)
|
Q_PROPERTY(bool busy READ busy WRITE setBusy NOTIFY busyChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Controller(QObject* parent = nullptr);
|
explicit Controller(QObject* parent = nullptr);
|
||||||
|
@ -36,64 +34,61 @@ class Controller : public QObject {
|
||||||
|
|
||||||
// All the Q_PROPERTYs.
|
// All the Q_PROPERTYs.
|
||||||
Connection* m_connection = new Connection();
|
Connection* m_connection = new Connection();
|
||||||
Connection* getConnection() { return m_connection; }
|
Connection* connection() { return m_connection; }
|
||||||
|
|
||||||
bool isLogin = false;
|
bool isLogin() { return m_isLogin; }
|
||||||
bool getIsLogin() { return isLogin; }
|
|
||||||
void setIsLogin(bool n) {
|
void setIsLogin(bool n) {
|
||||||
if (n != isLogin) {
|
if (n != m_isLogin) {
|
||||||
isLogin = n;
|
m_isLogin = n;
|
||||||
emit isLoginChanged();
|
emit isLoginChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString userID;
|
QString userID() { return m_userID; }
|
||||||
QString getUserID() { return userID; }
|
|
||||||
void setUserID(QString n) {
|
void setUserID(QString n) {
|
||||||
if (n != userID) {
|
if (n != m_userID) {
|
||||||
userID = n;
|
m_userID = n;
|
||||||
emit userIDChanged();
|
emit userIDChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray token;
|
QByteArray token() { return m_token; }
|
||||||
QByteArray getToken() { return token; }
|
|
||||||
void setToken(QByteArray n) {
|
void setToken(QByteArray n) {
|
||||||
if (n != token) {
|
if (n != m_token) {
|
||||||
token = n;
|
m_token = n;
|
||||||
emit tokenChanged();
|
emit tokenChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString homeserver;
|
QString homeserver() { return m_homeserver; }
|
||||||
QString getHomeserver() { return homeserver; }
|
|
||||||
void setHomeserver(QString n) {
|
void setHomeserver(QString n) {
|
||||||
if (n != homeserver) {
|
if (n != m_homeserver) {
|
||||||
homeserver = n;
|
m_homeserver = n;
|
||||||
emit homeserverChanged();
|
emit homeserverChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool busy = false;
|
bool busy() { return m_busy; }
|
||||||
bool getBusy() { return busy; }
|
|
||||||
void setBusy(bool b) {
|
void setBusy(bool b) {
|
||||||
if (b != busy) {
|
if (b != m_busy) {
|
||||||
busy = b;
|
m_busy = b;
|
||||||
emit busyChanged();
|
emit busyChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QClipboard* m_clipboard = QApplication::clipboard();
|
QClipboard* m_clipboard = QApplication::clipboard();
|
||||||
QMimeDatabase m_db;
|
|
||||||
|
bool m_isLogin = false;
|
||||||
|
QString m_userID;
|
||||||
|
QByteArray m_token;
|
||||||
|
QString m_homeserver;
|
||||||
|
bool m_busy = false;
|
||||||
|
|
||||||
void connected();
|
void connected();
|
||||||
void resync();
|
void resync();
|
||||||
void reconnect();
|
void reconnect();
|
||||||
|
|
||||||
QString getMIME(const QUrl& fileUrl) const;
|
|
||||||
void postFile(Room* room, const QUrl& localFile, const QUrl& mxcUrl);
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void connectionChanged();
|
void connectionChanged();
|
||||||
void isLoginChanged();
|
void isLoginChanged();
|
||||||
|
@ -104,15 +99,11 @@ class Controller : public QObject {
|
||||||
void errorOccured();
|
void errorOccured();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void uploadFile(Room* room);
|
|
||||||
void forgetRoom(const QString& roomID);
|
|
||||||
void joinRoom(const QString& alias);
|
void joinRoom(const QString& alias);
|
||||||
void createRoom(const QString& name, const QString& topic);
|
void createRoom(const QString& name, const QString& topic);
|
||||||
void createDirectChat(const QString& userID);
|
void createDirectChat(const QString& userID);
|
||||||
void copyToClipboard(const QString& text);
|
void copyToClipboard(const QString& text);
|
||||||
void saveFileAs(Room* room, QString eventId);
|
void playAudio(QUrl localFile);
|
||||||
void acceptRoom(Room* room);
|
|
||||||
void rejectRoom(Room* room);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CONTROLLER_H
|
#endif // CONTROLLER_H
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "messageeventmodel.h"
|
#include "messageeventmodel.h"
|
||||||
#include "room.h"
|
#include "room.h"
|
||||||
#include "roomlistmodel.h"
|
#include "roomlistmodel.h"
|
||||||
|
#include "matriqueroom.h"
|
||||||
|
|
||||||
#include "csapi/joining.h"
|
#include "csapi/joining.h"
|
||||||
#include "csapi/leaving.h"
|
#include "csapi/leaving.h"
|
||||||
|
@ -22,7 +23,7 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
qRegisterMetaType<Room *>("Room*");
|
qRegisterMetaType<MatriqueRoom *>("MatriqueRoom*");
|
||||||
qRegisterMetaType<User *>("User*");
|
qRegisterMetaType<User *>("User*");
|
||||||
qRegisterMetaType<MessageEventType>("MessageEventType");
|
qRegisterMetaType<MessageEventType>("MessageEventType");
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
#include "matriqueroom.h"
|
||||||
|
|
||||||
|
#include "connection.h"
|
||||||
|
#include "csapi/leaving.h"
|
||||||
|
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QMimeDatabase>
|
||||||
|
|
||||||
|
MatriqueRoom::MatriqueRoom(Connection* connection, QString roomId,
|
||||||
|
JoinState joinState)
|
||||||
|
: Room(connection, std::move(roomId), joinState) {}
|
||||||
|
|
||||||
|
void MatriqueRoom::chooseAndUploadFile() {
|
||||||
|
auto localFile = QFileDialog::getOpenFileUrl(Q_NULLPTR, tr("Save File as"));
|
||||||
|
if (!localFile.isEmpty()) {
|
||||||
|
uploadFile(localFile.toString(), localFile, getMIME(localFile));
|
||||||
|
QMetaObject::Connection* const connection = new QMetaObject::Connection;
|
||||||
|
*connection = connect(this, &Room::fileTransferCompleted,
|
||||||
|
[=](QString id, QUrl localFile, QUrl mxcUrl) {
|
||||||
|
disconnect(*connection);
|
||||||
|
postFile(localFile, mxcUrl);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatriqueRoom::postFile(const QUrl& localFile, const QUrl& mxcUrl) {
|
||||||
|
const QString mime = getMIME(localFile);
|
||||||
|
const QString fileName = localFile.fileName();
|
||||||
|
QString msgType = "m.file";
|
||||||
|
if (mime.startsWith("image")) msgType = "m.image";
|
||||||
|
if (mime.startsWith("video")) msgType = "m.video";
|
||||||
|
if (mime.startsWith("audio")) msgType = "m.audio";
|
||||||
|
QJsonObject json{QJsonObject{{"msgtype", msgType},
|
||||||
|
{"body", fileName},
|
||||||
|
{"filename", fileName},
|
||||||
|
{"url", mxcUrl.url()}}};
|
||||||
|
postJson("m.room.message", json);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString MatriqueRoom::getMIME(const QUrl& fileUrl) const {
|
||||||
|
return QMimeDatabase().mimeTypeForFile(fileUrl.toLocalFile()).name();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatriqueRoom::saveFileAs(QString eventId) {
|
||||||
|
auto fileName = QFileDialog::getSaveFileName(Q_NULLPTR, tr("Save File as"),
|
||||||
|
fileNameToDownload(eventId));
|
||||||
|
if (!fileName.isEmpty()) downloadFile(eventId, QUrl::fromLocalFile(fileName));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatriqueRoom::acceptInvitation() { setJoinState(JoinState::Join); }
|
||||||
|
|
||||||
|
void MatriqueRoom::rejectInvitation() {
|
||||||
|
setJoinState(JoinState::Leave);
|
||||||
|
forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatriqueRoom::forget() { connection()->forgetRoom(id()); }
|
|
@ -0,0 +1,43 @@
|
||||||
|
#ifndef MATRIQUEROOM_H
|
||||||
|
#define MATRIQUEROOM_H
|
||||||
|
|
||||||
|
#include "room.h"
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
using namespace QMatrixClient;
|
||||||
|
|
||||||
|
class MatriqueRoom : public Room {
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QString cachedInput READ cachedInput WRITE setCachedInput NOTIFY
|
||||||
|
cachedInputChanged)
|
||||||
|
public:
|
||||||
|
explicit MatriqueRoom(Connection* connection, QString roomId,
|
||||||
|
JoinState joinState = {});
|
||||||
|
|
||||||
|
const QString& cachedInput() const { return m_cachedInput; }
|
||||||
|
void setCachedInput(const QString& input) {
|
||||||
|
if (input != m_cachedInput) {
|
||||||
|
m_cachedInput = input;
|
||||||
|
emit cachedInputChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_cachedInput = "";
|
||||||
|
|
||||||
|
QString getMIME(const QUrl& fileUrl) const;
|
||||||
|
void postFile(const QUrl& localFile, const QUrl& mxcUrl);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void cachedInputChanged();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void chooseAndUploadFile();
|
||||||
|
void saveFileAs(QString eventId);
|
||||||
|
void acceptInvitation();
|
||||||
|
void rejectInvitation();
|
||||||
|
void forget();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MATRIQUEROOM_H
|
|
@ -1,15 +1,16 @@
|
||||||
#include "messageeventmodel.h"
|
#include "messageeventmodel.h"
|
||||||
|
|
||||||
#include <QtCore/QDebug>
|
|
||||||
#include <QtQml> // for qmlRegisterType()
|
|
||||||
|
|
||||||
#include <connection.h>
|
#include <connection.h>
|
||||||
|
#include <settings.h>
|
||||||
|
#include <user.h>
|
||||||
|
|
||||||
#include <events/redactionevent.h>
|
#include <events/redactionevent.h>
|
||||||
#include <events/roomavatarevent.h>
|
#include <events/roomavatarevent.h>
|
||||||
#include <events/roommemberevent.h>
|
#include <events/roommemberevent.h>
|
||||||
#include <events/simplestateevents.h>
|
#include <events/simplestateevents.h>
|
||||||
#include <settings.h>
|
|
||||||
#include <user.h>
|
#include <QtCore/QDebug>
|
||||||
|
#include <QtQml> // for qmlRegisterType()
|
||||||
|
|
||||||
QHash<int, QByteArray> MessageEventModel::roleNames() const {
|
QHash<int, QByteArray> MessageEventModel::roleNames() const {
|
||||||
QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
|
QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
#ifndef MESSAGEEVENTMODEL_H
|
#ifndef MESSAGEEVENTMODEL_H
|
||||||
#define MESSAGEEVENTMODEL_H
|
#define MESSAGEEVENTMODEL_H
|
||||||
|
|
||||||
#include <QtCore/QAbstractListModel>
|
|
||||||
#include "room.h"
|
#include "room.h"
|
||||||
|
|
||||||
|
#include <QtCore/QAbstractListModel>
|
||||||
|
|
||||||
class MessageEventModel : public QAbstractListModel {
|
class MessageEventModel : public QAbstractListModel {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(
|
Q_PROPERTY(
|
||||||
|
|
|
@ -37,12 +37,13 @@ void RoomListModel::doResetModel() {
|
||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
Room* RoomListModel::roomAt(int row) { return m_rooms.at(row); }
|
MatriqueRoom* RoomListModel::roomAt(int row) { return m_rooms.at(row); }
|
||||||
|
|
||||||
void RoomListModel::doAddRoom(Room* r) {
|
void RoomListModel::doAddRoom(Room* r) {
|
||||||
if (auto* room = r) {
|
if (auto* room = static_cast<MatriqueRoom*>(r)) {
|
||||||
m_rooms.append(room);
|
m_rooms.append(room);
|
||||||
connectRoomSignals(room);
|
connectRoomSignals(room);
|
||||||
|
// qCritical() << room->cachedInput();
|
||||||
emit roomAdded(room);
|
emit roomAdded(room);
|
||||||
} else {
|
} else {
|
||||||
qCritical() << "Attempt to add nullptr to the room list";
|
qCritical() << "Attempt to add nullptr to the room list";
|
||||||
|
@ -50,7 +51,7 @@ void RoomListModel::doAddRoom(Room* r) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoomListModel::connectRoomSignals(Room* room) {
|
void RoomListModel::connectRoomSignals(MatriqueRoom* room) {
|
||||||
connect(room, &Room::displaynameChanged, this, [=] { namesChanged(room); });
|
connect(room, &Room::displaynameChanged, this, [=] { namesChanged(room); });
|
||||||
connect(room, &Room::unreadMessagesChanged, this,
|
connect(room, &Room::unreadMessagesChanged, this,
|
||||||
[=] { unreadMessagesChanged(room); });
|
[=] { unreadMessagesChanged(room); });
|
||||||
|
@ -62,7 +63,7 @@ void RoomListModel::connectRoomSignals(Room* room) {
|
||||||
[=] { refresh(room, {AvatarRole}); });
|
[=] { refresh(room, {AvatarRole}); });
|
||||||
|
|
||||||
connect(room, &Room::unreadMessagesChanged, this, [=](Room* r) {
|
connect(room, &Room::unreadMessagesChanged, this, [=](Room* r) {
|
||||||
if (r->hasUnreadMessages()) emit newMessage(r);
|
if (r->hasUnreadMessages()) emit newMessage(static_cast<MatriqueRoom*>(r));
|
||||||
});
|
});
|
||||||
// connect(
|
// connect(
|
||||||
// room, &QMatrixClient::Room::aboutToAddNewMessages, this,
|
// room, &QMatrixClient::Room::aboutToAddNewMessages, this,
|
||||||
|
@ -84,7 +85,7 @@ void RoomListModel::updateRoom(Room* room, Room* prev) {
|
||||||
// the previously left room (in both cases prev has the previous state).
|
// the previously left room (in both cases prev has the previous state).
|
||||||
if (prev == room) {
|
if (prev == room) {
|
||||||
qCritical() << "RoomListModel::updateRoom: room tried to replace itself";
|
qCritical() << "RoomListModel::updateRoom: room tried to replace itself";
|
||||||
refresh(static_cast<Room*>(room));
|
refresh(static_cast<MatriqueRoom*>(room));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (prev && room->id() != prev->id()) {
|
if (prev && room->id() != prev->id()) {
|
||||||
|
@ -93,10 +94,10 @@ void RoomListModel::updateRoom(Room* room, Room* prev) {
|
||||||
// That doesn't look right but technically we still can do it.
|
// That doesn't look right but technically we still can do it.
|
||||||
}
|
}
|
||||||
// Ok, we're through with pre-checks, now for the real thing.
|
// Ok, we're through with pre-checks, now for the real thing.
|
||||||
auto* newRoom = room;
|
auto* newRoom = static_cast<MatriqueRoom*>(room);
|
||||||
const auto it =
|
const auto it = std::find_if(
|
||||||
std::find_if(m_rooms.begin(), m_rooms.end(),
|
m_rooms.begin(), m_rooms.end(),
|
||||||
[=](const Room* r) { return r == prev || r == newRoom; });
|
[=](const MatriqueRoom* r) { return r == prev || r == newRoom; });
|
||||||
if (it != m_rooms.end()) {
|
if (it != m_rooms.end()) {
|
||||||
const int row = it - m_rooms.begin();
|
const int row = it - m_rooms.begin();
|
||||||
// There's no guarantee that prev != newRoom
|
// There's no guarantee that prev != newRoom
|
||||||
|
@ -136,7 +137,7 @@ QVariant RoomListModel::data(const QModelIndex& index, int role) const {
|
||||||
qDebug() << "UserListModel: something wrong here...";
|
qDebug() << "UserListModel: something wrong here...";
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
Room* room = m_rooms.at(index.row());
|
MatriqueRoom* room = m_rooms.at(index.row());
|
||||||
if (role == NameRole) return room->displayName();
|
if (role == NameRole) return room->displayName();
|
||||||
if (role == AvatarRole) {
|
if (role == AvatarRole) {
|
||||||
if (room->avatarUrl().toString() != "") {
|
if (room->avatarUrl().toString() != "") {
|
||||||
|
@ -156,12 +157,12 @@ QVariant RoomListModel::data(const QModelIndex& index, int role) const {
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoomListModel::namesChanged(Room* room) {
|
void RoomListModel::namesChanged(MatriqueRoom* 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::refresh(Room* room, const QVector<int>& roles) {
|
void RoomListModel::refresh(MatriqueRoom* room, const QVector<int>& roles) {
|
||||||
const auto it = std::find(m_rooms.begin(), m_rooms.end(), room);
|
const auto it = std::find(m_rooms.begin(), m_rooms.end(), room);
|
||||||
if (it == m_rooms.end()) {
|
if (it == m_rooms.end()) {
|
||||||
qCritical() << "Room" << room->id() << "not found in the room list";
|
qCritical() << "Room" << room->id() << "not found in the room list";
|
||||||
|
@ -171,7 +172,7 @@ void RoomListModel::refresh(Room* room, const QVector<int>& roles) {
|
||||||
emit dataChanged(idx, idx, roles);
|
emit dataChanged(idx, idx, roles);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoomListModel::unreadMessagesChanged(Room* room) {
|
void RoomListModel::unreadMessagesChanged(MatriqueRoom* 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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
#ifndef ROOMLISTMODEL_H
|
#ifndef ROOMLISTMODEL_H
|
||||||
#define ROOMLISTMODEL_H
|
#define ROOMLISTMODEL_H
|
||||||
|
|
||||||
#include <QtCore/QAbstractListModel>
|
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
#include "room.h"
|
#include "room.h"
|
||||||
|
#include "matriqueroom.h"
|
||||||
|
|
||||||
|
#include <QtCore/QAbstractListModel>
|
||||||
|
|
||||||
using namespace QMatrixClient;
|
using namespace QMatrixClient;
|
||||||
|
|
||||||
|
@ -23,7 +25,7 @@ class RoomType : public QObject {
|
||||||
|
|
||||||
class RoomListModel : public QAbstractListModel {
|
class RoomListModel : public QAbstractListModel {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(Connection* connection READ getConnection WRITE setConnection)
|
Q_PROPERTY(Connection* connection READ connection WRITE setConnection)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum EventRoles {
|
enum EventRoles {
|
||||||
|
@ -37,11 +39,11 @@ class RoomListModel : public QAbstractListModel {
|
||||||
RoomListModel(QObject* parent = 0);
|
RoomListModel(QObject* parent = 0);
|
||||||
virtual ~RoomListModel();
|
virtual ~RoomListModel();
|
||||||
|
|
||||||
Connection* getConnection() { return m_connection; }
|
Connection* connection() { return m_connection; }
|
||||||
void setConnection(Connection* connection);
|
void setConnection(Connection* connection);
|
||||||
void doResetModel();
|
void doResetModel();
|
||||||
|
|
||||||
Q_INVOKABLE Room* roomAt(int row);
|
Q_INVOKABLE MatriqueRoom* roomAt(int row);
|
||||||
|
|
||||||
QVariant data(const QModelIndex& index,
|
QVariant data(const QModelIndex& index,
|
||||||
int role = Qt::DisplayRole) const override;
|
int role = Qt::DisplayRole) const override;
|
||||||
|
@ -51,23 +53,23 @@ class RoomListModel : public QAbstractListModel {
|
||||||
QHash<int, QByteArray> roleNames() const;
|
QHash<int, QByteArray> roleNames() const;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void namesChanged(Room* room);
|
void namesChanged(MatriqueRoom* room);
|
||||||
void unreadMessagesChanged(Room* room);
|
void unreadMessagesChanged(MatriqueRoom* room);
|
||||||
|
|
||||||
void doAddRoom(Room* room);
|
void doAddRoom(Room* room);
|
||||||
void updateRoom(Room* room, Room* prev);
|
void updateRoom(Room* room, Room* prev);
|
||||||
void deleteRoom(Room* room);
|
void deleteRoom(Room* room);
|
||||||
void refresh(Room* room, const QVector<int>& roles = {});
|
void refresh(MatriqueRoom* room, const QVector<int>& roles = {});
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Connection* m_connection = nullptr;
|
Connection* m_connection = nullptr;
|
||||||
QList<Room*> m_rooms;
|
QList<MatriqueRoom*> m_rooms;
|
||||||
void connectRoomSignals(Room* room);
|
void connectRoomSignals(MatriqueRoom* room);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void connectionChanged();
|
void connectionChanged();
|
||||||
void roomAdded(Room* room);
|
void roomAdded(MatriqueRoom* room);
|
||||||
void newMessage(Room* room);
|
void newMessage(MatriqueRoom* room);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ROOMLISTMODEL_H
|
#endif // ROOMLISTMODEL_H
|
||||||
|
|
Loading…
Reference in New Issue