diff --git a/src/api/conversationmodel.h b/src/api/conversationmodel.h index a1797bd3cc009084f23eb877619d38e8d4d3112f..67934a397520b0a1477653d104e011548b3aa6e0 100644 --- a/src/api/conversationmodel.h +++ b/src/api/conversationmodel.h @@ -289,7 +289,7 @@ public: void getTransferInfo(const QString& conversationId, const QString& interactionId, - api::datatransfer::Info& info); + api::datatransfer::Info& info) const; /** * @param convUid, uid of the conversation * @return the number of unread messages for the conversation diff --git a/src/conversationmodel.cpp b/src/conversationmodel.cpp index 105e4f98c6f60b69d874bb5df94688dc802ac0ea..2484e3a93c3b7fe92818f68140556c8ca0c873f5 100644 --- a/src/conversationmodel.cpp +++ b/src/conversationmodel.cpp @@ -194,10 +194,10 @@ public: /** * Handle data transfer progression */ - void updateTransfer(QTimer* timer, - const QString& conversation, - int conversationIdx, - const QString& interactionId); + void updateTransferProgress(QTimer* timer, + const QString& conversation, + int conversationIdx, + const QString& interactionId); bool usefulDataFromDataTransfer(const QString& fileId, const datatransfer::Info& info, @@ -1433,6 +1433,7 @@ ConversationModel::setInteractionRead(const QString& convId, const QString& inte return; } it->second.isRead = true; + interactions->emitDataChanged(it, {MessageList::Role::IsRead}); if (pimpl_->conversations[conversationIdx].unreadMessages != 0) pimpl_->conversations[conversationIdx].unreadMessages -= 1; itCopy = it->second; @@ -3130,14 +3131,16 @@ ConversationModelPimpl::addOrUpdateCallMessage(const QString& callId, auto msgId = storage::addOrUpdateMessage(db, conv_it->uid, msg, callId); // now set the formatted call message string in memory only msg.body = storage::getCallInteractionString(uriString, duration); - auto newInteraction = conv_it->interactions->find(msgId) == conv_it->interactions->end(); + auto interactionIt = conv_it->interactions->find(msgId); + auto newInteraction = interactionIt == conv_it->interactions->end(); if (newInteraction) { conv_it->lastMessageUid = msgId; std::lock_guard<std::mutex> lk(interactionsLocks[conv_it->uid]); conv_it->interactions->emplace(msgId, msg); } else { std::lock_guard<std::mutex> lk(interactionsLocks[conv_it->uid]); - (*(conv_it->interactions))[msgId] = msg; + interactionIt->second = msg; + conv_it->interactions->emitDataChanged(interactionIt); } if (newInteraction) @@ -3337,6 +3340,7 @@ ConversationModelPimpl::slotUpdateInteractionStatus(const QString& accountId, auto messageId = conversation.lastDisplayedMessageUid.find(peerId); if (it != interactions->end()) { it->second.status = newStatus; + interactions->emitDataChanged(it, {MessageList::Role::Status}); bool interactionDisplayed = newStatus == interaction::Status::DISPLAYED && isOutgoing(it->second); if (messageId != conversation.lastDisplayedMessageUid.end()) { @@ -3540,6 +3544,7 @@ ConversationModel::cancelTransfer(const QString& convUid, const QString& fileId) auto it = interactions->find(fileId); if (it != interactions->end()) { it->second.status = interaction::Status::TRANSFER_CANCELED; + interactions->emitDataChanged(it, {MessageList::Role::Status}); // update information in the db storage::updateInteractionStatus(pimpl_->db, @@ -3565,7 +3570,7 @@ ConversationModel::cancelTransfer(const QString& convUid, const QString& fileId) void ConversationModel::getTransferInfo(const QString& conversationId, const QString& interactionId, - datatransfer::Info& info) + datatransfer::Info& info) const { auto convOpt = getConversationForUid(conversationId); if (!convOpt) @@ -3818,6 +3823,8 @@ ConversationModelPimpl::acceptTransfer(const QString& convUid, if (it != interactions->end()) { it->second.body = acceptedFilePath; it->second.status = interaction::Status::TRANSFER_ACCEPTED; + using namespace MessageList; + interactions->emitDataChanged(it, {Role::Body, Role::Status}); emitUpdated = true; itCopy = it->second; } @@ -3895,7 +3902,7 @@ ConversationModelPimpl::slotTransferStatusOngoing(const QString& fileId, datatra auto conversationIdx = indexOf(conversationId); auto* timer = new QTimer(); connect(timer, &QTimer::timeout, [=] { - updateTransfer(timer, conversationId, conversationIdx, interactionId); + updateTransferProgress(timer, conversationId, conversationIdx, interactionId); }); timer->start(1000); } @@ -3925,6 +3932,7 @@ ConversationModelPimpl::slotTransferStatusFinished(const QString& fileId, datatr if (it->second.status == interaction::Status::TRANSFER_ONGOING) { emitUpdated = true; it->second.status = newStatus; + interactions->emitDataChanged(it, {MessageList::Role::Status}); itCopy = it->second; } } @@ -4010,10 +4018,14 @@ ConversationModelPimpl::updateTransferStatus(const QString& fileId, auto it = interactions->find(interactionId); if (it != interactions->end()) { emitUpdated = true; + VectorInt roles; it->second.status = newStatus; + roles += MessageList::Role::Status; if (conversation.isSwarm()) { it->second.body = info.path; + roles += MessageList::Role::Body; } + interactions->emitDataChanged(it, roles); itCopy = it->second; } } @@ -4026,20 +4038,22 @@ ConversationModelPimpl::updateTransferStatus(const QString& fileId, } void -ConversationModelPimpl::updateTransfer(QTimer* timer, - const QString& conversation, - int conversationIdx, - const QString& interactionId) +ConversationModelPimpl::updateTransferProgress(QTimer* timer, + const QString& conversation, + int conversationIdx, + const QString& interactionId) { try { bool emitUpdated = false; interaction::Info itCopy; { - std::lock_guard<std::mutex> lk(interactionsLocks[conversations[conversationIdx].uid]); + auto convId = conversations[conversationIdx].uid; + std::lock_guard<std::mutex> lk(interactionsLocks[convId]); const auto& interactions = conversations[conversationIdx].interactions; const auto& it = interactions->find(interactionId); if (it != interactions->cend() and it->second.status == interaction::Status::TRANSFER_ONGOING) { + interactions->emitDataChanged(it, {MessageList::Role::Status}); emitUpdated = true; itCopy = it->second; } diff --git a/src/messagelistmodel.cpp b/src/messagelistmodel.cpp index d120c50e450e15c2a0b1241888a04b3068076eee..4546128f5f6742a77a5e6b6bf398d3877636c1e9 100644 --- a/src/messagelistmodel.cpp +++ b/src/messagelistmodel.cpp @@ -348,6 +348,8 @@ MessageListModel::dataForItem(item_t item, int indexRow, int role) const return QVariant(item.second.linkPreviewInfo); case Role::Linkified: return QVariant(item.second.linkified); + case Role::TransferName: + return QVariant(item.second.commit["displayName"]); default: return {}; } @@ -399,4 +401,35 @@ MessageListModel::linkifyMessage(const QString& messageId, const QString& linkif Q_EMIT dataChanged(modelIndex, modelIndex, {Role::Body, Role::Linkified}); } +void +MessageListModel::emitBeginResetModel() +{ + Q_EMIT beginResetModel(); +} + +void +MessageListModel::emitEndResetModel() +{ + Q_EMIT endResetModel(); +} + +void +MessageListModel::emitDataChanged(iterator it, VectorInt roles) +{ + auto index = std::distance(begin(), it); + QModelIndex modelIndex = QAbstractListModel::index(index, 0); + Q_EMIT dataChanged(modelIndex, modelIndex, roles); +} + +void +MessageListModel::emitDataChanged(const QString& msgId, VectorInt roles) +{ + int index = getIndexOfMessage(msgId); + if (index == -1) { + return; + } + QModelIndex modelIndex = QAbstractListModel::index(index, 0); + Q_EMIT dataChanged(modelIndex, modelIndex, roles); +} + } // namespace lrc diff --git a/src/messagelistmodel.h b/src/messagelistmodel.h index 0f0d0f3c3162b9be42c2c82d08668148302ce427..79064983c16f5886e17f6a5904e0b942cd82b637 100644 --- a/src/messagelistmodel.h +++ b/src/messagelistmodel.h @@ -42,7 +42,8 @@ struct Info; X(IsRead) \ X(Commit) \ X(LinkPreviewInfo) \ - X(Linkified) + X(Linkified) \ + X(TransferName) namespace MessageList { Q_NAMESPACE @@ -106,6 +107,15 @@ public: void addHyperlinkInfo(const QString& messageId, const QVariantMap& info); void linkifyMessage(const QString& messageId, const QString& linkified); + // use these if the underlying data model is changed from conversationmodel + // Note: this is not ideal, and this class should be refactored into a proper + // view model and absorb the interaction management logic to avoid exposing + // these emission wrappers + void emitBeginResetModel(); + void emitEndResetModel(); + void emitDataChanged(iterator it, VectorInt roles = {}); + void emitDataChanged(const QString& msgId, VectorInt roles = {}); + protected: using Role = MessageList::Role;