2020-08-19 10:55:13 +03:00
|
|
|
#include "chatlistmodel.h"
|
2020-08-20 01:24:24 +03:00
|
|
|
#include <QListIterator>
|
2020-08-19 10:55:13 +03:00
|
|
|
|
|
|
|
ChatListModel::ChatListModel(TDLibWrapper *tdLibWrapper)
|
|
|
|
{
|
|
|
|
this->tdLibWrapper = tdLibWrapper;
|
2020-08-20 19:45:56 +03:00
|
|
|
this->deltaUpdates = false;
|
2020-08-19 10:55:13 +03:00
|
|
|
connect(this->tdLibWrapper, SIGNAL(newChatDiscovered(QString, QVariantMap)), this, SLOT(handleChatDiscovered(QString, QVariantMap)));
|
2020-08-20 15:58:32 +03:00
|
|
|
connect(this->tdLibWrapper, SIGNAL(chatLastMessageUpdated(QString, QString, QVariantMap)), this, SLOT(handleChatLastMessageUpdated(QString, QString, QVariantMap)));
|
2020-08-20 11:50:47 +03:00
|
|
|
connect(this->tdLibWrapper, SIGNAL(chatOrderUpdated(QString, QString)), this, SLOT(handleChatOrderUpdated(QString, QString)));
|
2020-08-21 00:56:21 +03:00
|
|
|
connect(this->tdLibWrapper, SIGNAL(chatReadInboxUpdated(QString, int)), this, SLOT(handleChatReadInboxUpdated(QString, int)));
|
2020-08-19 10:55:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
ChatListModel::~ChatListModel()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
int ChatListModel::rowCount(const QModelIndex &) const
|
|
|
|
{
|
|
|
|
return chatList.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
QVariant ChatListModel::data(const QModelIndex &index, int role) const
|
|
|
|
{
|
|
|
|
if(index.isValid() && role == Qt::DisplayRole) {
|
|
|
|
return QVariant(chatList.value(index.row()));
|
|
|
|
}
|
|
|
|
return QVariant();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ChatListModel::insertRows(int row, int count, const QModelIndex &parent)
|
|
|
|
{
|
|
|
|
qDebug() << "[ChatListModel] Inserting at " << row << ", row count: " << count;
|
|
|
|
beginInsertRows(parent, rowCount(QModelIndex()), rowCount(QModelIndex()) + count - 1);
|
|
|
|
this->chatList.append(this->chatToBeAdded);
|
2020-08-20 01:24:24 +03:00
|
|
|
this->chatIndexMap.insert(this->chatToBeAdded.value("id").toString(), row);
|
2020-08-19 10:55:13 +03:00
|
|
|
endInsertRows();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-08-20 21:06:59 +03:00
|
|
|
void ChatListModel::enableDeltaUpdates()
|
2020-08-20 19:45:56 +03:00
|
|
|
{
|
2020-08-20 21:06:59 +03:00
|
|
|
qDebug() << "[ChatListModel] Enabling delta updates and enforcing UI redraw...";
|
2020-08-20 19:45:56 +03:00
|
|
|
layoutChanged();
|
|
|
|
this->deltaUpdates = true;
|
|
|
|
}
|
|
|
|
|
2020-08-20 11:50:47 +03:00
|
|
|
bool compareChats(const QVariant &chat1, const QVariant &chat2)
|
|
|
|
{
|
|
|
|
QVariantMap chatMap1 = chat1.toMap();
|
|
|
|
QVariantMap chatMap2 = chat2.toMap();
|
|
|
|
// Order comes first...
|
|
|
|
if (chatMap1.value("order").toLongLong() > chatMap2.value("order").toLongLong()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// ID comes next...
|
|
|
|
if (chatMap1.value("order").toLongLong() == chatMap2.value("order").toLongLong() && chatMap1.value("id").toLongLong() > chatMap2.value("id").toLongLong()) {
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-19 10:55:13 +03:00
|
|
|
void ChatListModel::handleChatDiscovered(const QString &chatId, const QVariantMap &chatInformation)
|
|
|
|
{
|
2020-08-20 11:50:47 +03:00
|
|
|
this->chatListMutex.lock();
|
2020-08-19 10:55:13 +03:00
|
|
|
qDebug() << "[ChatListModel] Adding new chat " << chatId;
|
|
|
|
this->chatToBeAdded = chatInformation;
|
|
|
|
insertRows(rowCount(QModelIndex()), 1);
|
2020-08-20 11:50:47 +03:00
|
|
|
this->chatListMutex.unlock();
|
2020-08-19 10:55:13 +03:00
|
|
|
}
|
2020-08-20 01:24:24 +03:00
|
|
|
|
2020-08-20 18:06:47 +03:00
|
|
|
|
|
|
|
|
2020-08-20 15:58:32 +03:00
|
|
|
void ChatListModel::handleChatLastMessageUpdated(const QString &chatId, const QString &order, const QVariantMap &lastMessage)
|
2020-08-20 01:24:24 +03:00
|
|
|
{
|
2020-08-20 11:50:47 +03:00
|
|
|
this->chatListMutex.lock();
|
2020-08-20 01:24:24 +03:00
|
|
|
int chatIndex = this->chatIndexMap.value(chatId).toInt();
|
|
|
|
qDebug() << "[ChatListModel] Updating last message for chat " << chatId << " at index " << chatIndex;
|
|
|
|
QVariantMap currentChat = this->chatList.value(chatIndex).toMap();
|
|
|
|
currentChat.insert("last_message", lastMessage);
|
2020-08-20 15:58:32 +03:00
|
|
|
currentChat.insert("order", order);
|
2020-08-20 01:24:24 +03:00
|
|
|
this->chatList.replace(chatIndex, currentChat);
|
|
|
|
emit dataChanged(this->index(chatIndex), this->index(chatIndex));
|
2020-08-20 18:06:47 +03:00
|
|
|
|
|
|
|
this->updateChatOrder(chatIndex, currentChat);
|
2020-08-21 10:29:19 +03:00
|
|
|
emit chatChanged(chatId);
|
2020-08-20 18:06:47 +03:00
|
|
|
|
2020-08-20 11:50:47 +03:00
|
|
|
this->chatListMutex.unlock();
|
2020-08-20 01:24:24 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void ChatListModel::handleChatOrderUpdated(const QString &chatId, const QString &order)
|
|
|
|
{
|
2020-08-20 11:50:47 +03:00
|
|
|
this->chatListMutex.lock();
|
|
|
|
qDebug() << "[ChatListModel] Updating chat order because of " << chatId << " new order " << order;
|
2020-08-20 18:06:47 +03:00
|
|
|
int chatIndex = this->chatIndexMap.value(chatId).toInt();
|
|
|
|
QVariantMap currentChat = this->chatList.at(chatIndex).toMap();
|
2020-08-20 11:50:47 +03:00
|
|
|
currentChat.insert("order", order);
|
2020-08-20 18:06:47 +03:00
|
|
|
this->chatList.replace(chatIndex, currentChat);
|
|
|
|
emit dataChanged(this->index(chatIndex), this->index(chatIndex));
|
|
|
|
|
|
|
|
this->updateChatOrder(chatIndex, currentChat);
|
2020-08-21 10:29:19 +03:00
|
|
|
emit chatChanged(chatId);
|
2020-08-20 18:06:47 +03:00
|
|
|
|
2020-08-20 11:50:47 +03:00
|
|
|
this->chatListMutex.unlock();
|
2020-08-20 01:24:24 +03:00
|
|
|
}
|
2020-08-20 18:06:47 +03:00
|
|
|
|
2020-08-21 00:56:21 +03:00
|
|
|
void ChatListModel::handleChatReadInboxUpdated(const QString &chatId, const int &unreadCount)
|
|
|
|
{
|
|
|
|
this->chatListMutex.lock();
|
|
|
|
qDebug() << "[ChatListModel] Updating chat unread count for " << chatId << " unread messages " << unreadCount;
|
|
|
|
int chatIndex = this->chatIndexMap.value(chatId).toInt();
|
|
|
|
QVariantMap currentChat = this->chatList.at(chatIndex).toMap();
|
|
|
|
currentChat.insert("unread_count", unreadCount);
|
|
|
|
this->chatList.replace(chatIndex, currentChat);
|
|
|
|
emit dataChanged(this->index(chatIndex), this->index(chatIndex));
|
2020-08-21 10:29:19 +03:00
|
|
|
emit chatChanged(chatId);
|
2020-08-21 00:56:21 +03:00
|
|
|
this->chatListMutex.unlock();
|
|
|
|
}
|
|
|
|
|
2020-08-20 18:06:47 +03:00
|
|
|
void ChatListModel::updateChatOrder(const int ¤tChatIndex, const QVariantMap &updatedChat)
|
|
|
|
{
|
|
|
|
// Finding the new position manually as information is needed by beginMoveRows()
|
|
|
|
// This seems to be the most convenient way of persisting the list position while changing the items
|
|
|
|
// Other alternative layoutChanged() after sorting resets the index position - there we would need to calculate the new position as well
|
|
|
|
// If somebody has a better solution - go for it ;)
|
|
|
|
int newChatIndex = 0;
|
2020-08-20 19:45:56 +03:00
|
|
|
QVariantMap previousChat;
|
2020-08-20 18:06:47 +03:00
|
|
|
for (int i = 0; i < this->chatList.length(); i++) {
|
|
|
|
QVariantMap otherChat = this->chatList.at(i).toMap();
|
|
|
|
if (compareChats(updatedChat, otherChat)) {
|
2020-08-20 19:45:56 +03:00
|
|
|
if (previousChat.value("id") == updatedChat.value("id")) {
|
|
|
|
newChatIndex = currentChatIndex;
|
|
|
|
} else {
|
|
|
|
newChatIndex = i;
|
|
|
|
}
|
2020-08-20 18:06:47 +03:00
|
|
|
break;
|
|
|
|
}
|
2020-08-20 19:45:56 +03:00
|
|
|
previousChat = otherChat;
|
2020-08-20 18:06:47 +03:00
|
|
|
}
|
|
|
|
if (newChatIndex != currentChatIndex) {
|
|
|
|
// The updated chat now needs to go to the position of the other chat
|
|
|
|
qDebug() << "[ChatListModel] Chat " << updatedChat.value("id").toString() << " will be moved from position " << currentChatIndex << " to " << newChatIndex;
|
2020-08-20 19:45:56 +03:00
|
|
|
if (deltaUpdates) {
|
|
|
|
beginMoveRows(QModelIndex(), currentChatIndex, currentChatIndex, QModelIndex(), (( newChatIndex < currentChatIndex ) ? newChatIndex : ( newChatIndex + 1 )));
|
|
|
|
}
|
2020-08-20 18:06:47 +03:00
|
|
|
std::sort(this->chatList.begin(), this->chatList.end(), compareChats);
|
|
|
|
this->chatIndexMap.clear();
|
|
|
|
for (int i = 0; i < this->chatList.length(); i++) {
|
|
|
|
this->chatIndexMap.insert(this->chatList.at(i).toMap().value("id").toString(), i);
|
|
|
|
}
|
2020-08-20 19:45:56 +03:00
|
|
|
if (deltaUpdates) {
|
|
|
|
endMoveRows();
|
|
|
|
}
|
|
|
|
|
2020-08-20 18:06:47 +03:00
|
|
|
}
|
|
|
|
}
|