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