Clang-tidy + clang-format
This commit is contained in:
@@ -29,8 +29,9 @@ AccountListModel::AccountListModel(QObject *parent)
|
|||||||
}
|
}
|
||||||
conn->disconnect(this);
|
conn->disconnect(this);
|
||||||
const auto it = std::find(m_connections.begin(), m_connections.end(), conn);
|
const auto it = std::find(m_connections.begin(), m_connections.end(), conn);
|
||||||
if (it == m_connections.end())
|
if (it == m_connections.end()) {
|
||||||
return; // Already deleted, nothing to do
|
return; // Already deleted, nothing to do
|
||||||
|
}
|
||||||
const int row = it - m_connections.begin();
|
const int row = it - m_connections.begin();
|
||||||
beginRemoveRows(QModelIndex(), row, row);
|
beginRemoveRows(QModelIndex(), row, row);
|
||||||
m_connections.erase(it);
|
m_connections.erase(it);
|
||||||
|
|||||||
@@ -22,10 +22,10 @@ public:
|
|||||||
|
|
||||||
AccountListModel(QObject *parent = nullptr);
|
AccountListModel(QObject *parent = nullptr);
|
||||||
|
|
||||||
QVariant data(const QModelIndex &index, int role = UserRole) const override;
|
[[nodiscard]] QVariant data(const QModelIndex &index, int role = UserRole) const override;
|
||||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
[[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QVector<Connection *> m_connections;
|
QVector<Connection *> m_connections;
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
#include <QQmlFile>
|
#include <QQmlFile>
|
||||||
#include <QQmlFileSelector>
|
#include <QQmlFileSelector>
|
||||||
#include <QQuickTextDocument>
|
#include <QQuickTextDocument>
|
||||||
|
#include <QStringBuilder>
|
||||||
#include <QTextBlock>
|
#include <QTextBlock>
|
||||||
#include <QTextDocument>
|
#include <QTextDocument>
|
||||||
#include <QStringBuilder>
|
|
||||||
|
|
||||||
#include "neochatroom.h"
|
#include "neochatroom.h"
|
||||||
|
|
||||||
@@ -23,11 +23,13 @@ QQuickTextDocument *ChatDocumentHandler::document() const
|
|||||||
|
|
||||||
void ChatDocumentHandler::setDocument(QQuickTextDocument *document)
|
void ChatDocumentHandler::setDocument(QQuickTextDocument *document)
|
||||||
{
|
{
|
||||||
if (document == m_document)
|
if (document == m_document) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_document)
|
if (m_document) {
|
||||||
m_document->textDocument()->disconnect(this);
|
m_document->textDocument()->disconnect(this);
|
||||||
|
}
|
||||||
m_document = document;
|
m_document = document;
|
||||||
Q_EMIT documentChanged();
|
Q_EMIT documentChanged();
|
||||||
}
|
}
|
||||||
@@ -39,14 +41,14 @@ int ChatDocumentHandler::cursorPosition() const
|
|||||||
|
|
||||||
void ChatDocumentHandler::setCursorPosition(int position)
|
void ChatDocumentHandler::setCursorPosition(int position)
|
||||||
{
|
{
|
||||||
if (position == m_cursorPosition)
|
if (position == m_cursorPosition) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_cursorPosition = position;
|
m_cursorPosition = position;
|
||||||
Q_EMIT cursorPositionChanged();
|
Q_EMIT cursorPositionChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int ChatDocumentHandler::selectionStart() const
|
int ChatDocumentHandler::selectionStart() const
|
||||||
{
|
{
|
||||||
return m_selectionStart;
|
return m_selectionStart;
|
||||||
@@ -54,8 +56,9 @@ int ChatDocumentHandler::selectionStart() const
|
|||||||
|
|
||||||
void ChatDocumentHandler::setSelectionStart(int position)
|
void ChatDocumentHandler::setSelectionStart(int position)
|
||||||
{
|
{
|
||||||
if (position == m_selectionStart)
|
if (position == m_selectionStart) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_selectionStart = position;
|
m_selectionStart = position;
|
||||||
Q_EMIT selectionStartChanged();
|
Q_EMIT selectionStartChanged();
|
||||||
@@ -68,8 +71,9 @@ int ChatDocumentHandler::selectionEnd() const
|
|||||||
|
|
||||||
void ChatDocumentHandler::setSelectionEnd(int position)
|
void ChatDocumentHandler::setSelectionEnd(int position)
|
||||||
{
|
{
|
||||||
if (position == m_selectionEnd)
|
if (position == m_selectionEnd) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_selectionEnd = position;
|
m_selectionEnd = position;
|
||||||
Q_EMIT selectionEndChanged();
|
Q_EMIT selectionEndChanged();
|
||||||
@@ -78,8 +82,9 @@ void ChatDocumentHandler::setSelectionEnd(int position)
|
|||||||
QTextCursor ChatDocumentHandler::textCursor() const
|
QTextCursor ChatDocumentHandler::textCursor() const
|
||||||
{
|
{
|
||||||
QTextDocument *doc = textDocument();
|
QTextDocument *doc = textDocument();
|
||||||
if (!doc)
|
if (!doc) {
|
||||||
return QTextCursor();
|
return QTextCursor();
|
||||||
|
}
|
||||||
|
|
||||||
QTextCursor cursor = QTextCursor(doc);
|
QTextCursor cursor = QTextCursor(doc);
|
||||||
if (m_selectionStart != m_selectionEnd) {
|
if (m_selectionStart != m_selectionEnd) {
|
||||||
@@ -93,8 +98,9 @@ QTextCursor ChatDocumentHandler::textCursor() const
|
|||||||
|
|
||||||
QTextDocument *ChatDocumentHandler::textDocument() const
|
QTextDocument *ChatDocumentHandler::textDocument() const
|
||||||
{
|
{
|
||||||
if (!m_document)
|
if (!m_document) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
return m_document->textDocument();
|
return m_document->textDocument();
|
||||||
}
|
}
|
||||||
@@ -106,8 +112,9 @@ NeoChatRoom *ChatDocumentHandler::room() const
|
|||||||
|
|
||||||
void ChatDocumentHandler::setRoom(NeoChatRoom *room)
|
void ChatDocumentHandler::setRoom(NeoChatRoom *room)
|
||||||
{
|
{
|
||||||
if (m_room == room)
|
if (m_room == room) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_room = room;
|
m_room = room;
|
||||||
Q_EMIT roomChanged();
|
Q_EMIT roomChanged();
|
||||||
@@ -123,8 +130,7 @@ QVariantMap ChatDocumentHandler::getAutocompletionInfo()
|
|||||||
{"type", AutoCompletionType::Ignore},
|
{"type", AutoCompletionType::Ignore},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (m_cursorPosition != m_autoCompleteBeginPosition
|
if (m_cursorPosition != m_autoCompleteBeginPosition && m_cursorPosition != m_autoCompleteEndPosition) {
|
||||||
&& m_cursorPosition != m_autoCompleteEndPosition) {
|
|
||||||
// we moved our cursor, so cancel autocompletion
|
// we moved our cursor, so cancel autocompletion
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,12 +155,11 @@ QVariantMap ChatDocumentHandler::getAutocompletionInfo()
|
|||||||
{"keyword", autoCompletePrefix},
|
{"keyword", autoCompletePrefix},
|
||||||
{"type", AutoCompletionType::User},
|
{"type", AutoCompletionType::User},
|
||||||
};
|
};
|
||||||
} else {
|
|
||||||
return QVariantMap {
|
|
||||||
{"keyword", autoCompletePrefix},
|
|
||||||
{"type", AutoCompletionType::Emoji},
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
return QVariantMap {
|
||||||
|
{"keyword", autoCompletePrefix},
|
||||||
|
{"type", AutoCompletionType::Emoji},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return QVariantMap {
|
return QVariantMap {
|
||||||
@@ -164,8 +169,9 @@ QVariantMap ChatDocumentHandler::getAutocompletionInfo()
|
|||||||
|
|
||||||
void ChatDocumentHandler::postMessage(const QString &attachementPath, const QString &replyEventId) const
|
void ChatDocumentHandler::postMessage(const QString &attachementPath, const QString &replyEventId) const
|
||||||
{
|
{
|
||||||
if (!m_room || !m_document)
|
if (!m_room || !m_document) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QString cleanedText = m_document->textDocument()->toMarkdown();
|
QString cleanedText = m_document->textDocument()->toMarkdown();
|
||||||
|
|
||||||
@@ -175,8 +181,9 @@ void ChatDocumentHandler::postMessage(const QString &attachementPath, const QStr
|
|||||||
m_room->uploadFile(attachementPath, cleanedText);
|
m_room->uploadFile(attachementPath, cleanedText);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cleanedText.length() == 0)
|
if (cleanedText.length() == 0) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto messageEventType = RoomMessageEvent::MsgType::Text;
|
auto messageEventType = RoomMessageEvent::MsgType::Text;
|
||||||
|
|
||||||
@@ -187,7 +194,8 @@ void ChatDocumentHandler::postMessage(const QString &attachementPath, const QStr
|
|||||||
if (cleanedText.indexOf(rainbowPrefix) == 0) {
|
if (cleanedText.indexOf(rainbowPrefix) == 0) {
|
||||||
cleanedText = cleanedText.remove(0, rainbowPrefix.length());
|
cleanedText = cleanedText.remove(0, rainbowPrefix.length());
|
||||||
QString rainbowText;
|
QString rainbowText;
|
||||||
QStringList rainbowColors { "#ff2b00", "#ff5500", "#ff8000", "#ffaa00", "#ffd500", "#ffff00", "#d4ff00", "#aaff00", "#80ff00", "#55ff00", "#2bff00", "#00ff00", "#00ff2b", "#00ff55", "#00ff80", "#00ffaa", "#00ffd5", "#00ffff", "#00d4ff", "#00aaff", "#007fff", "#0055ff", "#002bff", "#0000ff", "#2a00ff", "#5500ff", "#7f00ff", "#aa00ff", "#d400ff", "#ff00ff", "#ff00d4", "#ff00aa", "#ff0080", "#ff0055", "#ff002b", "#ff0000" };
|
QStringList rainbowColors {"#ff2b00", "#ff5500", "#ff8000", "#ffaa00", "#ffd500", "#ffff00", "#d4ff00", "#aaff00", "#80ff00", "#55ff00", "#2bff00", "#00ff00", "#00ff2b", "#00ff55", "#00ff80", "#00ffaa", "#00ffd5", "#00ffff",
|
||||||
|
"#00d4ff", "#00aaff", "#007fff", "#0055ff", "#002bff", "#0000ff", "#2a00ff", "#5500ff", "#7f00ff", "#aa00ff", "#d400ff", "#ff00ff", "#ff00d4", "#ff00aa", "#ff0080", "#ff0055", "#ff002b", "#ff0000"};
|
||||||
|
|
||||||
for (int i = 0; i < cleanedText.length(); i++) {
|
for (int i = 0; i < cleanedText.length(); i++) {
|
||||||
rainbowText = rainbowText % QStringLiteral("<font color='") % rainbowColors.at(i % rainbowColors.length()) % "'>" % cleanedText.at(i) % "</font>";
|
rainbowText = rainbowText % QStringLiteral("<font color='") % rainbowColors.at(i % rainbowColors.length()) % "'>" % cleanedText.at(i) % "</font>";
|
||||||
|
|||||||
@@ -34,24 +34,24 @@ public:
|
|||||||
};
|
};
|
||||||
Q_ENUM(AutoCompletionType)
|
Q_ENUM(AutoCompletionType)
|
||||||
|
|
||||||
explicit ChatDocumentHandler(QObject *object = nullptr);
|
explicit ChatDocumentHandler(QObject *parent = nullptr);
|
||||||
|
|
||||||
QQuickTextDocument *document() const;
|
[[nodiscard]] QQuickTextDocument *document() const;
|
||||||
void setDocument(QQuickTextDocument *document);
|
void setDocument(QQuickTextDocument *document);
|
||||||
|
|
||||||
int cursorPosition() const;
|
[[nodiscard]] int cursorPosition() const;
|
||||||
void setCursorPosition(int position);
|
void setCursorPosition(int position);
|
||||||
|
|
||||||
int selectionStart() const;
|
[[nodiscard]] int selectionStart() const;
|
||||||
void setSelectionStart(int position);
|
void setSelectionStart(int position);
|
||||||
|
|
||||||
int selectionEnd() const;
|
[[nodiscard]] int selectionEnd() const;
|
||||||
void setSelectionEnd(int position);
|
void setSelectionEnd(int position);
|
||||||
|
|
||||||
NeoChatRoom *room() const;
|
[[nodiscard]] NeoChatRoom *room() const;
|
||||||
void setRoom(NeoChatRoom *room);
|
void setRoom(NeoChatRoom *room);
|
||||||
|
|
||||||
Q_INVOKABLE void postMessage(const QString &attachmentPath, const QString &replyEventId) const;
|
Q_INVOKABLE void postMessage(const QString &attachementPath, const QString &replyEventId) const;
|
||||||
|
|
||||||
/// This function will look at the current QTextCursor and determine if there
|
/// This function will look at the current QTextCursor and determine if there
|
||||||
/// is the posibility to autocomplete it.
|
/// is the posibility to autocomplete it.
|
||||||
@@ -66,8 +66,8 @@ Q_SIGNALS:
|
|||||||
void roomChanged();
|
void roomChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QTextCursor textCursor() const;
|
[[nodiscard]] QTextCursor textCursor() const;
|
||||||
QTextDocument *textDocument() const;
|
[[nodiscard]] QTextDocument *textDocument() const;
|
||||||
|
|
||||||
QQuickTextDocument *m_document;
|
QQuickTextDocument *m_document;
|
||||||
|
|
||||||
|
|||||||
@@ -31,15 +31,17 @@ QImage Clipboard::image() const
|
|||||||
return m_clipboard->image();
|
return m_clipboard->image();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Clipboard::saveImage(const QUrl &localPath)
|
bool Clipboard::saveImage(const QUrl &localPath) const
|
||||||
{
|
{
|
||||||
if (!localPath.isLocalFile())
|
if (!localPath.isLocalFile()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
auto i = image();
|
auto i = image();
|
||||||
|
|
||||||
if (i.isNull())
|
if (i.isNull()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
QString path = QFileInfo(localPath.toLocalFile()).absolutePath();
|
QString path = QFileInfo(localPath.toLocalFile()).absolutePath();
|
||||||
QDir dir;
|
QDir dir;
|
||||||
|
|||||||
@@ -22,10 +22,10 @@ class Clipboard : public QObject
|
|||||||
public:
|
public:
|
||||||
explicit Clipboard(QObject *parent = nullptr);
|
explicit Clipboard(QObject *parent = nullptr);
|
||||||
|
|
||||||
bool hasImage() const;
|
[[nodiscard]] bool hasImage() const;
|
||||||
QImage image() const;
|
[[nodiscard]] QImage image() const;
|
||||||
|
|
||||||
Q_INVOKABLE bool saveImage(const QUrl &localPath);
|
Q_INVOKABLE bool saveImage(const QUrl &localPath) const;
|
||||||
|
|
||||||
Q_INVOKABLE void saveText(QString message);
|
Q_INVOKABLE void saveText(QString message);
|
||||||
|
|
||||||
|
|||||||
@@ -31,14 +31,15 @@
|
|||||||
#include <QtGui/QPixmap>
|
#include <QtGui/QPixmap>
|
||||||
#include <QtNetwork/QAuthenticator>
|
#include <QtNetwork/QAuthenticator>
|
||||||
#include <QtNetwork/QNetworkReply>
|
#include <QtNetwork/QNetworkReply>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "csapi/account-data.h"
|
#include "csapi/account-data.h"
|
||||||
#include "csapi/content-repo.h"
|
#include "csapi/content-repo.h"
|
||||||
#include "csapi/joining.h"
|
#include "csapi/joining.h"
|
||||||
#include "csapi/logout.h"
|
#include "csapi/logout.h"
|
||||||
#include "csapi/profile.h"
|
#include "csapi/profile.h"
|
||||||
#include "csapi/wellknown.h"
|
|
||||||
#include "csapi/registration.h"
|
#include "csapi/registration.h"
|
||||||
|
#include "csapi/wellknown.h"
|
||||||
#include "events/eventcontent.h"
|
#include "events/eventcontent.h"
|
||||||
#include "events/roommessageevent.h"
|
#include "events/roommessageevent.h"
|
||||||
#include "neochatroom.h"
|
#include "neochatroom.h"
|
||||||
@@ -91,7 +92,7 @@ inline QString accessTokenFileName(const AccountSettings &account)
|
|||||||
return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + '/' + fileName;
|
return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + '/' + fileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::loginWithCredentials(QString serverAddr, QString user, QString pass, QString deviceName)
|
void Controller::loginWithCredentials(const QString &serverAddr, const QString &user, const QString &pass, QString deviceName)
|
||||||
{
|
{
|
||||||
if (user.isEmpty() || pass.isEmpty()) {
|
if (user.isEmpty() || pass.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
@@ -121,17 +122,18 @@ void Controller::loginWithCredentials(QString serverAddr, QString user, QString
|
|||||||
account.setHomeserver(finalConn->homeserver());
|
account.setHomeserver(finalConn->homeserver());
|
||||||
account.setDeviceId(finalConn->deviceId());
|
account.setDeviceId(finalConn->deviceId());
|
||||||
account.setDeviceName(deviceName);
|
account.setDeviceName(deviceName);
|
||||||
if (!saveAccessTokenToKeyChain(account, finalConn->accessToken()))
|
if (!saveAccessTokenToKeyChain(account, finalConn->accessToken())) {
|
||||||
qWarning() << "Couldn't save access token";
|
qWarning() << "Couldn't save access token";
|
||||||
|
}
|
||||||
account.sync();
|
account.sync();
|
||||||
addConnection(finalConn);
|
addConnection(finalConn);
|
||||||
setActiveConnection(finalConn);
|
setActiveConnection(finalConn);
|
||||||
});
|
});
|
||||||
connect(finalConn, &Connection::networkError, [=](QString error, QString, int, int) {
|
connect(finalConn, &Connection::networkError, [=](QString error, const QString &, int, int) {
|
||||||
Q_EMIT globalErrorOccured(i18n("Network Error"), error);
|
Q_EMIT globalErrorOccured(i18n("Network Error"), std::move(error));
|
||||||
});
|
});
|
||||||
connect(finalConn, &Connection::loginError, [=](QString error, QString) {
|
connect(finalConn, &Connection::loginError, [=](QString error, const QString &) {
|
||||||
Q_EMIT errorOccured(i18n("Login Failed"), error);
|
Q_EMIT errorOccured(i18n("Login Failed"), std::move(error));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -142,7 +144,7 @@ void Controller::loginWithCredentials(QString serverAddr, QString user, QString
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::loginWithAccessToken(QString serverAddr, QString user, QString token, QString deviceName)
|
void Controller::loginWithAccessToken(const QString &serverAddr, const QString &user, const QString &token, const QString &deviceName)
|
||||||
{
|
{
|
||||||
if (user.isEmpty() || token.isEmpty()) {
|
if (user.isEmpty() || token.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
@@ -162,14 +164,15 @@ void Controller::loginWithAccessToken(QString serverAddr, QString user, QString
|
|||||||
account.setHomeserver(conn->homeserver());
|
account.setHomeserver(conn->homeserver());
|
||||||
account.setDeviceId(conn->deviceId());
|
account.setDeviceId(conn->deviceId());
|
||||||
account.setDeviceName(deviceName);
|
account.setDeviceName(deviceName);
|
||||||
if (!saveAccessTokenToKeyChain(account, conn->accessToken()))
|
if (!saveAccessTokenToKeyChain(account, conn->accessToken())) {
|
||||||
qWarning() << "Couldn't save access token";
|
qWarning() << "Couldn't save access token";
|
||||||
|
}
|
||||||
account.sync();
|
account.sync();
|
||||||
addConnection(conn);
|
addConnection(conn);
|
||||||
setActiveConnection(conn);
|
setActiveConnection(conn);
|
||||||
});
|
});
|
||||||
connect(conn, &Connection::networkError, this, [=](QString error, QString, int, int) {
|
connect(conn, &Connection::networkError, this, [=](QString error, const QString &, int, int) {
|
||||||
Q_EMIT errorOccured("Network Error", error);
|
Q_EMIT errorOccured("Network Error", std::move(error));
|
||||||
});
|
});
|
||||||
conn->connectWithToken(user, token, deviceName);
|
conn->connectWithToken(user, token, deviceName);
|
||||||
}
|
}
|
||||||
@@ -200,10 +203,11 @@ void Controller::logout(Connection *conn, bool serverSideLogout)
|
|||||||
conn->stopSync();
|
conn->stopSync();
|
||||||
Q_EMIT conn->stateChanged();
|
Q_EMIT conn->stateChanged();
|
||||||
Q_EMIT conn->loggedOut();
|
Q_EMIT conn->loggedOut();
|
||||||
if (!m_connections.isEmpty())
|
if (!m_connections.isEmpty()) {
|
||||||
setActiveConnection(m_connections[0]);
|
setActiveConnection(m_connections[0]);
|
||||||
else
|
} else {
|
||||||
setActiveConnection(nullptr);
|
setActiveConnection(nullptr);
|
||||||
|
}
|
||||||
if (!serverSideLogout) {
|
if (!serverSideLogout) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -262,7 +266,7 @@ void Controller::invokeLogin()
|
|||||||
c->loadState();
|
c->loadState();
|
||||||
addConnection(c);
|
addConnection(c);
|
||||||
});
|
});
|
||||||
connect(c, &Connection::loginError, this, [=](QString error, QString) {
|
connect(c, &Connection::loginError, this, [=](const QString &error, const QString &) {
|
||||||
if (error == "Unrecognised access token") {
|
if (error == "Unrecognised access token") {
|
||||||
Q_EMIT errorOccured(i18n("Login Failed"), i18n("Access Token invalid or revoked"));
|
Q_EMIT errorOccured(i18n("Login Failed"), i18n("Access Token invalid or revoked"));
|
||||||
logout(c, false);
|
logout(c, false);
|
||||||
@@ -271,7 +275,7 @@ void Controller::invokeLogin()
|
|||||||
logout(c, true);
|
logout(c, true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
connect(c, &Connection::networkError, this, [=](QString error, QString, int, int) {
|
connect(c, &Connection::networkError, this, [=](const QString &error, const QString &, int, int) {
|
||||||
Q_EMIT errorOccured("Network Error", error);
|
Q_EMIT errorOccured("Network Error", error);
|
||||||
});
|
});
|
||||||
c->connectWithToken(account.userId(), accessToken, account.deviceId());
|
c->connectWithToken(account.userId(), accessToken, account.deviceId());
|
||||||
@@ -289,8 +293,9 @@ QByteArray Controller::loadAccessTokenFromFile(const AccountSettings &account)
|
|||||||
{
|
{
|
||||||
QFile accountTokenFile {accessTokenFileName(account)};
|
QFile accountTokenFile {accessTokenFileName(account)};
|
||||||
if (accountTokenFile.open(QFile::ReadOnly)) {
|
if (accountTokenFile.open(QFile::ReadOnly)) {
|
||||||
if (accountTokenFile.size() < 1024)
|
if (accountTokenFile.size() < 1024) {
|
||||||
return accountTokenFile.readAll();
|
return accountTokenFile.readAll();
|
||||||
|
}
|
||||||
|
|
||||||
qWarning() << "File" << accountTokenFile.fileName() << "is" << accountTokenFile.size() << "bytes long - too long for a token, ignoring it.";
|
qWarning() << "File" << accountTokenFile.fileName() << "is" << accountTokenFile.size() << "bytes long - too long for a token, ignoring it.";
|
||||||
}
|
}
|
||||||
@@ -388,12 +393,13 @@ bool Controller::saveAccessTokenToKeyChain(const AccountSettings &account, const
|
|||||||
|
|
||||||
void Controller::joinRoom(Connection *c, const QString &alias)
|
void Controller::joinRoom(Connection *c, const QString &alias)
|
||||||
{
|
{
|
||||||
if (!alias.contains(":"))
|
if (!alias.contains(":")) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto knownServer = alias.mid(alias.indexOf(":") + 1);
|
auto knownServer = alias.mid(alias.indexOf(":") + 1);
|
||||||
auto joinRoomJob = c->joinRoom(alias, QStringList {knownServer});
|
auto joinRoomJob = c->joinRoom(alias, QStringList {knownServer});
|
||||||
joinRoomJob->connect(joinRoomJob, &JoinRoomJob::failure, [=] {
|
Quotient::JoinRoomJob::connect(joinRoomJob, &JoinRoomJob::failure, [=] {
|
||||||
Q_EMIT errorOccured("Join Room Failed", joinRoomJob->errorString());
|
Q_EMIT errorOccured("Join Room Failed", joinRoomJob->errorString());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -401,7 +407,7 @@ void Controller::joinRoom(Connection *c, const QString &alias)
|
|||||||
void Controller::createRoom(Connection *c, const QString &name, const QString &topic)
|
void Controller::createRoom(Connection *c, const QString &name, const QString &topic)
|
||||||
{
|
{
|
||||||
auto createRoomJob = c->createRoom(Connection::PublishRoom, "", name, topic, QStringList());
|
auto createRoomJob = c->createRoom(Connection::PublishRoom, "", name, topic, QStringList());
|
||||||
createRoomJob->connect(createRoomJob, &CreateRoomJob::failure, [=] {
|
Quotient::CreateRoomJob::connect(createRoomJob, &CreateRoomJob::failure, [=] {
|
||||||
Q_EMIT errorOccured("Create Room Failed", createRoomJob->errorString());
|
Q_EMIT errorOccured("Create Room Failed", createRoomJob->errorString());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -409,12 +415,12 @@ void Controller::createRoom(Connection *c, const QString &name, const QString &t
|
|||||||
void Controller::createDirectChat(Connection *c, const QString &userID)
|
void Controller::createDirectChat(Connection *c, const QString &userID)
|
||||||
{
|
{
|
||||||
auto createRoomJob = c->createDirectChat(userID);
|
auto createRoomJob = c->createDirectChat(userID);
|
||||||
createRoomJob->connect(createRoomJob, &CreateRoomJob::failure, [=] {
|
Quotient::CreateRoomJob::connect(createRoomJob, &CreateRoomJob::failure, [=] {
|
||||||
Q_EMIT errorOccured("Create Direct Chat Failed", createRoomJob->errorString());
|
Q_EMIT errorOccured("Create Direct Chat Failed", createRoomJob->errorString());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::playAudio(QUrl localFile)
|
void Controller::playAudio(const QUrl &localFile)
|
||||||
{
|
{
|
||||||
auto player = new QMediaPlayer;
|
auto player = new QMediaPlayer;
|
||||||
player->setMedia(localFile);
|
player->setMedia(localFile);
|
||||||
@@ -424,7 +430,7 @@ void Controller::playAudio(QUrl localFile)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::changeAvatar(Connection *conn, QUrl localFile)
|
void Controller::changeAvatar(Connection *conn, const QUrl &localFile)
|
||||||
{
|
{
|
||||||
auto job = conn->uploadFile(localFile.toLocalFile());
|
auto job = conn->uploadFile(localFile.toLocalFile());
|
||||||
if (isJobRunning(job)) {
|
if (isJobRunning(job)) {
|
||||||
@@ -442,7 +448,7 @@ void Controller::markAllMessagesAsRead(Connection *conn)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::setAboutData(KAboutData aboutData)
|
void Controller::setAboutData(const KAboutData &aboutData)
|
||||||
{
|
{
|
||||||
m_aboutData = aboutData;
|
m_aboutData = aboutData;
|
||||||
Q_EMIT aboutDataChanged();
|
Q_EMIT aboutDataChanged();
|
||||||
@@ -488,7 +494,7 @@ NeochatChangePasswordJob::NeochatChangePasswordJob(const QString &newPassword, b
|
|||||||
addParam<>(_data, QStringLiteral("new_password"), newPassword);
|
addParam<>(_data, QStringLiteral("new_password"), newPassword);
|
||||||
addParam<IfNotEmpty>(_data, QStringLiteral("logout_devices"), logoutDevices);
|
addParam<IfNotEmpty>(_data, QStringLiteral("logout_devices"), logoutDevices);
|
||||||
addParam<IfNotEmpty>(_data, QStringLiteral("auth"), auth);
|
addParam<IfNotEmpty>(_data, QStringLiteral("auth"), auth);
|
||||||
setRequestData(std::move(_data));
|
setRequestData(_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<Connection *> Controller::connections() const
|
QVector<Connection *> Controller::connections() const
|
||||||
@@ -501,7 +507,7 @@ int Controller::accountCount() const
|
|||||||
return m_connections.count();
|
return m_connections.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Controller::quitOnLastWindowClosed() const
|
bool Controller::quitOnLastWindowClosed()
|
||||||
{
|
{
|
||||||
return QApplication::quitOnLastWindowClosed();
|
return QApplication::quitOnLastWindowClosed();
|
||||||
}
|
}
|
||||||
@@ -530,15 +536,17 @@ void Controller::setBusy(bool busy)
|
|||||||
|
|
||||||
Connection *Controller::activeConnection() const
|
Connection *Controller::activeConnection() const
|
||||||
{
|
{
|
||||||
if (m_connection.isNull())
|
if (m_connection.isNull()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
}
|
||||||
return m_connection;
|
return m_connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::setActiveConnection(Connection *connection)
|
void Controller::setActiveConnection(Connection *connection)
|
||||||
{
|
{
|
||||||
if (connection == m_connection)
|
if (connection == m_connection) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
m_connection = connection;
|
m_connection = connection;
|
||||||
Q_EMIT activeConnectionChanged();
|
Q_EMIT activeConnectionChanged();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,29 +33,29 @@ class Controller : public QObject
|
|||||||
public:
|
public:
|
||||||
static Controller &instance();
|
static Controller &instance();
|
||||||
|
|
||||||
QVector<Connection *> connections() const;
|
[[nodiscard]] QVector<Connection *> connections() const;
|
||||||
|
|
||||||
void setActiveConnection(Connection *connection);
|
void setActiveConnection(Connection *connection);
|
||||||
Connection *activeConnection() const;
|
[[nodiscard]] Connection *activeConnection() const;
|
||||||
|
|
||||||
void addConnection(Connection *c);
|
void addConnection(Connection *c);
|
||||||
void dropConnection(Connection *c);
|
void dropConnection(Connection *c);
|
||||||
|
|
||||||
Q_INVOKABLE void loginWithCredentials(QString, QString, QString, QString);
|
Q_INVOKABLE void loginWithCredentials(const QString &, const QString &, const QString &, QString);
|
||||||
Q_INVOKABLE void loginWithAccessToken(QString, QString, QString, QString);
|
Q_INVOKABLE void loginWithAccessToken(const QString &, const QString &, const QString &, const QString &);
|
||||||
|
|
||||||
Q_INVOKABLE void changePassword(Quotient::Connection *connection, const QString ¤tPassword, const QString &newPassword);
|
Q_INVOKABLE void changePassword(Quotient::Connection *connection, const QString ¤tPassword, const QString &newPassword);
|
||||||
|
|
||||||
int accountCount() const;
|
[[nodiscard]] int accountCount() const;
|
||||||
|
|
||||||
bool quitOnLastWindowClosed() const;
|
[[nodiscard]] static bool quitOnLastWindowClosed();
|
||||||
void setQuitOnLastWindowClosed(bool value);
|
void setQuitOnLastWindowClosed(bool value);
|
||||||
|
|
||||||
bool busy() const;
|
[[nodiscard]] bool busy() const;
|
||||||
void setBusy(bool busy);
|
void setBusy(bool busy);
|
||||||
|
|
||||||
void setAboutData(KAboutData aboutData);
|
void setAboutData(const KAboutData &aboutData);
|
||||||
KAboutData aboutData() const;
|
[[nodiscard]] KAboutData aboutData() const;
|
||||||
|
|
||||||
enum PasswordStatus {
|
enum PasswordStatus {
|
||||||
Success,
|
Success,
|
||||||
@@ -66,13 +66,13 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
explicit Controller(QObject *parent = nullptr);
|
explicit Controller(QObject *parent = nullptr);
|
||||||
~Controller();
|
~Controller() override;
|
||||||
|
|
||||||
QVector<Connection *> m_connections;
|
QVector<Connection *> m_connections;
|
||||||
QPointer<Connection> m_connection;
|
QPointer<Connection> m_connection;
|
||||||
bool m_busy = false;
|
bool m_busy = false;
|
||||||
|
|
||||||
QByteArray loadAccessTokenFromFile(const AccountSettings &account);
|
static QByteArray loadAccessTokenFromFile(const AccountSettings &account);
|
||||||
QByteArray loadAccessTokenFromKeyChain(const AccountSettings &account);
|
QByteArray loadAccessTokenFromKeyChain(const AccountSettings &account);
|
||||||
|
|
||||||
bool saveAccessTokenToFile(const AccountSettings &account, const QByteArray &accessToken);
|
bool saveAccessTokenToFile(const AccountSettings &account, const QByteArray &accessToken);
|
||||||
@@ -88,20 +88,20 @@ private Q_SLOTS:
|
|||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void busyChanged();
|
void busyChanged();
|
||||||
/// Error occured because of user inputs
|
/// Error occured because of user inputs
|
||||||
void errorOccured(QString error, QString detail);
|
void errorOccured(QString _t1, QString _t2);
|
||||||
|
|
||||||
/// Error occured because of server or bug in NeoChat
|
/// Error occured because of server or bug in NeoChat
|
||||||
void globalErrorOccured(QString error, QString detail);
|
void globalErrorOccured(QString _t1, QString _t2);
|
||||||
void syncDone();
|
void syncDone();
|
||||||
void connectionAdded(Quotient::Connection *conn);
|
void connectionAdded(Quotient::Connection *_t1);
|
||||||
void connectionDropped(Quotient::Connection *conn);
|
void connectionDropped(Quotient::Connection *_t1);
|
||||||
void initiated();
|
void initiated();
|
||||||
void notificationClicked(const QString roomId, const QString eventId);
|
void notificationClicked(const QString &_t1, const QString &_t2);
|
||||||
void quitOnLastWindowClosedChanged();
|
void quitOnLastWindowClosedChanged();
|
||||||
void unreadCountChanged();
|
void unreadCountChanged();
|
||||||
void activeConnectionChanged();
|
void activeConnectionChanged();
|
||||||
void aboutDataChanged();
|
void aboutDataChanged();
|
||||||
void passwordStatus(Controller::PasswordStatus status);
|
void passwordStatus(Controller::PasswordStatus _t1);
|
||||||
void showWindow();
|
void showWindow();
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
@@ -109,9 +109,9 @@ public Q_SLOTS:
|
|||||||
void joinRoom(Quotient::Connection *c, const QString &alias);
|
void joinRoom(Quotient::Connection *c, const QString &alias);
|
||||||
void createRoom(Quotient::Connection *c, const QString &name, const QString &topic);
|
void createRoom(Quotient::Connection *c, const QString &name, const QString &topic);
|
||||||
void createDirectChat(Quotient::Connection *c, const QString &userID);
|
void createDirectChat(Quotient::Connection *c, const QString &userID);
|
||||||
void playAudio(QUrl localFile);
|
static void playAudio(const QUrl &localFile);
|
||||||
void changeAvatar(Quotient::Connection *conn, QUrl localFile);
|
void changeAvatar(Quotient::Connection *conn, const QUrl &localFile);
|
||||||
void markAllMessagesAsRead(Quotient::Connection *conn);
|
static void markAllMessagesAsRead(Quotient::Connection *conn);
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO libQuotient 0.7: Drop
|
// TODO libQuotient 0.7: Drop
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ QVariantList EmojiModel::filterModel(const QString &filter)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmojiModel::emojiUsed(QVariant modelData)
|
void EmojiModel::emojiUsed(const QVariant &modelData)
|
||||||
{
|
{
|
||||||
QVariantList list = history();
|
QVariantList list = history();
|
||||||
|
|
||||||
@@ -78,8 +78,9 @@ void EmojiModel::emojiUsed(QVariant modelData)
|
|||||||
while (it != list.end()) {
|
while (it != list.end()) {
|
||||||
if ((*it).value<Emoji>().unicode == modelData.value<Emoji>().unicode) {
|
if ((*it).value<Emoji>().unicode == modelData.value<Emoji>().unicode) {
|
||||||
it = list.erase(it);
|
it = list.erase(it);
|
||||||
} else
|
} else {
|
||||||
it++;
|
it++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
list.push_front(modelData);
|
list.push_front(modelData);
|
||||||
|
|||||||
@@ -10,16 +10,15 @@
|
|||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
struct Emoji {
|
struct Emoji {
|
||||||
Emoji(const QString &u, const QString &s)
|
Emoji(QString u, QString s)
|
||||||
: unicode(u)
|
: unicode(std::move(std::move(u)))
|
||||||
, shortname(s)
|
, shortname(std::move(std::move(s)))
|
||||||
{
|
|
||||||
}
|
|
||||||
Emoji()
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
Emoji() = default;
|
||||||
|
|
||||||
friend QDataStream &operator<<(QDataStream &arch, const Emoji &object)
|
friend QDataStream &operator<<(QDataStream &arch, const Emoji &object)
|
||||||
{
|
{
|
||||||
@@ -67,13 +66,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
Q_INVOKABLE QVariantList history();
|
Q_INVOKABLE QVariantList history();
|
||||||
Q_INVOKABLE QVariantList filterModel(const QString &filter);
|
Q_INVOKABLE static QVariantList filterModel(const QString &filter);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void historyChanged();
|
void historyChanged();
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void emojiUsed(QVariant modelData);
|
void emojiUsed(const QVariant &modelData);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const QVariantList people;
|
static const QVariantList people;
|
||||||
|
|||||||
17
src/main.cpp
17
src/main.cpp
@@ -23,6 +23,7 @@
|
|||||||
#include "neochat-version.h"
|
#include "neochat-version.h"
|
||||||
|
|
||||||
#include "accountlistmodel.h"
|
#include "accountlistmodel.h"
|
||||||
|
#include "chatdocumenthandler.h"
|
||||||
#include "clipboard.h"
|
#include "clipboard.h"
|
||||||
#include "controller.h"
|
#include "controller.h"
|
||||||
#include "csapi/joining.h"
|
#include "csapi/joining.h"
|
||||||
@@ -30,6 +31,7 @@
|
|||||||
#include "emojimodel.h"
|
#include "emojimodel.h"
|
||||||
#include "matriximageprovider.h"
|
#include "matriximageprovider.h"
|
||||||
#include "messageeventmodel.h"
|
#include "messageeventmodel.h"
|
||||||
|
#include "neochatconfig.h"
|
||||||
#include "neochatroom.h"
|
#include "neochatroom.h"
|
||||||
#include "neochatuser.h"
|
#include "neochatuser.h"
|
||||||
#include "notificationsmanager.h"
|
#include "notificationsmanager.h"
|
||||||
@@ -39,8 +41,6 @@
|
|||||||
#include "sortfilterroomlistmodel.h"
|
#include "sortfilterroomlistmodel.h"
|
||||||
#include "userdirectorylistmodel.h"
|
#include "userdirectorylistmodel.h"
|
||||||
#include "userlistmodel.h"
|
#include "userlistmodel.h"
|
||||||
#include "neochatconfig.h"
|
|
||||||
#include "chatdocumenthandler.h"
|
|
||||||
|
|
||||||
using namespace Quotient;
|
using namespace Quotient;
|
||||||
|
|
||||||
@@ -60,8 +60,8 @@ int main(int argc, char *argv[])
|
|||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
app.setOrganizationName("KDE");
|
QApplication::setOrganizationName("KDE");
|
||||||
app.setWindowIcon(QIcon(":/assets/img/icon.png"));
|
QApplication::setWindowIcon(QIcon(":/assets/img/icon.png"));
|
||||||
|
|
||||||
KAboutData about(QStringLiteral("neochat"), i18n("Neochat"), QStringLiteral(NEOCHAT_VERSION_STRING), i18n("Matrix client"), KAboutLicense::GPL_V3, i18n("© 2018-2020 Black Hat, 2020 KDE Community"));
|
KAboutData about(QStringLiteral("neochat"), i18n("Neochat"), QStringLiteral(NEOCHAT_VERSION_STRING), i18n("Matrix client"), KAboutLicense::GPL_V3, i18n("© 2018-2020 Black Hat, 2020 KDE Community"));
|
||||||
about.addAuthor(i18n("Black Hat"), QString(), QStringLiteral("bhat@encom.eu.org"));
|
about.addAuthor(i18n("Black Hat"), QString(), QStringLiteral("bhat@encom.eu.org"));
|
||||||
@@ -123,14 +123,15 @@ int main(int argc, char *argv[])
|
|||||||
engine.addImageProvider(QLatin1String("mxc"), new MatrixImageProvider);
|
engine.addImageProvider(QLatin1String("mxc"), new MatrixImageProvider);
|
||||||
|
|
||||||
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;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef Q_OS_ANDROID
|
#ifndef Q_OS_ANDROID
|
||||||
QObject::connect(&service, &KDBusService::activateRequested, &engine, [&engine](const QStringList &/*arguments*/, const QString &/*workingDirectory*/) {
|
QObject::connect(&service, &KDBusService::activateRequested, &engine, [&engine](const QStringList & /*arguments*/, const QString & /*workingDirectory*/) {
|
||||||
const auto rootObjects = engine.rootObjects();
|
const auto rootObjects = engine.rootObjects();
|
||||||
for (auto obj : rootObjects) {
|
for (auto obj : rootObjects) {
|
||||||
auto view = qobject_cast<QQuickWindow*>(obj);
|
auto view = qobject_cast<QQuickWindow *>(obj);
|
||||||
if (view) {
|
if (view) {
|
||||||
view->raise();
|
view->raise();
|
||||||
return;
|
return;
|
||||||
@@ -138,5 +139,5 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
return app.exec();
|
return QApplication::exec();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,8 +73,9 @@ void ThumbnailResponse::prepareResult()
|
|||||||
|
|
||||||
QString localPath = QFileInfo(localFile).absolutePath();
|
QString localPath = QFileInfo(localFile).absolutePath();
|
||||||
QDir dir;
|
QDir dir;
|
||||||
if (!dir.exists(localPath))
|
if (!dir.exists(localPath)) {
|
||||||
dir.mkpath(localPath);
|
dir.mkpath(localPath);
|
||||||
|
}
|
||||||
|
|
||||||
image.save(localFile);
|
image.save(localFile);
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "messageeventmodel.h"
|
#include "messageeventmodel.h"
|
||||||
|
|
||||||
|
#include "neochatconfig.h"
|
||||||
#include <connection.h>
|
#include <connection.h>
|
||||||
#include <events/reactionevent.h>
|
#include <events/reactionevent.h>
|
||||||
#include <events/redactionevent.h>
|
#include <events/redactionevent.h>
|
||||||
@@ -12,11 +13,10 @@
|
|||||||
#include <events/roommemberevent.h>
|
#include <events/roommemberevent.h>
|
||||||
#include <events/simplestateevents.h>
|
#include <events/simplestateevents.h>
|
||||||
#include <user.h>
|
#include <user.h>
|
||||||
#include "neochatconfig.h"
|
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QTimeZone>
|
|
||||||
#include <QQmlEngine> // for qmlRegisterType()
|
#include <QQmlEngine> // for qmlRegisterType()
|
||||||
|
#include <QTimeZone>
|
||||||
|
|
||||||
#include <KLocalizedString>
|
#include <KLocalizedString>
|
||||||
|
|
||||||
@@ -70,14 +70,13 @@ MessageEventModel::MessageEventModel(QObject *parent)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageEventModel::~MessageEventModel()
|
MessageEventModel::~MessageEventModel() = default;
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void MessageEventModel::setRoom(NeoChatRoom *room)
|
void MessageEventModel::setRoom(NeoChatRoom *room)
|
||||||
{
|
{
|
||||||
if (room == m_currentRoom)
|
if (room == m_currentRoom) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
if (m_currentRoom) {
|
if (m_currentRoom) {
|
||||||
@@ -93,8 +92,9 @@ void MessageEventModel::setRoom(NeoChatRoom *room)
|
|||||||
beginInsertRows({}, timelineBaseIndex(), timelineBaseIndex() + int(events.size()) - 1);
|
beginInsertRows({}, timelineBaseIndex(), timelineBaseIndex() + int(events.size()) - 1);
|
||||||
});
|
});
|
||||||
connect(m_currentRoom, &Room::aboutToAddHistoricalMessages, this, [=](RoomEventsRange events) {
|
connect(m_currentRoom, &Room::aboutToAddHistoricalMessages, this, [=](RoomEventsRange events) {
|
||||||
if (rowCount() > 0)
|
if (rowCount() > 0) {
|
||||||
rowBelowInserted = rowCount() - 1; // See #312
|
rowBelowInserted = rowCount() - 1; // See #312
|
||||||
|
}
|
||||||
beginInsertRows({}, rowCount(), rowCount() + int(events.size()) - 1);
|
beginInsertRows({}, rowCount(), rowCount() + int(events.size()) - 1);
|
||||||
});
|
});
|
||||||
connect(m_currentRoom, &Room::addedMessages, this, [=](int lowest, int biggest) {
|
connect(m_currentRoom, &Room::addedMessages, this, [=](int lowest, int biggest) {
|
||||||
@@ -103,16 +103,18 @@ void MessageEventModel::setRoom(NeoChatRoom *room)
|
|||||||
auto rowBelowInserted = m_currentRoom->maxTimelineIndex() - biggest + timelineBaseIndex() - 1;
|
auto rowBelowInserted = m_currentRoom->maxTimelineIndex() - biggest + timelineBaseIndex() - 1;
|
||||||
refreshEventRoles(rowBelowInserted, {ShowAuthorRole});
|
refreshEventRoles(rowBelowInserted, {ShowAuthorRole});
|
||||||
}
|
}
|
||||||
for (auto i = m_currentRoom->maxTimelineIndex() - biggest; i <= m_currentRoom->maxTimelineIndex() - lowest; ++i)
|
for (auto i = m_currentRoom->maxTimelineIndex() - biggest; i <= m_currentRoom->maxTimelineIndex() - lowest; ++i) {
|
||||||
refreshLastUserEvents(i);
|
refreshLastUserEvents(i);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
connect(m_currentRoom, &Room::pendingEventAboutToAdd, this, [this] {
|
connect(m_currentRoom, &Room::pendingEventAboutToAdd, this, [this] {
|
||||||
beginInsertRows({}, 0, 0);
|
beginInsertRows({}, 0, 0);
|
||||||
});
|
});
|
||||||
connect(m_currentRoom, &Room::pendingEventAdded, this, &MessageEventModel::endInsertRows);
|
connect(m_currentRoom, &Room::pendingEventAdded, this, &MessageEventModel::endInsertRows);
|
||||||
connect(m_currentRoom, &Room::pendingEventAboutToMerge, this, [this](RoomEvent *, int i) {
|
connect(m_currentRoom, &Room::pendingEventAboutToMerge, this, [this](RoomEvent *, int i) {
|
||||||
if (i == 0)
|
if (i == 0) {
|
||||||
return; // No need to move anything, just refresh
|
return; // No need to move anything, just refresh
|
||||||
|
}
|
||||||
|
|
||||||
movingEvent = true;
|
movingEvent = true;
|
||||||
// Reverse i because row 0 is bottommost in the model
|
// Reverse i because row 0 is bottommost in the model
|
||||||
@@ -126,10 +128,12 @@ void MessageEventModel::setRoom(NeoChatRoom *room)
|
|||||||
}
|
}
|
||||||
refreshRow(timelineBaseIndex()); // Refresh the looks
|
refreshRow(timelineBaseIndex()); // Refresh the looks
|
||||||
refreshLastUserEvents(0);
|
refreshLastUserEvents(0);
|
||||||
if (m_currentRoom->timelineSize() > 1) // Refresh above
|
if (m_currentRoom->timelineSize() > 1) { // Refresh above
|
||||||
refreshEventRoles(timelineBaseIndex() + 1, {ReadMarkerRole});
|
refreshEventRoles(timelineBaseIndex() + 1, {ReadMarkerRole});
|
||||||
if (timelineBaseIndex() > 0) // Refresh below, see #312
|
}
|
||||||
|
if (timelineBaseIndex() > 0) { // Refresh below, see #312
|
||||||
refreshEventRoles(timelineBaseIndex() - 1, {ShowAuthorRole});
|
refreshEventRoles(timelineBaseIndex() - 1, {ShowAuthorRole});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
connect(m_currentRoom, &Room::pendingEventChanged, this, &MessageEventModel::refreshRow);
|
connect(m_currentRoom, &Room::pendingEventChanged, this, &MessageEventModel::refreshRow);
|
||||||
connect(m_currentRoom, &Room::pendingEventAboutToDiscard, this, [this](int i) {
|
connect(m_currentRoom, &Room::pendingEventAboutToDiscard, this, [this](int i) {
|
||||||
@@ -153,7 +157,7 @@ void MessageEventModel::setRoom(NeoChatRoom *room)
|
|||||||
connect(m_currentRoom, &Room::fileTransferCompleted, this, &MessageEventModel::refreshEvent);
|
connect(m_currentRoom, &Room::fileTransferCompleted, this, &MessageEventModel::refreshEvent);
|
||||||
connect(m_currentRoom, &Room::fileTransferFailed, this, &MessageEventModel::refreshEvent);
|
connect(m_currentRoom, &Room::fileTransferFailed, this, &MessageEventModel::refreshEvent);
|
||||||
connect(m_currentRoom, &Room::fileTransferCancelled, this, &MessageEventModel::refreshEvent);
|
connect(m_currentRoom, &Room::fileTransferCancelled, this, &MessageEventModel::refreshEvent);
|
||||||
connect(m_currentRoom, &Room::readMarkerForUserMoved, this, [=](User *, QString fromEventId, QString toEventId) {
|
connect(m_currentRoom, &Room::readMarkerForUserMoved, this, [=](User *, const QString &fromEventId, const QString &toEventId) {
|
||||||
refreshEventRoles(fromEventId, {UserMarkerRole});
|
refreshEventRoles(fromEventId, {UserMarkerRole});
|
||||||
refreshEventRoles(toEventId, {UserMarkerRole});
|
refreshEventRoles(toEventId, {UserMarkerRole});
|
||||||
});
|
});
|
||||||
@@ -162,8 +166,9 @@ void MessageEventModel::setRoom(NeoChatRoom *room)
|
|||||||
endResetModel();
|
endResetModel();
|
||||||
});
|
});
|
||||||
qDebug() << "Connected to room" << room->id() << "as" << room->localUser()->id();
|
qDebug() << "Connected to room" << room->id() << "as" << room->localUser()->id();
|
||||||
} else
|
} else {
|
||||||
lastReadEventId.clear();
|
lastReadEventId.clear();
|
||||||
|
}
|
||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,9 +200,9 @@ int MessageEventModel::refreshEventRoles(const QString &id, const QVector<int> &
|
|||||||
int row = -1;
|
int row = -1;
|
||||||
// First try pendingEvents because it is almost always very short.
|
// First try pendingEvents because it is almost always very short.
|
||||||
const auto pendingIt = m_currentRoom->findPendingEvent(id);
|
const auto pendingIt = m_currentRoom->findPendingEvent(id);
|
||||||
if (pendingIt != m_currentRoom->pendingEvents().end())
|
if (pendingIt != m_currentRoom->pendingEvents().end()) {
|
||||||
row = int(pendingIt - m_currentRoom->pendingEvents().begin());
|
row = int(pendingIt - m_currentRoom->pendingEvents().begin());
|
||||||
else {
|
} else {
|
||||||
const auto timelineIt = m_currentRoom->findInTimeline(id);
|
const auto timelineIt = m_currentRoom->findInTimeline(id);
|
||||||
if (timelineIt == m_currentRoom->timelineEdge()) {
|
if (timelineIt == m_currentRoom->timelineEdge()) {
|
||||||
qWarning() << "Trying to refresh inexistent event:" << id;
|
qWarning() << "Trying to refresh inexistent event:" << id;
|
||||||
@@ -218,43 +223,51 @@ QDateTime MessageEventModel::makeMessageTimestamp(const Quotient::Room::rev_iter
|
|||||||
{
|
{
|
||||||
const auto &timeline = m_currentRoom->messageEvents();
|
const auto &timeline = m_currentRoom->messageEvents();
|
||||||
auto ts = baseIt->event()->originTimestamp();
|
auto ts = baseIt->event()->originTimestamp();
|
||||||
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 Quotient::TimelineItem;
|
using Quotient::TimelineItem;
|
||||||
auto rit = std::find_if(baseIt, timeline.rend(), hasValidTimestamp);
|
auto rit = std::find_if(baseIt, timeline.rend(), hasValidTimestamp);
|
||||||
if (rit != timeline.rend())
|
if (rit != timeline.rend()) {
|
||||||
return {rit->event()->originTimestamp().date(), {0, 0}, Qt::LocalTime};
|
return {rit->event()->originTimestamp().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()->originTimestamp().date(), {0, 0}, Qt::LocalTime};
|
return {it->event()->originTimestamp().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::renderDate(QDateTime timestamp) const
|
QString MessageEventModel::renderDate(const QDateTime ×tamp)
|
||||||
{
|
{
|
||||||
auto date = timestamp.toLocalTime().date();
|
auto date = timestamp.toLocalTime().date();
|
||||||
if (date == QDate::currentDate())
|
if (date == QDate::currentDate()) {
|
||||||
return i18n("Today");
|
return i18n("Today");
|
||||||
if (date == QDate::currentDate().addDays(-1))
|
}
|
||||||
|
if (date == QDate::currentDate().addDays(-1)) {
|
||||||
return i18n("Yesterday");
|
return i18n("Yesterday");
|
||||||
if (date == QDate::currentDate().addDays(-2))
|
}
|
||||||
|
if (date == QDate::currentDate().addDays(-2)) {
|
||||||
return i18n("The day before yesterday");
|
return i18n("The day before yesterday");
|
||||||
if (date > QDate::currentDate().addDays(-7))
|
}
|
||||||
|
if (date > QDate::currentDate().addDays(-7)) {
|
||||||
return date.toString("dddd");
|
return date.toString("dddd");
|
||||||
|
}
|
||||||
|
|
||||||
return QLocale::system().toString(date, QLocale::ShortFormat);
|
return QLocale::system().toString(date, QLocale::ShortFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageEventModel::refreshLastUserEvents(int baseTimelineRow)
|
void MessageEventModel::refreshLastUserEvents(int baseTimelineRow)
|
||||||
{
|
{
|
||||||
if (!m_currentRoom || m_currentRoom->timelineSize() <= baseTimelineRow)
|
if (!m_currentRoom || m_currentRoom->timelineSize() <= baseTimelineRow) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const auto &timelineBottom = m_currentRoom->messageEvents().rbegin();
|
const auto &timelineBottom = m_currentRoom->messageEvents().rbegin();
|
||||||
const auto &lastSender = (*(timelineBottom + baseTimelineRow))->senderId();
|
const auto &lastSender = (*(timelineBottom + baseTimelineRow))->senderId();
|
||||||
@@ -269,8 +282,9 @@ void MessageEventModel::refreshLastUserEvents(int baseTimelineRow)
|
|||||||
|
|
||||||
int MessageEventModel::rowCount(const QModelIndex &parent) const
|
int MessageEventModel::rowCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
if (!m_currentRoom || parent.isValid())
|
if (!m_currentRoom || parent.isValid()) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
return m_currentRoom->timelineSize();
|
return m_currentRoom->timelineSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,8 +306,9 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
|
|||||||
{
|
{
|
||||||
const auto row = idx.row();
|
const auto row = idx.row();
|
||||||
|
|
||||||
if (!m_currentRoom || row < 0 || row >= int(m_currentRoom->pendingEvents().size()) + m_currentRoom->timelineSize())
|
if (!m_currentRoom || row < 0 || row >= int(m_currentRoom->pendingEvents().size()) + m_currentRoom->timelineSize()) {
|
||||||
return {};
|
return {};
|
||||||
|
};
|
||||||
|
|
||||||
bool isPending = row < timelineBaseIndex();
|
bool isPending = row < timelineBaseIndex();
|
||||||
const auto timelineIt = m_currentRoom->messageEvents().crbegin() + std::max(0, row - timelineBaseIndex());
|
const auto timelineIt = m_currentRoom->messageEvents().crbegin() + std::max(0, row - timelineBaseIndex());
|
||||||
@@ -338,14 +353,16 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
|
|||||||
|
|
||||||
return "message";
|
return "message";
|
||||||
}
|
}
|
||||||
if (evt.isStateEvent())
|
if (evt.isStateEvent()) {
|
||||||
return "state";
|
return "state";
|
||||||
|
}
|
||||||
|
|
||||||
return "other";
|
return "other";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (role == EventResolvedTypeRole)
|
if (role == EventResolvedTypeRole) {
|
||||||
return EventTypeRegistry::getMatrixType(evt.type());
|
return EventTypeRegistry::getMatrixType(evt.type());
|
||||||
|
}
|
||||||
|
|
||||||
if (role == AuthorRole) {
|
if (role == AuthorRole) {
|
||||||
auto author = static_cast<NeoChatUser *>(isPending ? m_currentRoom->localUser() : m_currentRoom->user(evt.senderId()));
|
auto author = static_cast<NeoChatUser *>(isPending ? m_currentRoom->localUser() : m_currentRoom->user(evt.senderId()));
|
||||||
@@ -374,29 +391,36 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (role == HighlightRole)
|
if (role == HighlightRole) {
|
||||||
return m_currentRoom->isEventHighlighted(&evt);
|
return m_currentRoom->isEventHighlighted(&evt);
|
||||||
|
}
|
||||||
|
|
||||||
if (role == ReadMarkerRole)
|
if (role == ReadMarkerRole) {
|
||||||
return evt.id() == lastReadEventId && row > timelineBaseIndex();
|
return evt.id() == lastReadEventId && row > timelineBaseIndex();
|
||||||
|
}
|
||||||
|
|
||||||
if (role == SpecialMarksRole) {
|
if (role == SpecialMarksRole) {
|
||||||
if (isPending)
|
if (isPending) {
|
||||||
return pendingIt->deliveryStatus();
|
return pendingIt->deliveryStatus();
|
||||||
|
}
|
||||||
|
|
||||||
auto *memberEvent = timelineIt->viewAs<RoomMemberEvent>();
|
auto *memberEvent = timelineIt->viewAs<RoomMemberEvent>();
|
||||||
if (memberEvent) {
|
if (memberEvent) {
|
||||||
if ((memberEvent->isJoin() || memberEvent->isLeave()) && !NeoChatConfig::self()->showLeaveJoinEvent())
|
if ((memberEvent->isJoin() || memberEvent->isLeave()) && !NeoChatConfig::self()->showLeaveJoinEvent()) {
|
||||||
return EventStatus::Hidden;
|
return EventStatus::Hidden;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is<RedactionEvent>(evt) || is<ReactionEvent>(evt))
|
if (is<RedactionEvent>(evt) || is<ReactionEvent>(evt)) {
|
||||||
return EventStatus::Hidden;
|
return EventStatus::Hidden;
|
||||||
if (evt.isRedacted())
|
}
|
||||||
|
if (evt.isRedacted()) {
|
||||||
return EventStatus::Hidden;
|
return EventStatus::Hidden;
|
||||||
|
}
|
||||||
|
|
||||||
if (evt.isStateEvent() && static_cast<const StateEventBase &>(evt).repeatsState())
|
if (evt.isStateEvent() && static_cast<const StateEventBase &>(evt).repeatsState()) {
|
||||||
return EventStatus::Hidden;
|
return EventStatus::Hidden;
|
||||||
|
}
|
||||||
|
|
||||||
if (auto e = eventCast<const RoomMessageEvent>(&evt)) {
|
if (auto e = eventCast<const RoomMessageEvent>(&evt)) {
|
||||||
if (!e->replacedEvent().isEmpty() && e->replacedEvent() != e->id()) {
|
if (!e->replacedEvent().isEmpty() && e->replacedEvent() != e->id()) {
|
||||||
@@ -404,24 +428,30 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_currentRoom->connection()->isIgnored(m_currentRoom->user(evt.senderId())))
|
if (m_currentRoom->connection()->isIgnored(m_currentRoom->user(evt.senderId()))) {
|
||||||
return EventStatus::Hidden;
|
return EventStatus::Hidden;
|
||||||
|
}
|
||||||
|
|
||||||
return EventStatus::Normal;
|
return EventStatus::Normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (role == EventIdRole)
|
if (role == EventIdRole) {
|
||||||
return !evt.id().isEmpty() ? evt.id() : evt.transactionId();
|
return !evt.id().isEmpty() ? evt.id() : evt.transactionId();
|
||||||
|
|
||||||
if (role == LongOperationRole) {
|
|
||||||
if (auto e = eventCast<const RoomMessageEvent>(&evt))
|
|
||||||
if (e->hasFileContent())
|
|
||||||
return QVariant::fromValue(m_currentRoom->fileTransferInfo(e->id()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (role == AnnotationRole)
|
if (role == LongOperationRole) {
|
||||||
if (isPending)
|
if (auto e = eventCast<const RoomMessageEvent>(&evt)) {
|
||||||
|
if (e->hasFileContent()) {
|
||||||
|
return QVariant::fromValue(m_currentRoom->fileTransferInfo(e->id()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (role == AnnotationRole) {
|
||||||
|
if (isPending) {
|
||||||
return pendingIt->annotation();
|
return pendingIt->annotation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (role == TimeRole || role == SectionRole) {
|
if (role == TimeRole || role == SectionRole) {
|
||||||
auto ts = isPending ? pendingIt->lastUpdated() : makeMessageTimestamp(timelineIt);
|
auto ts = isPending ? pendingIt->lastUpdated() : makeMessageTimestamp(timelineIt);
|
||||||
@@ -432,8 +462,9 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
|
|||||||
QVariantList variantList;
|
QVariantList variantList;
|
||||||
const auto users = m_currentRoom->usersAtEventId(evt.id());
|
const auto users = m_currentRoom->usersAtEventId(evt.id());
|
||||||
for (User *user : users) {
|
for (User *user : users) {
|
||||||
if (user == m_currentRoom->localUser())
|
if (user == m_currentRoom->localUser()) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
variantList.append(QVariant::fromValue(user));
|
variantList.append(QVariant::fromValue(user));
|
||||||
}
|
}
|
||||||
return variantList;
|
return variantList;
|
||||||
@@ -441,11 +472,13 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
|
|||||||
|
|
||||||
if (role == ReplyRole) {
|
if (role == ReplyRole) {
|
||||||
const QString &replyEventId = evt.contentJson()["m.relates_to"].toObject()["m.in_reply_to"].toObject()["event_id"].toString();
|
const QString &replyEventId = evt.contentJson()["m.relates_to"].toObject()["m.in_reply_to"].toObject()["event_id"].toString();
|
||||||
if (replyEventId.isEmpty())
|
if (replyEventId.isEmpty()) {
|
||||||
return {};
|
return {};
|
||||||
|
};
|
||||||
const auto replyIt = m_currentRoom->findInTimeline(replyEventId);
|
const auto replyIt = m_currentRoom->findInTimeline(replyEventId);
|
||||||
if (replyIt == m_currentRoom->timelineEdge())
|
if (replyIt == m_currentRoom->timelineEdge()) {
|
||||||
return {};
|
return {};
|
||||||
|
};
|
||||||
const auto &replyEvt = **replyIt;
|
const auto &replyEvt = **replyIt;
|
||||||
|
|
||||||
return QVariantMap {{"eventId", replyEventId}, {"display", m_currentRoom->eventToString(replyEvt, Qt::RichText)}, {"author", userAtEvent(static_cast<NeoChatUser *>(m_currentRoom->user(replyEvt.senderId())), m_currentRoom, evt)}};
|
return QVariantMap {{"eventId", replyEventId}, {"display", m_currentRoom->eventToString(replyEvt, Qt::RichText)}, {"author", userAtEvent(static_cast<NeoChatUser *>(m_currentRoom->user(replyEvt.senderId())), m_currentRoom, evt)}};
|
||||||
@@ -477,14 +510,17 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
|
|||||||
|
|
||||||
if (role == ReactionRole) {
|
if (role == ReactionRole) {
|
||||||
const auto &annotations = m_currentRoom->relatedEvents(evt, EventRelation::Annotation());
|
const auto &annotations = m_currentRoom->relatedEvents(evt, EventRelation::Annotation());
|
||||||
if (annotations.isEmpty())
|
if (annotations.isEmpty()) {
|
||||||
return {};
|
return {};
|
||||||
|
};
|
||||||
QMap<QString, QList<NeoChatUser *>> reactions = {};
|
QMap<QString, QList<NeoChatUser *>> reactions = {};
|
||||||
for (const auto &a : annotations) {
|
for (const auto &a : annotations) {
|
||||||
if (a->isRedacted()) // Just in case?
|
if (a->isRedacted()) { // Just in case?
|
||||||
continue;
|
continue;
|
||||||
if (auto e = eventCast<const ReactionEvent>(a))
|
}
|
||||||
|
if (auto e = eventCast<const ReactionEvent>(a)) {
|
||||||
reactions[e->relation().key].append(static_cast<NeoChatUser *>(m_currentRoom->user(e->senderId())));
|
reactions[e->relation().key].append(static_cast<NeoChatUser *>(m_currentRoom->user(e->senderId())));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reactions.isEmpty()) {
|
if (reactions.isEmpty()) {
|
||||||
|
|||||||
@@ -55,17 +55,17 @@ public:
|
|||||||
explicit MessageEventModel(QObject *parent = nullptr);
|
explicit MessageEventModel(QObject *parent = nullptr);
|
||||||
~MessageEventModel() override;
|
~MessageEventModel() override;
|
||||||
|
|
||||||
NeoChatRoom *room() const
|
[[nodiscard]] NeoChatRoom *room() const
|
||||||
{
|
{
|
||||||
return m_currentRoom;
|
return m_currentRoom;
|
||||||
}
|
}
|
||||||
void setRoom(NeoChatRoom *room);
|
void setRoom(NeoChatRoom *room);
|
||||||
|
|
||||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
[[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
[[nodiscard]] QVariant data(const QModelIndex &idx, int role = Qt::DisplayRole) const override;
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
Q_INVOKABLE int eventIDToIndex(const QString &eventID) const;
|
Q_INVOKABLE [[nodiscard]] int eventIDToIndex(const QString &eventID) const;
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
int refreshEvent(const QString &eventId);
|
int refreshEvent(const QString &eventId);
|
||||||
@@ -75,13 +75,13 @@ private:
|
|||||||
NeoChatRoom *m_currentRoom = nullptr;
|
NeoChatRoom *m_currentRoom = nullptr;
|
||||||
QString lastReadEventId;
|
QString lastReadEventId;
|
||||||
int rowBelowInserted = -1;
|
int rowBelowInserted = -1;
|
||||||
bool movingEvent = 0;
|
bool movingEvent = false;
|
||||||
|
|
||||||
int timelineBaseIndex() const;
|
[[nodiscard]] int timelineBaseIndex() const;
|
||||||
QDateTime makeMessageTimestamp(const Quotient::Room::rev_iter_t &baseIt) const;
|
[[nodiscard]] QDateTime makeMessageTimestamp(const Quotient::Room::rev_iter_t &baseIt) const;
|
||||||
QString renderDate(QDateTime timestamp) const;
|
[[nodiscard]] static QString renderDate(const QDateTime ×tamp);
|
||||||
|
|
||||||
void refreshLastUserEvents(int baseRow);
|
void refreshLastUserEvents(int baseTimelineRow);
|
||||||
void refreshEventRoles(int row, const QVector<int> &roles = {});
|
void refreshEventRoles(int row, const QVector<int> &roles = {});
|
||||||
int refreshEventRoles(const QString &eventId, const QVector<int> &roles = {});
|
int refreshEventRoles(const QString &eventId, const QVector<int> &roles = {});
|
||||||
|
|
||||||
|
|||||||
@@ -29,9 +29,9 @@
|
|||||||
#include "events/roompowerlevelsevent.h"
|
#include "events/roompowerlevelsevent.h"
|
||||||
#include "events/typingevent.h"
|
#include "events/typingevent.h"
|
||||||
#include "jobs/downloadfilejob.h"
|
#include "jobs/downloadfilejob.h"
|
||||||
|
#include "notificationsmanager.h"
|
||||||
#include "user.h"
|
#include "user.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "notificationsmanager.h"
|
|
||||||
|
|
||||||
#include <KLocalizedString>
|
#include <KLocalizedString>
|
||||||
|
|
||||||
@@ -45,14 +45,17 @@ NeoChatRoom::NeoChatRoom(Connection *connection, QString roomId, JoinState joinS
|
|||||||
setHasFileUploading(false);
|
setHasFileUploading(false);
|
||||||
});
|
});
|
||||||
connect(this, &NeoChatRoom::notificationCountChanged, this, [this]() {
|
connect(this, &NeoChatRoom::notificationCountChanged, this, [this]() {
|
||||||
if(messageEvents().size() == 0)
|
if (messageEvents().size() == 0) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
const RoomEvent *lastEvent = messageEvents().rbegin()->get();
|
const RoomEvent *lastEvent = messageEvents().rbegin()->get();
|
||||||
if (lastEvent->isStateEvent())
|
if (lastEvent->isStateEvent()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
User *sender = user(lastEvent->senderId());
|
User *sender = user(lastEvent->senderId());
|
||||||
if (sender == localUser())
|
if (sender == localUser()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
NotificationsManager::instance().postNotification(id(), lastEvent->id(), displayName(), sender->displayname(this), eventToString(*lastEvent), avatar(128));
|
NotificationsManager::instance().postNotification(id(), lastEvent->id(), displayName(), sender->displayname(this), eventToString(*lastEvent), avatar(128));
|
||||||
});
|
});
|
||||||
@@ -62,24 +65,25 @@ NeoChatRoom::NeoChatRoom(Connection *connection, QString roomId, JoinState joinS
|
|||||||
|
|
||||||
void NeoChatRoom::uploadFile(const QUrl &url, const QString &body)
|
void NeoChatRoom::uploadFile(const QUrl &url, const QString &body)
|
||||||
{
|
{
|
||||||
if (url.isEmpty())
|
if (url.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QString txnId = postFile(body.isEmpty() ? url.fileName() : body, url, false);
|
QString txnId = postFile(body.isEmpty() ? url.fileName() : body, url, false);
|
||||||
setHasFileUploading(true);
|
setHasFileUploading(true);
|
||||||
connect(this, &Room::fileTransferCompleted, [=](QString id, QUrl /*localFile*/, QUrl /*mxcUrl*/) {
|
connect(this, &Room::fileTransferCompleted, [=](const QString &id, const QUrl & /*localFile*/, const QUrl & /*mxcUrl*/) {
|
||||||
if (id == txnId) {
|
if (id == txnId) {
|
||||||
setFileUploadingProgress(0);
|
setFileUploadingProgress(0);
|
||||||
setHasFileUploading(false);
|
setHasFileUploading(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
connect(this, &Room::fileTransferFailed, [=](QString id, QString /*error*/) {
|
connect(this, &Room::fileTransferFailed, [=](const QString &id, const QString & /*error*/) {
|
||||||
if (id == txnId) {
|
if (id == txnId) {
|
||||||
setFileUploadingProgress(0);
|
setFileUploadingProgress(0);
|
||||||
setHasFileUploading(false);
|
setHasFileUploading(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
connect(this, &Room::fileTransferProgress, [=](QString id, qint64 progress, qint64 total) {
|
connect(this, &Room::fileTransferProgress, [=](const QString &id, qint64 progress, qint64 total) {
|
||||||
if (id == txnId) {
|
if (id == txnId) {
|
||||||
qDebug() << "Progress:" << progress << total;
|
qDebug() << "Progress:" << progress << total;
|
||||||
setFileUploadingProgress(int(float(progress) / float(total) * 100));
|
setFileUploadingProgress(int(float(progress) / float(total) * 100));
|
||||||
@@ -118,13 +122,16 @@ QString NeoChatRoom::lastEvent() const
|
|||||||
for (auto i = messageEvents().rbegin(); i < messageEvents().rend(); i++) {
|
for (auto i = messageEvents().rbegin(); i < messageEvents().rend(); i++) {
|
||||||
const RoomEvent *evt = i->get();
|
const RoomEvent *evt = i->get();
|
||||||
|
|
||||||
if (is<RedactionEvent>(*evt) || is<ReactionEvent>(*evt))
|
if (is<RedactionEvent>(*evt) || is<ReactionEvent>(*evt)) {
|
||||||
continue;
|
continue;
|
||||||
if (evt->isRedacted())
|
}
|
||||||
|
if (evt->isRedacted()) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (evt->isStateEvent() && static_cast<const StateEventBase &>(*evt).repeatsState())
|
if (evt->isStateEvent() && static_cast<const StateEventBase &>(*evt).repeatsState()) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (auto e = eventCast<const RoomMessageEvent>(evt)) {
|
if (auto e = eventCast<const RoomMessageEvent>(evt)) {
|
||||||
if (!e->replacedEvent().isEmpty() && e->replacedEvent() != e->id()) {
|
if (!e->replacedEvent().isEmpty() && e->replacedEvent() != e->id()) {
|
||||||
@@ -132,8 +139,9 @@ QString NeoChatRoom::lastEvent() const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connection()->isIgnored(user(evt->senderId())))
|
if (connection()->isIgnored(user(evt->senderId()))) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
return user(evt->senderId())->displayname() + (evt->isStateEvent() ? " " : ": ") + eventToString(*evt);
|
return user(evt->senderId())->displayname() + (evt->isStateEvent() ? " " : ": ") + eventToString(*evt);
|
||||||
}
|
}
|
||||||
@@ -148,12 +156,14 @@ bool NeoChatRoom::isEventHighlighted(const RoomEvent *e) const
|
|||||||
void NeoChatRoom::checkForHighlights(const Quotient::TimelineItem &ti)
|
void NeoChatRoom::checkForHighlights(const Quotient::TimelineItem &ti)
|
||||||
{
|
{
|
||||||
auto localUserId = localUser()->id();
|
auto localUserId = localUser()->id();
|
||||||
if (ti->senderId() == localUserId)
|
if (ti->senderId() == localUserId) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
if (auto *e = ti.viewAs<RoomMessageEvent>()) {
|
if (auto *e = ti.viewAs<RoomMessageEvent>()) {
|
||||||
const auto &text = e->plainBody();
|
const auto &text = e->plainBody();
|
||||||
if (text.contains(localUserId) || text.contains(roomMembername(localUserId)))
|
if (text.contains(localUserId) || text.contains(roomMembername(localUserId))) {
|
||||||
highlights.insert(e);
|
highlights.insert(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,8 +200,9 @@ void NeoChatRoom::countChanged()
|
|||||||
|
|
||||||
QDateTime NeoChatRoom::lastActiveTime() const
|
QDateTime NeoChatRoom::lastActiveTime() const
|
||||||
{
|
{
|
||||||
if (timelineSize() == 0)
|
if (timelineSize() == 0) {
|
||||||
return QDateTime();
|
return QDateTime();
|
||||||
|
}
|
||||||
return messageEvents().rbegin()->get()->originTimestamp();
|
return messageEvents().rbegin()->get()->originTimestamp();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,8 +218,9 @@ int NeoChatRoom::savedBottomVisibleIndex() const
|
|||||||
|
|
||||||
void NeoChatRoom::saveViewport(int topIndex, int bottomIndex)
|
void NeoChatRoom::saveViewport(int topIndex, int bottomIndex)
|
||||||
{
|
{
|
||||||
if (topIndex == -1 || bottomIndex == -1 || (bottomIndex == savedBottomVisibleIndex() && (bottomIndex == 0 || topIndex == savedTopVisibleIndex())))
|
if (topIndex == -1 || bottomIndex == -1 || (bottomIndex == savedBottomVisibleIndex() && (bottomIndex == 0 || topIndex == savedTopVisibleIndex()))) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
if (bottomIndex == 0) {
|
if (bottomIndex == 0) {
|
||||||
setFirstDisplayedEventId({});
|
setFirstDisplayedEventId({});
|
||||||
setLastDisplayedEventId({});
|
setLastDisplayedEventId({});
|
||||||
@@ -222,15 +234,16 @@ QVariantList NeoChatRoom::getUsers(const QString &keyword) const
|
|||||||
{
|
{
|
||||||
const auto userList = users();
|
const auto userList = users();
|
||||||
QVariantList matchedList;
|
QVariantList matchedList;
|
||||||
for (const auto u : userList)
|
for (const auto u : userList) {
|
||||||
if (u->displayname(this).contains(keyword, Qt::CaseInsensitive)) {
|
if (u->displayname(this).contains(keyword, Qt::CaseInsensitive)) {
|
||||||
matchedList.append(QVariant::fromValue(u));
|
matchedList.append(QVariant::fromValue(u));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return matchedList;
|
return matchedList;
|
||||||
}
|
}
|
||||||
|
|
||||||
QUrl NeoChatRoom::urlToMxcUrl(QUrl mxcUrl)
|
QUrl NeoChatRoom::urlToMxcUrl(const QUrl &mxcUrl)
|
||||||
{
|
{
|
||||||
return DownloadFileJob::makeRequestUrl(connection()->homeserver(), mxcUrl);
|
return DownloadFileJob::makeRequestUrl(connection()->homeserver(), mxcUrl);
|
||||||
}
|
}
|
||||||
@@ -268,7 +281,7 @@ QString NeoChatRoom::eventToString(const RoomEvent &evt, Qt::TextFormat format,
|
|||||||
if (removeReply) {
|
if (removeReply) {
|
||||||
htmlBody.remove(utils::removeRichReplyRegex);
|
htmlBody.remove(utils::removeRichReplyRegex);
|
||||||
}
|
}
|
||||||
htmlBody.replace(utils::userPillRegExp, "<b class=\"user-pill\">\\1</b>");
|
htmlBody.replace(utils::userPillRegExp, R"(<b class="user-pill">\1</b>)");
|
||||||
htmlBody.replace(utils::strikethroughRegExp, "<s>\\1</s>");
|
htmlBody.replace(utils::strikethroughRegExp, "<s>\\1</s>");
|
||||||
|
|
||||||
return htmlBody;
|
return htmlBody;
|
||||||
@@ -309,30 +322,35 @@ QString NeoChatRoom::eventToString(const RoomEvent &evt, Qt::TextFormat format,
|
|||||||
// The below code assumes senderName output in AuthorRole
|
// The below code assumes senderName output in AuthorRole
|
||||||
switch (e.membership()) {
|
switch (e.membership()) {
|
||||||
case MembershipType::Invite:
|
case MembershipType::Invite:
|
||||||
if (e.repeatsState())
|
if (e.repeatsState()) {
|
||||||
return i18n("reinvited %1 to the room", subjectName);
|
return i18n("reinvited %1 to the room", subjectName);
|
||||||
|
}
|
||||||
case MembershipType::Join: {
|
case MembershipType::Join: {
|
||||||
if (e.repeatsState())
|
if (e.repeatsState()) {
|
||||||
return i18n("joined the room (repeated)");
|
return i18n("joined the room (repeated)");
|
||||||
|
}
|
||||||
if (!e.prevContent() || e.membership() != e.prevContent()->membership) {
|
if (!e.prevContent() || e.membership() != e.prevContent()->membership) {
|
||||||
return e.membership() == MembershipType::Invite ? i18n("invited %1 to the room", subjectName) : i18n("joined the room");
|
return e.membership() == MembershipType::Invite ? i18n("invited %1 to the room", subjectName) : i18n("joined the room");
|
||||||
}
|
}
|
||||||
QString text {};
|
QString text {};
|
||||||
if (e.isRename()) {
|
if (e.isRename()) {
|
||||||
if (e.displayName().isEmpty())
|
if (e.displayName().isEmpty()) {
|
||||||
text = i18n("cleared their display name");
|
text = i18n("cleared their display name");
|
||||||
else
|
} else {
|
||||||
text = i18n("changed their display name to %1", e.displayName().toHtmlEscaped());
|
text = i18n("changed their display name to %1", e.displayName().toHtmlEscaped());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (e.isAvatarUpdate()) {
|
if (e.isAvatarUpdate()) {
|
||||||
if (!text.isEmpty())
|
if (!text.isEmpty()) {
|
||||||
text += i18n(" and ");
|
text += i18n(" and ");
|
||||||
if (e.avatarUrl().isEmpty())
|
}
|
||||||
|
if (e.avatarUrl().isEmpty()) {
|
||||||
text += i18n("cleared their avatar");
|
text += i18n("cleared their avatar");
|
||||||
else if (e.prevContent()->avatarUrl.isEmpty())
|
} else if (e.prevContent()->avatarUrl.isEmpty()) {
|
||||||
text += i18n("set an avatar");
|
text += i18n("set an avatar");
|
||||||
else
|
} else {
|
||||||
text += i18n("updated their avatar");
|
text += i18n("updated their avatar");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
@@ -378,7 +396,7 @@ QString NeoChatRoom::eventToString(const RoomEvent &evt, Qt::TextFormat format,
|
|||||||
i18n("Unknown event"));
|
i18n("Unknown event"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NeoChatRoom::changeAvatar(QUrl localFile)
|
void NeoChatRoom::changeAvatar(const QUrl &localFile)
|
||||||
{
|
{
|
||||||
const auto job = connection()->uploadFile(localFile.toLocalFile());
|
const auto job = connection()->uploadFile(localFile.toLocalFile());
|
||||||
if (isJobRunning(job)) {
|
if (isJobRunning(job)) {
|
||||||
@@ -391,8 +409,9 @@ void NeoChatRoom::changeAvatar(QUrl localFile)
|
|||||||
void NeoChatRoom::addLocalAlias(const QString &alias)
|
void NeoChatRoom::addLocalAlias(const QString &alias)
|
||||||
{
|
{
|
||||||
auto a = aliases();
|
auto a = aliases();
|
||||||
if (a.contains(alias))
|
if (a.contains(alias)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
a += alias;
|
a += alias;
|
||||||
|
|
||||||
@@ -402,8 +421,9 @@ void NeoChatRoom::addLocalAlias(const QString &alias)
|
|||||||
void NeoChatRoom::removeLocalAlias(const QString &alias)
|
void NeoChatRoom::removeLocalAlias(const QString &alias)
|
||||||
{
|
{
|
||||||
auto a = aliases();
|
auto a = aliases();
|
||||||
if (!a.contains(alias))
|
if (!a.contains(alias)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
a.removeAll(alias);
|
a.removeAll(alias);
|
||||||
|
|
||||||
@@ -467,8 +487,9 @@ void NeoChatRoom::postPlainMessage(const QString &text, MessageEventType type, c
|
|||||||
{
|
{
|
||||||
bool isReply = !replyEventId.isEmpty();
|
bool isReply = !replyEventId.isEmpty();
|
||||||
const auto replyIt = findInTimeline(replyEventId);
|
const auto replyIt = findInTimeline(replyEventId);
|
||||||
if (replyIt == timelineEdge())
|
if (replyIt == timelineEdge()) {
|
||||||
isReply = false;
|
isReply = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (isReply) {
|
if (isReply) {
|
||||||
const auto &replyEvt = **replyIt;
|
const auto &replyEvt = **replyIt;
|
||||||
@@ -511,8 +532,9 @@ void NeoChatRoom::postHtmlMessage(const QString &text, const QString &html, Mess
|
|||||||
{
|
{
|
||||||
bool isReply = !replyEventId.isEmpty();
|
bool isReply = !replyEventId.isEmpty();
|
||||||
const auto replyIt = findInTimeline(replyEventId);
|
const auto replyIt = findInTimeline(replyEventId);
|
||||||
if (replyIt == timelineEdge())
|
if (replyIt == timelineEdge()) {
|
||||||
isReply = false;
|
isReply = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (isReply) {
|
if (isReply) {
|
||||||
const auto &replyEvt = **replyIt;
|
const auto &replyEvt = **replyIt;
|
||||||
@@ -553,12 +575,14 @@ void NeoChatRoom::postHtmlMessage(const QString &text, const QString &html, Mess
|
|||||||
|
|
||||||
void NeoChatRoom::toggleReaction(const QString &eventId, const QString &reaction)
|
void NeoChatRoom::toggleReaction(const QString &eventId, const QString &reaction)
|
||||||
{
|
{
|
||||||
if (eventId.isEmpty() || reaction.isEmpty())
|
if (eventId.isEmpty() || reaction.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const auto eventIt = findInTimeline(eventId);
|
const auto eventIt = findInTimeline(eventId);
|
||||||
if (eventIt == timelineEdge())
|
if (eventIt == timelineEdge()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const auto &evt = **eventIt;
|
const auto &evt = **eventIt;
|
||||||
|
|
||||||
@@ -568,8 +592,9 @@ void NeoChatRoom::toggleReaction(const QString &eventId, const QString &reaction
|
|||||||
if (!annotations.isEmpty()) {
|
if (!annotations.isEmpty()) {
|
||||||
for (const auto &a : annotations) {
|
for (const auto &a : annotations) {
|
||||||
if (auto e = eventCast<const ReactionEvent>(a)) {
|
if (auto e = eventCast<const ReactionEvent>(a)) {
|
||||||
if (e->relation().key != reaction)
|
if (e->relation().key != reaction) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (e->senderId() == localUser()->id()) {
|
if (e->senderId() == localUser()->id()) {
|
||||||
redactEventIds.push_back(e->id());
|
redactEventIds.push_back(e->id());
|
||||||
@@ -588,12 +613,13 @@ void NeoChatRoom::toggleReaction(const QString &eventId, const QString &reaction
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NeoChatRoom::containsUser(QString userID) const
|
bool NeoChatRoom::containsUser(const QString &userID) const
|
||||||
{
|
{
|
||||||
auto u = Room::user(userID);
|
auto u = Room::user(userID);
|
||||||
|
|
||||||
if (!u)
|
if (!u) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return Room::memberJoinState(u) != JoinState::Leave;
|
return Room::memberJoinState(u) != JoinState::Leave;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,14 +35,14 @@ class NeoChatRoom : public Room
|
|||||||
public:
|
public:
|
||||||
explicit NeoChatRoom(Connection *connection, QString roomId, JoinState joinState = {});
|
explicit NeoChatRoom(Connection *connection, QString roomId, JoinState joinState = {});
|
||||||
|
|
||||||
QVariantList getUsersTyping() const;
|
[[nodiscard]] QVariantList getUsersTyping() const;
|
||||||
|
|
||||||
QString lastEvent() const;
|
[[nodiscard]] QString lastEvent() const;
|
||||||
bool isEventHighlighted(const Quotient::RoomEvent *e) const;
|
bool isEventHighlighted(const Quotient::RoomEvent *e) const;
|
||||||
|
|
||||||
QDateTime lastActiveTime() const;
|
[[nodiscard]] QDateTime lastActiveTime() const;
|
||||||
|
|
||||||
bool hasFileUploading() const
|
[[nodiscard]] bool hasFileUploading() const
|
||||||
{
|
{
|
||||||
return m_hasFileUploading;
|
return m_hasFileUploading;
|
||||||
}
|
}
|
||||||
@@ -55,7 +55,7 @@ public:
|
|||||||
Q_EMIT hasFileUploadingChanged();
|
Q_EMIT hasFileUploadingChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
int fileUploadingProgress() const
|
[[nodiscard]] int fileUploadingProgress() const
|
||||||
{
|
{
|
||||||
return m_fileUploadingProgress;
|
return m_fileUploadingProgress;
|
||||||
}
|
}
|
||||||
@@ -68,24 +68,24 @@ public:
|
|||||||
Q_EMIT fileUploadingProgressChanged();
|
Q_EMIT fileUploadingProgressChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool readMarkerLoaded() const;
|
[[nodiscard]] bool readMarkerLoaded() const;
|
||||||
|
|
||||||
Q_INVOKABLE int savedTopVisibleIndex() const;
|
Q_INVOKABLE [[nodiscard]] int savedTopVisibleIndex() const;
|
||||||
Q_INVOKABLE int savedBottomVisibleIndex() const;
|
Q_INVOKABLE [[nodiscard]] int savedBottomVisibleIndex() const;
|
||||||
Q_INVOKABLE void saveViewport(int topIndex, int bottomIndex);
|
Q_INVOKABLE void saveViewport(int topIndex, int bottomIndex);
|
||||||
|
|
||||||
Q_INVOKABLE QVariantList getUsers(const QString &keyword) const;
|
Q_INVOKABLE [[nodiscard]] QVariantList getUsers(const QString &keyword) const;
|
||||||
|
|
||||||
Q_INVOKABLE QUrl urlToMxcUrl(QUrl mxcUrl);
|
Q_INVOKABLE QUrl urlToMxcUrl(const QUrl &mxcUrl);
|
||||||
|
|
||||||
QString avatarMediaId() const;
|
[[nodiscard]] QString avatarMediaId() const;
|
||||||
|
|
||||||
QString eventToString(const RoomEvent &evt, Qt::TextFormat format = Qt::PlainText, bool removeReply = true) const;
|
[[nodiscard]] QString eventToString(const RoomEvent &evt, Qt::TextFormat format = Qt::PlainText, bool removeReply = true) const;
|
||||||
|
|
||||||
Q_INVOKABLE bool containsUser(QString userID) const;
|
Q_INVOKABLE [[nodiscard]] bool containsUser(const QString &userID) const;
|
||||||
|
|
||||||
Q_INVOKABLE bool canSendEvent(const QString &eventType) const;
|
Q_INVOKABLE [[nodiscard]] bool canSendEvent(const QString &eventType) const;
|
||||||
Q_INVOKABLE bool canSendState(const QString &eventType) const;
|
Q_INVOKABLE [[nodiscard]] bool canSendState(const QString &eventType) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString m_cachedInput;
|
QString m_cachedInput;
|
||||||
@@ -100,7 +100,7 @@ private:
|
|||||||
void onAddHistoricalTimelineEvents(rev_iter_t from) override;
|
void onAddHistoricalTimelineEvents(rev_iter_t from) override;
|
||||||
void onRedaction(const RoomEvent &prevEvent, const RoomEvent &after) override;
|
void onRedaction(const RoomEvent &prevEvent, const RoomEvent &after) override;
|
||||||
|
|
||||||
static QString markdownToHTML(const QString &plaintext);
|
static QString markdownToHTML(const QString &markdown);
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void countChanged();
|
void countChanged();
|
||||||
@@ -121,7 +121,7 @@ public Q_SLOTS:
|
|||||||
void postArbitaryMessage(const QString &text, Quotient::RoomMessageEvent::MsgType type, const QString &replyEventId);
|
void postArbitaryMessage(const QString &text, Quotient::RoomMessageEvent::MsgType type, const QString &replyEventId);
|
||||||
void postPlainMessage(const QString &text, Quotient::RoomMessageEvent::MsgType type = Quotient::MessageEventType::Text, const QString &replyEventId = "");
|
void postPlainMessage(const QString &text, Quotient::RoomMessageEvent::MsgType type = Quotient::MessageEventType::Text, const QString &replyEventId = "");
|
||||||
void postHtmlMessage(const QString &text, const QString &html, Quotient::MessageEventType type = Quotient::MessageEventType::Text, const QString &replyEventId = "");
|
void postHtmlMessage(const QString &text, const QString &html, Quotient::MessageEventType type = Quotient::MessageEventType::Text, const QString &replyEventId = "");
|
||||||
void changeAvatar(QUrl localFile);
|
void changeAvatar(const QUrl &localFile);
|
||||||
void addLocalAlias(const QString &alias);
|
void addLocalAlias(const QString &alias);
|
||||||
void removeLocalAlias(const QString &alias);
|
void removeLocalAlias(const QString &alias);
|
||||||
void toggleReaction(const QString &eventId, const QString &reaction);
|
void toggleReaction(const QString &eventId, const QString &reaction);
|
||||||
|
|||||||
@@ -6,11 +6,12 @@
|
|||||||
#include "neochatuser.h"
|
#include "neochatuser.h"
|
||||||
|
|
||||||
#include <PlatformTheme> // Kirigami
|
#include <PlatformTheme> // Kirigami
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "csapi/profile.h"
|
#include "csapi/profile.h"
|
||||||
|
|
||||||
NeoChatUser::NeoChatUser(QString userId, Connection *connection)
|
NeoChatUser::NeoChatUser(QString userId, Connection *connection)
|
||||||
: User(userId, connection)
|
: User(std::move(userId), connection)
|
||||||
{
|
{
|
||||||
m_theme = static_cast<Kirigami::PlatformTheme *>(qmlAttachedPropertiesObject<Kirigami::PlatformTheme>(this, true));
|
m_theme = static_cast<Kirigami::PlatformTheme *>(qmlAttachedPropertiesObject<Kirigami::PlatformTheme>(this, true));
|
||||||
Q_ASSERT(m_theme);
|
Q_ASSERT(m_theme);
|
||||||
@@ -23,10 +24,11 @@ QColor NeoChatUser::color()
|
|||||||
return m_color;
|
return m_color;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NeoChatUser::setColor(QColor color)
|
void NeoChatUser::setColor(const QColor &color)
|
||||||
{
|
{
|
||||||
if (m_color == color)
|
if (m_color == color) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_color = color;
|
m_color = color;
|
||||||
emit colorChanged(m_color);
|
emit colorChanged(m_color);
|
||||||
|
|||||||
@@ -26,10 +26,10 @@ public:
|
|||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
QColor color();
|
QColor color();
|
||||||
void setColor(QColor color);
|
void setColor(const QColor &color);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void colorChanged(QColor color);
|
void colorChanged(QColor _t1);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Kirigami::PlatformTheme *m_theme = nullptr;
|
Kirigami::PlatformTheme *m_theme = nullptr;
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ NotificationsManager &NotificationsManager::instance()
|
|||||||
return _instance;
|
return _instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NotificationsManager::NotificationsManager(QObject *parent)
|
NotificationsManager::NotificationsManager(QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
{
|
{
|
||||||
@@ -27,7 +26,7 @@ NotificationsManager::NotificationsManager(QObject *parent)
|
|||||||
|
|
||||||
void NotificationsManager::postNotification(const QString &roomid, const QString &eventid, const QString &roomname, const QString &sender, const QString &text, const QImage &icon)
|
void NotificationsManager::postNotification(const QString &roomid, const QString &eventid, const QString &roomname, const QString &sender, const QString &text, const QImage &icon)
|
||||||
{
|
{
|
||||||
if(!NeoChatConfig::self()->showNotifications()) {
|
if (!NeoChatConfig::self()->showNotifications()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,8 +12,9 @@ PublicRoomListModel::PublicRoomListModel(QObject *parent)
|
|||||||
|
|
||||||
void PublicRoomListModel::setConnection(Connection *conn)
|
void PublicRoomListModel::setConnection(Connection *conn)
|
||||||
{
|
{
|
||||||
if (m_connection == conn)
|
if (m_connection == conn) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
|
|
||||||
@@ -46,8 +47,9 @@ void PublicRoomListModel::setConnection(Connection *conn)
|
|||||||
|
|
||||||
void PublicRoomListModel::setServer(const QString &value)
|
void PublicRoomListModel::setServer(const QString &value)
|
||||||
{
|
{
|
||||||
if (m_server == value)
|
if (m_server == value) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_server = value;
|
m_server = value;
|
||||||
|
|
||||||
@@ -74,8 +76,9 @@ void PublicRoomListModel::setServer(const QString &value)
|
|||||||
|
|
||||||
void PublicRoomListModel::setKeyword(const QString &value)
|
void PublicRoomListModel::setKeyword(const QString &value)
|
||||||
{
|
{
|
||||||
if (m_keyword == value)
|
if (m_keyword == value) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_keyword = value;
|
m_keyword = value;
|
||||||
|
|
||||||
@@ -102,8 +105,9 @@ void PublicRoomListModel::setKeyword(const QString &value)
|
|||||||
|
|
||||||
void PublicRoomListModel::next(int count)
|
void PublicRoomListModel::next(int count)
|
||||||
{
|
{
|
||||||
if (count < 1)
|
if (count < 1) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (job) {
|
if (job) {
|
||||||
qDebug() << "PublicRoomListModel: Other jobs running, ignore";
|
qDebug() << "PublicRoomListModel: Other jobs running, ignore";
|
||||||
@@ -134,8 +138,9 @@ void PublicRoomListModel::next(int count)
|
|||||||
|
|
||||||
QVariant PublicRoomListModel::data(const QModelIndex &index, int role) const
|
QVariant PublicRoomListModel::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
if (!index.isValid())
|
if (!index.isValid()) {
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
if (index.row() >= rooms.count()) {
|
if (index.row() >= rooms.count()) {
|
||||||
qDebug() << "PublicRoomListModel, something's wrong: index.row() >= "
|
qDebug() << "PublicRoomListModel, something's wrong: index.row() >= "
|
||||||
@@ -195,8 +200,9 @@ QVariant PublicRoomListModel::data(const QModelIndex &index, int role) const
|
|||||||
return room.worldReadable;
|
return room.worldReadable;
|
||||||
}
|
}
|
||||||
if (role == IsJoinedRole) {
|
if (role == IsJoinedRole) {
|
||||||
if (!m_connection)
|
if (!m_connection) {
|
||||||
return {};
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
return m_connection->room(room.roomId, JoinState::Join) != nullptr;
|
return m_connection->room(room.roomId, JoinState::Join) != nullptr;
|
||||||
}
|
}
|
||||||
@@ -223,8 +229,9 @@ QHash<int, QByteArray> PublicRoomListModel::roleNames() const
|
|||||||
|
|
||||||
int PublicRoomListModel::rowCount(const QModelIndex &parent) const
|
int PublicRoomListModel::rowCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
if (parent.isValid())
|
if (parent.isValid()) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return rooms.count();
|
return rooms.count();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,30 +38,30 @@ public:
|
|||||||
|
|
||||||
PublicRoomListModel(QObject *parent = nullptr);
|
PublicRoomListModel(QObject *parent = nullptr);
|
||||||
|
|
||||||
QVariant data(const QModelIndex &index, int role = NameRole) const override;
|
[[nodiscard]] QVariant data(const QModelIndex &index, int role = NameRole) const override;
|
||||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
[[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
Connection *connection() const
|
[[nodiscard]] Connection *connection() const
|
||||||
{
|
{
|
||||||
return m_connection;
|
return m_connection;
|
||||||
}
|
}
|
||||||
void setConnection(Connection *value);
|
void setConnection(Connection *conn);
|
||||||
|
|
||||||
QString server() const
|
[[nodiscard]] QString server() const
|
||||||
{
|
{
|
||||||
return m_server;
|
return m_server;
|
||||||
}
|
}
|
||||||
void setServer(const QString &value);
|
void setServer(const QString &value);
|
||||||
|
|
||||||
QString keyword() const
|
[[nodiscard]] QString keyword() const
|
||||||
{
|
{
|
||||||
return m_keyword;
|
return m_keyword;
|
||||||
}
|
}
|
||||||
void setKeyword(const QString &value);
|
void setKeyword(const QString &value);
|
||||||
|
|
||||||
bool hasMore() const;
|
[[nodiscard]] bool hasMore() const;
|
||||||
|
|
||||||
Q_INVOKABLE void next(int count = 50);
|
Q_INVOKABLE void next(int count = 50);
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
*/
|
*/
|
||||||
#include "roomlistmodel.h"
|
#include "roomlistmodel.h"
|
||||||
|
|
||||||
|
#include "neochatconfig.h"
|
||||||
#include "user.h"
|
#include "user.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "neochatconfig.h"
|
|
||||||
|
|
||||||
#include "events/roomevent.h"
|
#include "events/roomevent.h"
|
||||||
|
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
|
|
||||||
#include <KLocalizedString>
|
#include <KLocalizedString>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
RoomListModel::RoomListModel(QObject *parent)
|
RoomListModel::RoomListModel(QObject *parent)
|
||||||
: QAbstractListModel(parent)
|
: QAbstractListModel(parent)
|
||||||
@@ -27,16 +28,16 @@ RoomListModel::RoomListModel(QObject *parent)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RoomListModel::~RoomListModel()
|
RoomListModel::~RoomListModel() = default;
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void RoomListModel::setConnection(Connection *connection)
|
void RoomListModel::setConnection(Connection *connection)
|
||||||
{
|
{
|
||||||
if (connection == m_connection)
|
if (connection == m_connection) {
|
||||||
return;
|
return;
|
||||||
if (m_connection)
|
}
|
||||||
|
if (m_connection) {
|
||||||
m_connection->disconnect(this);
|
m_connection->disconnect(this);
|
||||||
|
}
|
||||||
if (!connection) {
|
if (!connection) {
|
||||||
qDebug() << "Removing current connection...";
|
qDebug() << "Removing current connection...";
|
||||||
m_connection = nullptr;
|
m_connection = nullptr;
|
||||||
@@ -61,13 +62,14 @@ void RoomListModel::setConnection(Connection *connection)
|
|||||||
auto refreshRooms = [this, &connection](Quotient::DirectChatsMap rooms) {
|
auto refreshRooms = [this, &connection](Quotient::DirectChatsMap rooms) {
|
||||||
for (const QString &roomID : qAsConst(rooms)) {
|
for (const QString &roomID : qAsConst(rooms)) {
|
||||||
auto room = connection->room(roomID);
|
auto room = connection->room(roomID);
|
||||||
if (room)
|
if (room) {
|
||||||
refresh(static_cast<NeoChatRoom *>(room));
|
refresh(static_cast<NeoChatRoom *>(room));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
refreshRooms(additions);
|
refreshRooms(std::move(additions));
|
||||||
refreshRooms(removals);
|
refreshRooms(std::move(removals));
|
||||||
});
|
});
|
||||||
|
|
||||||
doResetModel();
|
doResetModel();
|
||||||
@@ -128,29 +130,37 @@ void RoomListModel::connectRoomSignals(NeoChatRoom *room)
|
|||||||
refresh(room, {LastEventRole});
|
refresh(room, {LastEventRole});
|
||||||
});
|
});
|
||||||
connect(room, &Room::notificationCountChanged, this, [=] {
|
connect(room, &Room::notificationCountChanged, this, [=] {
|
||||||
if (room->notificationCount() == 0)
|
if (room->notificationCount() == 0) {
|
||||||
return;
|
return;
|
||||||
if (room->timelineSize() == 0)
|
}
|
||||||
|
if (room->timelineSize() == 0) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
const RoomEvent *lastEvent = room->messageEvents().rbegin()->get();
|
const RoomEvent *lastEvent = room->messageEvents().rbegin()->get();
|
||||||
if (lastEvent->isStateEvent())
|
if (lastEvent->isStateEvent()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
User *sender = room->user(lastEvent->senderId());
|
User *sender = room->user(lastEvent->senderId());
|
||||||
if (sender == room->localUser())
|
if (sender == room->localUser()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
Q_EMIT newMessage(room->id(), lastEvent->id(), room->displayName(), sender->displayname(), room->eventToString(*lastEvent), room->avatar(128));
|
Q_EMIT newMessage(room->id(), lastEvent->id(), room->displayName(), sender->displayname(), room->eventToString(*lastEvent), room->avatar(128));
|
||||||
});
|
});
|
||||||
connect(room, &Room::highlightCountChanged, this, [=] {
|
connect(room, &Room::highlightCountChanged, this, [=] {
|
||||||
if (room->highlightCount() == 0)
|
if (room->highlightCount() == 0) {
|
||||||
return;
|
return;
|
||||||
if (room->timelineSize() == 0)
|
}
|
||||||
|
if (room->timelineSize() == 0) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
const RoomEvent *lastEvent = room->messageEvents().rbegin()->get();
|
const RoomEvent *lastEvent = room->messageEvents().rbegin()->get();
|
||||||
if (lastEvent->isStateEvent())
|
if (lastEvent->isStateEvent()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
User *sender = room->user(lastEvent->senderId());
|
User *sender = room->user(lastEvent->senderId());
|
||||||
if (sender == room->localUser())
|
if (sender == room->localUser()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
Q_EMIT newHighlight(room->id(), lastEvent->id(), room->displayName(), sender->displayname(), room->eventToString(*lastEvent), room->avatar(128));
|
Q_EMIT newHighlight(room->id(), lastEvent->id(), room->displayName(), sender->displayname(), room->eventToString(*lastEvent), room->avatar(128));
|
||||||
});
|
});
|
||||||
connect(room, &Room::notificationCountChanged, this, &RoomListModel::refreshNotificationCount);
|
connect(room, &Room::notificationCountChanged, this, &RoomListModel::refreshNotificationCount);
|
||||||
@@ -206,8 +216,9 @@ void RoomListModel::deleteRoom(Room *room)
|
|||||||
{
|
{
|
||||||
qDebug() << "Deleting room" << room->id();
|
qDebug() << "Deleting room" << room->id();
|
||||||
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()) {
|
||||||
return; // Already deleted, nothing to do
|
return; // Already deleted, nothing to do
|
||||||
|
}
|
||||||
qDebug() << "Erasing room" << room->id();
|
qDebug() << "Erasing room" << room->id();
|
||||||
const int row = it - m_rooms.begin();
|
const int row = it - m_rooms.begin();
|
||||||
beginRemoveRows(QModelIndex(), row, row);
|
beginRemoveRows(QModelIndex(), row, row);
|
||||||
@@ -217,57 +228,74 @@ void RoomListModel::deleteRoom(Room *room)
|
|||||||
|
|
||||||
int RoomListModel::rowCount(const QModelIndex &parent) const
|
int RoomListModel::rowCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
if (parent.isValid())
|
if (parent.isValid()) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
return m_rooms.count();
|
return m_rooms.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant RoomListModel::data(const QModelIndex &index, int role) const
|
QVariant RoomListModel::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
if (!index.isValid())
|
if (!index.isValid()) {
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
if (index.row() >= m_rooms.count()) {
|
if (index.row() >= m_rooms.count()) {
|
||||||
qDebug() << "UserListModel: something wrong here...";
|
qDebug() << "UserListModel: something wrong here...";
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
NeoChatRoom *room = m_rooms.at(index.row());
|
NeoChatRoom *room = m_rooms.at(index.row());
|
||||||
if (role == NameRole)
|
if (role == NameRole) {
|
||||||
return room->displayName();
|
return room->displayName();
|
||||||
if (role == AvatarRole)
|
}
|
||||||
|
if (role == AvatarRole) {
|
||||||
return room->avatarMediaId();
|
return room->avatarMediaId();
|
||||||
if (role == TopicRole)
|
}
|
||||||
|
if (role == TopicRole) {
|
||||||
return room->topic();
|
return room->topic();
|
||||||
|
}
|
||||||
if (role == CategoryRole) {
|
if (role == CategoryRole) {
|
||||||
if (room->joinState() == JoinState::Invite)
|
if (room->joinState() == JoinState::Invite) {
|
||||||
return RoomType::Invited;
|
return RoomType::Invited;
|
||||||
if (room->isFavourite())
|
}
|
||||||
|
if (room->isFavourite()) {
|
||||||
return RoomType::Favorite;
|
return RoomType::Favorite;
|
||||||
if (room->isDirectChat())
|
}
|
||||||
|
if (room->isDirectChat()) {
|
||||||
return RoomType::Direct;
|
return RoomType::Direct;
|
||||||
if (room->isLowPriority())
|
}
|
||||||
|
if (room->isLowPriority()) {
|
||||||
return RoomType::Deprioritized;
|
return RoomType::Deprioritized;
|
||||||
|
}
|
||||||
return RoomType::Normal;
|
return RoomType::Normal;
|
||||||
}
|
}
|
||||||
if (role == UnreadCountRole)
|
if (role == UnreadCountRole) {
|
||||||
return room->unreadCount();
|
return room->unreadCount();
|
||||||
if (role == NotificationCountRole)
|
}
|
||||||
|
if (role == NotificationCountRole) {
|
||||||
return room->notificationCount();
|
return room->notificationCount();
|
||||||
if (role == HighlightCountRole)
|
}
|
||||||
|
if (role == HighlightCountRole) {
|
||||||
return room->highlightCount();
|
return room->highlightCount();
|
||||||
if (role == LastEventRole)
|
}
|
||||||
|
if (role == LastEventRole) {
|
||||||
return room->lastEvent();
|
return room->lastEvent();
|
||||||
if (role == LastActiveTimeRole)
|
}
|
||||||
|
if (role == LastActiveTimeRole) {
|
||||||
return room->lastActiveTime();
|
return room->lastActiveTime();
|
||||||
|
}
|
||||||
if (role == JoinStateRole) {
|
if (role == JoinStateRole) {
|
||||||
if (!room->successorId().isEmpty())
|
if (!room->successorId().isEmpty()) {
|
||||||
return QStringLiteral("upgraded");
|
return QStringLiteral("upgraded");
|
||||||
|
}
|
||||||
return toCString(room->joinState());
|
return toCString(room->joinState());
|
||||||
}
|
}
|
||||||
if (role == CurrentRoomRole)
|
if (role == CurrentRoomRole) {
|
||||||
return QVariant::fromValue(room);
|
return QVariant::fromValue(room);
|
||||||
if (role == CategoryVisibleRole)
|
}
|
||||||
|
if (role == CategoryVisibleRole) {
|
||||||
return m_categoryVisibility.value(data(index, CategoryRole).toInt(), true);
|
return m_categoryVisibility.value(data(index, CategoryRole).toInt(), true);
|
||||||
|
}
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,7 +328,7 @@ QHash<int, QByteArray> RoomListModel::roleNames() const
|
|||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString RoomListModel::categoryName(int section) const
|
QString RoomListModel::categoryName(int section)
|
||||||
{
|
{
|
||||||
switch (section) {
|
switch (section) {
|
||||||
case 1:
|
case 1:
|
||||||
|
|||||||
@@ -54,27 +54,27 @@ public:
|
|||||||
Q_ENUM(EventRoles)
|
Q_ENUM(EventRoles)
|
||||||
|
|
||||||
RoomListModel(QObject *parent = nullptr);
|
RoomListModel(QObject *parent = nullptr);
|
||||||
virtual ~RoomListModel() override;
|
~RoomListModel() override;
|
||||||
|
|
||||||
Connection *connection() const
|
[[nodiscard]] Connection *connection() const
|
||||||
{
|
{
|
||||||
return m_connection;
|
return m_connection;
|
||||||
}
|
}
|
||||||
void setConnection(Connection *connection);
|
void setConnection(Connection *connection);
|
||||||
void doResetModel();
|
void doResetModel();
|
||||||
|
|
||||||
Q_INVOKABLE NeoChatRoom *roomAt(int row) const;
|
Q_INVOKABLE [[nodiscard]] NeoChatRoom *roomAt(int row) const;
|
||||||
|
|
||||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
[[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
Q_INVOKABLE int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
Q_INVOKABLE [[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
Q_INVOKABLE QString categoryName(int category) const;
|
Q_INVOKABLE [[nodiscard]] static QString categoryName(int section);
|
||||||
Q_INVOKABLE void setCategoryVisible(int category, bool visible);
|
Q_INVOKABLE void setCategoryVisible(int category, bool visible);
|
||||||
Q_INVOKABLE bool categoryVisible(int category) const;
|
Q_INVOKABLE [[nodiscard]] bool categoryVisible(int category) const;
|
||||||
|
|
||||||
int notificationCount() const
|
[[nodiscard]] int notificationCount() const
|
||||||
{
|
{
|
||||||
return m_notificationCount;
|
return m_notificationCount;
|
||||||
}
|
}
|
||||||
@@ -100,9 +100,9 @@ Q_SIGNALS:
|
|||||||
void connectionChanged();
|
void connectionChanged();
|
||||||
void notificationCountChanged();
|
void notificationCountChanged();
|
||||||
|
|
||||||
void roomAdded(NeoChatRoom *room);
|
void roomAdded(NeoChatRoom *_t1);
|
||||||
void newMessage(const QString &roomId, const QString &eventId, const QString &roomName, const QString &senderName, const QString &text, const QImage &icon);
|
void newMessage(const QString &_t1, const QString &_t2, const QString &_t3, const QString &_t4, const QString &_t5, const QImage &_t6);
|
||||||
void newHighlight(const QString &roomId, const QString &eventId, const QString &roomName, const QString &senderName, const QString &text, const QImage &icon);
|
void newHighlight(const QString &_t1, const QString &_t2, const QString &_t3, const QString &_t4, const QString &_t5, const QImage &_t6);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ROOMLISTMODEL_H
|
#endif // ROOMLISTMODEL_H
|
||||||
|
|||||||
@@ -22,10 +22,11 @@ void SortFilterRoomListModel::setRoomSortOrder(SortFilterRoomListModel::RoomSort
|
|||||||
{
|
{
|
||||||
m_sortOrder = sortOrder;
|
m_sortOrder = sortOrder;
|
||||||
Q_EMIT roomSortOrderChanged();
|
Q_EMIT roomSortOrderChanged();
|
||||||
if (sortOrder == SortFilterRoomListModel::Alphabetical)
|
if (sortOrder == SortFilterRoomListModel::Alphabetical) {
|
||||||
setSortRole(RoomListModel::NameRole);
|
setSortRole(RoomListModel::NameRole);
|
||||||
else if (sortOrder == SortFilterRoomListModel::LastActivity)
|
} else if (sortOrder == SortFilterRoomListModel::LastActivity) {
|
||||||
setSortRole(RoomListModel::LastActiveTimeRole);
|
setSortRole(RoomListModel::LastActiveTimeRole);
|
||||||
|
}
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +44,8 @@ bool SortFilterRoomListModel::lessThan(const QModelIndex &source_left, const QMo
|
|||||||
|
|
||||||
if (categoryLeft == RoomType::Types::Favorite && categoryRight == RoomType::Types::Favorite) {
|
if (categoryLeft == RoomType::Types::Favorite && categoryRight == RoomType::Types::Favorite) {
|
||||||
return sourceModel()->data(source_left, RoomListModel::LastActiveTimeRole).toDateTime() > sourceModel()->data(source_right, RoomListModel::LastActiveTimeRole).toDateTime();
|
return sourceModel()->data(source_left, RoomListModel::LastActiveTimeRole).toDateTime() > sourceModel()->data(source_right, RoomListModel::LastActiveTimeRole).toDateTime();
|
||||||
} else if (categoryLeft == RoomType::Types::Favorite) {
|
}
|
||||||
|
if (categoryLeft == RoomType::Types::Favorite) {
|
||||||
return true;
|
return true;
|
||||||
} else if (categoryRight == RoomType::Types::Favorite) {
|
} else if (categoryRight == RoomType::Types::Favorite) {
|
||||||
return false;
|
return false;
|
||||||
@@ -51,10 +53,12 @@ bool SortFilterRoomListModel::lessThan(const QModelIndex &source_left, const QMo
|
|||||||
|
|
||||||
return sourceModel()->data(source_left, RoomListModel::LastActiveTimeRole).toDateTime() > sourceModel()->data(source_right, RoomListModel::LastActiveTimeRole).toDateTime();
|
return sourceModel()->data(source_left, RoomListModel::LastActiveTimeRole).toDateTime() > sourceModel()->data(source_right, RoomListModel::LastActiveTimeRole).toDateTime();
|
||||||
}
|
}
|
||||||
if (m_sortOrder != SortFilterRoomListModel::Categories)
|
if (m_sortOrder != SortFilterRoomListModel::Categories) {
|
||||||
return QSortFilterProxyModel::lessThan(source_left, source_right);
|
return QSortFilterProxyModel::lessThan(source_left, source_right);
|
||||||
if (sourceModel()->data(source_left, RoomListModel::CategoryRole) != sourceModel()->data(source_right, RoomListModel::CategoryRole))
|
}
|
||||||
|
if (sourceModel()->data(source_left, RoomListModel::CategoryRole) != sourceModel()->data(source_right, RoomListModel::CategoryRole)) {
|
||||||
return sourceModel()->data(source_left, RoomListModel::CategoryRole).toInt() < sourceModel()->data(source_right, RoomListModel::CategoryRole).toInt();
|
return sourceModel()->data(source_left, RoomListModel::CategoryRole).toInt() < sourceModel()->data(source_right, RoomListModel::CategoryRole).toInt();
|
||||||
|
}
|
||||||
return sourceModel()->data(source_left, RoomListModel::LastActiveTimeRole).toDateTime() > sourceModel()->data(source_right, RoomListModel::LastActiveTimeRole).toDateTime();
|
return sourceModel()->data(source_left, RoomListModel::LastActiveTimeRole).toDateTime() > sourceModel()->data(source_right, RoomListModel::LastActiveTimeRole).toDateTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,15 +26,15 @@ public:
|
|||||||
SortFilterRoomListModel(QObject *parent = nullptr);
|
SortFilterRoomListModel(QObject *parent = nullptr);
|
||||||
|
|
||||||
void setRoomSortOrder(RoomSortOrder sortOrder);
|
void setRoomSortOrder(RoomSortOrder sortOrder);
|
||||||
RoomSortOrder roomSortOrder() const;
|
[[nodiscard]] RoomSortOrder roomSortOrder() const;
|
||||||
|
|
||||||
void setFilterText(const QString &text);
|
void setFilterText(const QString &text);
|
||||||
QString filterText() const;
|
[[nodiscard]] QString filterText() const;
|
||||||
|
|
||||||
bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override;
|
[[nodiscard]] bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
|
[[nodiscard]] bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void roomSortOrderChanged();
|
void roomSortOrderChanged();
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ TrayIcon::TrayIcon(QObject *parent)
|
|||||||
auto viewAction_ = new QAction(i18n("Show"), parent);
|
auto viewAction_ = new QAction(i18n("Show"), parent);
|
||||||
|
|
||||||
connect(viewAction_, &QAction::triggered, this, &TrayIcon::showWindow);
|
connect(viewAction_, &QAction::triggered, this, &TrayIcon::showWindow);
|
||||||
connect(this, &KStatusNotifierItem::activateRequested, this, [this] (bool active) {
|
connect(this, &KStatusNotifierItem::activateRequested, this, [this](bool active) {
|
||||||
if (active) {
|
if (active) {
|
||||||
Q_EMIT showWindow();
|
Q_EMIT showWindow();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,12 +8,12 @@
|
|||||||
|
|
||||||
// Modified from mujx/nheko's TrayIcon.
|
// Modified from mujx/nheko's TrayIcon.
|
||||||
|
|
||||||
|
#include <KStatusNotifierItem>
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
#include <QIconEngine>
|
#include <QIconEngine>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QRect>
|
#include <QRect>
|
||||||
#include <KStatusNotifierItem>
|
|
||||||
|
|
||||||
class TrayIcon : public KStatusNotifierItem
|
class TrayIcon : public KStatusNotifierItem
|
||||||
{
|
{
|
||||||
@@ -29,7 +29,7 @@ public:
|
|||||||
}
|
}
|
||||||
void setIconSource(const QString &source);
|
void setIconSource(const QString &source);
|
||||||
|
|
||||||
bool isOnline()
|
bool isOnline() const
|
||||||
{
|
{
|
||||||
return m_isOnline;
|
return m_isOnline;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,8 +12,9 @@ UserDirectoryListModel::UserDirectoryListModel(QObject *parent)
|
|||||||
|
|
||||||
void UserDirectoryListModel::setConnection(Connection *conn)
|
void UserDirectoryListModel::setConnection(Connection *conn)
|
||||||
{
|
{
|
||||||
if (m_connection == conn)
|
if (m_connection == conn) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
|
|
||||||
@@ -40,8 +41,9 @@ void UserDirectoryListModel::setConnection(Connection *conn)
|
|||||||
|
|
||||||
void UserDirectoryListModel::setKeyword(const QString &value)
|
void UserDirectoryListModel::setKeyword(const QString &value)
|
||||||
{
|
{
|
||||||
if (m_keyword == value)
|
if (m_keyword == value) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_keyword = value;
|
m_keyword = value;
|
||||||
|
|
||||||
@@ -59,8 +61,9 @@ void UserDirectoryListModel::setKeyword(const QString &value)
|
|||||||
|
|
||||||
void UserDirectoryListModel::search(int count)
|
void UserDirectoryListModel::search(int count)
|
||||||
{
|
{
|
||||||
if (count < 1)
|
if (count < 1) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (job) {
|
if (job) {
|
||||||
qDebug() << "UserDirectoryListModel: Other jobs running, ignore";
|
qDebug() << "UserDirectoryListModel: Other jobs running, ignore";
|
||||||
@@ -68,8 +71,9 @@ void UserDirectoryListModel::search(int count)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attempted)
|
if (attempted) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
job = m_connection->callApi<SearchUserDirectoryJob>(m_keyword, count);
|
job = m_connection->callApi<SearchUserDirectoryJob>(m_keyword, count);
|
||||||
|
|
||||||
@@ -95,8 +99,9 @@ void UserDirectoryListModel::search(int count)
|
|||||||
|
|
||||||
QVariant UserDirectoryListModel::data(const QModelIndex &index, int role) const
|
QVariant UserDirectoryListModel::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
if (!index.isValid())
|
if (!index.isValid()) {
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
if (index.row() >= users.count()) {
|
if (index.row() >= users.count()) {
|
||||||
qDebug() << "UserDirectoryListModel, something's wrong: index.row() >= "
|
qDebug() << "UserDirectoryListModel, something's wrong: index.row() >= "
|
||||||
@@ -130,8 +135,9 @@ QVariant UserDirectoryListModel::data(const QModelIndex &index, int role) const
|
|||||||
return user.userId;
|
return user.userId;
|
||||||
}
|
}
|
||||||
if (role == DirectChatsRole) {
|
if (role == DirectChatsRole) {
|
||||||
if (!m_connection)
|
if (!m_connection) {
|
||||||
return {};
|
return {};
|
||||||
|
};
|
||||||
|
|
||||||
auto userObj = m_connection->user(user.userId);
|
auto userObj = m_connection->user(user.userId);
|
||||||
auto directChats = m_connection->directChats();
|
auto directChats = m_connection->directChats();
|
||||||
@@ -161,8 +167,9 @@ QHash<int, QByteArray> UserDirectoryListModel::roleNames() const
|
|||||||
|
|
||||||
int UserDirectoryListModel::rowCount(const QModelIndex &parent) const
|
int UserDirectoryListModel::rowCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
if (parent.isValid())
|
if (parent.isValid()) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return users.count();
|
return users.count();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,24 +31,24 @@ public:
|
|||||||
|
|
||||||
UserDirectoryListModel(QObject *parent = nullptr);
|
UserDirectoryListModel(QObject *parent = nullptr);
|
||||||
|
|
||||||
QVariant data(const QModelIndex &index, int role = NameRole) const override;
|
[[nodiscard]] QVariant data(const QModelIndex &index, int role = NameRole) const override;
|
||||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
[[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
Connection *connection() const
|
[[nodiscard]] Connection *connection() const
|
||||||
{
|
{
|
||||||
return m_connection;
|
return m_connection;
|
||||||
}
|
}
|
||||||
void setConnection(Connection *value);
|
void setConnection(Connection *conn);
|
||||||
|
|
||||||
QString keyword() const
|
[[nodiscard]] QString keyword() const
|
||||||
{
|
{
|
||||||
return m_keyword;
|
return m_keyword;
|
||||||
}
|
}
|
||||||
void setKeyword(const QString &value);
|
void setKeyword(const QString &value);
|
||||||
|
|
||||||
bool limited() const
|
[[nodiscard]] bool limited() const
|
||||||
{
|
{
|
||||||
return m_limited;
|
return m_limited;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,16 +25,18 @@ UserListModel::UserListModel(QObject *parent)
|
|||||||
|
|
||||||
void UserListModel::setRoom(Quotient::Room *room)
|
void UserListModel::setRoom(Quotient::Room *room)
|
||||||
{
|
{
|
||||||
if (m_currentRoom == room)
|
if (m_currentRoom == room) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
using namespace Quotient;
|
using namespace Quotient;
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
if (m_currentRoom) {
|
if (m_currentRoom) {
|
||||||
m_currentRoom->disconnect(this);
|
m_currentRoom->disconnect(this);
|
||||||
// m_currentRoom->connection()->disconnect(this);
|
// m_currentRoom->connection()->disconnect(this);
|
||||||
for (User *user : qAsConst(m_users))
|
for (User *user : qAsConst(m_users)) {
|
||||||
user->disconnect(this);
|
user->disconnect(this);
|
||||||
|
}
|
||||||
m_users.clear();
|
m_users.clear();
|
||||||
}
|
}
|
||||||
m_currentRoom = room;
|
m_currentRoom = room;
|
||||||
@@ -61,15 +63,17 @@ void UserListModel::setRoom(Quotient::Room *room)
|
|||||||
|
|
||||||
Quotient::User *UserListModel::userAt(QModelIndex index) const
|
Quotient::User *UserListModel::userAt(QModelIndex index) const
|
||||||
{
|
{
|
||||||
if (index.row() < 0 || index.row() >= m_users.size())
|
if (index.row() < 0 || index.row() >= m_users.size()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
}
|
||||||
return m_users.at(index.row());
|
return m_users.at(index.row());
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant UserListModel::data(const QModelIndex &index, int role) const
|
QVariant UserListModel::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
if (!index.isValid())
|
if (!index.isValid()) {
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
if (index.row() >= m_users.count()) {
|
if (index.row() >= m_users.count()) {
|
||||||
qDebug() << "UserListModel, something's wrong: index.row() >= m_users.count()";
|
qDebug() << "UserListModel, something's wrong: index.row() >= m_users.count()";
|
||||||
@@ -132,8 +136,9 @@ QVariant UserListModel::data(const QModelIndex &index, int role) const
|
|||||||
|
|
||||||
int UserListModel::rowCount(const QModelIndex &parent) const
|
int UserListModel::rowCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
if (parent.isValid())
|
if (parent.isValid()) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return m_users.count();
|
return m_users.count();
|
||||||
}
|
}
|
||||||
@@ -155,23 +160,26 @@ void UserListModel::userRemoved(Quotient::User *user)
|
|||||||
m_users.removeAt(pos);
|
m_users.removeAt(pos);
|
||||||
endRemoveRows();
|
endRemoveRows();
|
||||||
user->disconnect(this);
|
user->disconnect(this);
|
||||||
} else
|
} else {
|
||||||
qWarning() << "Trying to remove a room member not in the user list";
|
qWarning() << "Trying to remove a room member not in the user list";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserListModel::refresh(Quotient::User *user, QVector<int> roles)
|
void UserListModel::refresh(Quotient::User *user, const QVector<int> &roles)
|
||||||
{
|
{
|
||||||
auto pos = findUserPos(user);
|
auto pos = findUserPos(user);
|
||||||
if (pos != m_users.size())
|
if (pos != m_users.size()) {
|
||||||
Q_EMIT dataChanged(index(pos), index(pos), roles);
|
Q_EMIT dataChanged(index(pos), index(pos), roles);
|
||||||
else
|
} else {
|
||||||
qWarning() << "Trying to access a room member not in the user list";
|
qWarning() << "Trying to access a room member not in the user list";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserListModel::avatarChanged(Quotient::User *user, const Quotient::Room *context)
|
void UserListModel::avatarChanged(Quotient::User *user, const Quotient::Room *context)
|
||||||
{
|
{
|
||||||
if(context == m_currentRoom)
|
if (context == m_currentRoom) {
|
||||||
refresh(user, {AvatarRole});
|
refresh(user, {AvatarRole});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int UserListModel::findUserPos(User *user) const
|
int UserListModel::findUserPos(User *user) const
|
||||||
|
|||||||
@@ -48,17 +48,17 @@ public:
|
|||||||
|
|
||||||
UserListModel(QObject *parent = nullptr);
|
UserListModel(QObject *parent = nullptr);
|
||||||
|
|
||||||
Quotient::Room *room() const
|
[[nodiscard]] Quotient::Room *room() const
|
||||||
{
|
{
|
||||||
return m_currentRoom;
|
return m_currentRoom;
|
||||||
}
|
}
|
||||||
void setRoom(Quotient::Room *room);
|
void setRoom(Quotient::Room *room);
|
||||||
Quotient::User *userAt(QModelIndex index) const;
|
[[nodiscard]] Quotient::User *userAt(QModelIndex index) const;
|
||||||
|
|
||||||
QVariant data(const QModelIndex &index, int role = NameRole) const override;
|
[[nodiscard]] QVariant data(const QModelIndex &index, int role = NameRole) const override;
|
||||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
[[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void roomChanged();
|
void roomChanged();
|
||||||
@@ -66,7 +66,7 @@ Q_SIGNALS:
|
|||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void userAdded(Quotient::User *user);
|
void userAdded(Quotient::User *user);
|
||||||
void userRemoved(Quotient::User *user);
|
void userRemoved(Quotient::User *user);
|
||||||
void refresh(Quotient::User *user, QVector<int> roles = {});
|
void refresh(Quotient::User *user, const QVector<int> &roles = {});
|
||||||
void avatarChanged(Quotient::User *user, const Quotient::Room *context);
|
void avatarChanged(Quotient::User *user, const Quotient::Room *context);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -74,7 +74,7 @@ private:
|
|||||||
QList<Quotient::User *> m_users;
|
QList<Quotient::User *> m_users;
|
||||||
|
|
||||||
int findUserPos(Quotient::User *user) const;
|
int findUserPos(Quotient::User *user) const;
|
||||||
int findUserPos(const QString &username) const;
|
[[nodiscard]] int findUserPos(const QString &username) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // USERLISTMODEL_H
|
#endif // USERLISTMODEL_H
|
||||||
|
|||||||
Reference in New Issue
Block a user