From 50190f3eac1c013864d3b9ae9980aa07ae92f0db Mon Sep 17 00:00:00 2001 From: blue Date: Wed, 28 Apr 2021 23:26:19 +0300 Subject: [PATCH] handled a case when user removes downloaded file, minor optimizations on message changing --- core/account.cpp | 3 ++ core/account.h | 1 + core/handlers/messagehandler.cpp | 15 +++++++ core/handlers/messagehandler.h | 1 + core/networkaccess.cpp | 5 +++ core/networkaccess.h | 1 + core/squawk.cpp | 17 ++++++++ core/squawk.h | 1 + core/urlstorage.cpp | 1 + main.cpp | 1 + shared/message.cpp | 27 +++++++----- ui/models/element.cpp | 1 + ui/models/element.h | 1 + ui/models/messagefeed.cpp | 75 ++++++++++++++++++++------------ ui/models/messagefeed.h | 2 + ui/models/roster.cpp | 2 + ui/models/roster.h | 1 + ui/squawk.cpp | 1 + ui/squawk.h | 1 + ui/utils/feedview.cpp | 11 +++++ ui/utils/feedview.h | 1 + ui/utils/messagedelegate.cpp | 6 ++- ui/utils/messagedelegate.h | 1 + 23 files changed, 136 insertions(+), 40 deletions(-) diff --git a/core/account.cpp b/core/account.cpp index da7f25c..5ce29ee 100644 --- a/core/account.cpp +++ b/core/account.cpp @@ -920,3 +920,6 @@ void Core::Account::onContactHistoryResponse(const std::list& l } emit responseArchive(contact->jid, list, last); } + +void Core::Account::requestChangeMessage(const QString& jid, const QString& messageId, const QMap& data){ + mh->requestChangeMessage(jid, messageId, data);} diff --git a/core/account.h b/core/account.h index 8b0839b..ce3b754 100644 --- a/core/account.h +++ b/core/account.h @@ -96,6 +96,7 @@ public: void addContactToGroupRequest(const QString& jid, const QString& groupName); void removeContactFromGroupRequest(const QString& jid, const QString& groupName); void renameContactRequest(const QString& jid, const QString& newName); + void requestChangeMessage(const QString& jid, const QString& messageId, const QMap& data); void setRoomJoined(const QString& jid, bool joined); void setRoomAutoJoin(const QString& jid, bool joined); diff --git a/core/handlers/messagehandler.cpp b/core/handlers/messagehandler.cpp index 171a424..0bb84be 100644 --- a/core/handlers/messagehandler.cpp +++ b/core/handlers/messagehandler.cpp @@ -429,3 +429,18 @@ void Core::MessageHandler::sendMessageWithLocalUploadedFile(Shared::Message msg, performSending(msg); //TODO removal/progress update } + +void Core::MessageHandler::requestChangeMessage(const QString& jid, const QString& messageId, const QMap& data) +{ + RosterItem* cnt = acc->rh->getRosterItem(jid); + if (cnt != 0) { + QMap::const_iterator itr = data.find("attachPath"); + if (data.size() == 1 && itr != data.end()) { + cnt->changeMessage(messageId, data); + emit acc->changeMessage(jid, messageId, data); + } else { + qDebug() << "A request to change message" << messageId << "of conversation" << jid << "with following data" << data; + qDebug() << "nothing but the changing of the local path is supported yet in this method, skipping"; + } + } +} diff --git a/core/handlers/messagehandler.h b/core/handlers/messagehandler.h index 8893921..28fc783 100644 --- a/core/handlers/messagehandler.h +++ b/core/handlers/messagehandler.h @@ -58,6 +58,7 @@ public slots: void onDownloadFileComplete(const std::list& msgs, const QString& path); void onUploadFileComplete(const std::list& msgs, const QString& path); void onLoadFileError(const std::list& msgs, const QString& path, bool up); + void requestChangeMessage(const QString& jid, const QString& messageId, const QMap& data); private: bool handleChatMessage(const QXmppMessage& msg, bool outgoing = false, bool forwarded = false, bool guessing = false); diff --git a/core/networkaccess.cpp b/core/networkaccess.cpp index d771dc6..eece379 100644 --- a/core/networkaccess.cpp +++ b/core/networkaccess.cpp @@ -493,3 +493,8 @@ QString Core::NetworkAccess::addMessageAndCheckForPath(const QString& url, const { return storage.addMessageAndCheckForPath(url, account, jid, id); } + +std::list Core::NetworkAccess::reportPathInvalid(const QString& path) +{ + return storage.deletedFile(path); +} diff --git a/core/networkaccess.h b/core/networkaccess.h index a116e6d..5b9eae2 100644 --- a/core/networkaccess.h +++ b/core/networkaccess.h @@ -53,6 +53,7 @@ public: QString addMessageAndCheckForPath(const QString& url, const QString& account, const QString& jid, const QString& id); void uploadFile(const Shared::MessageInfo& info, const QString& path, const QUrl& put, const QUrl& get, const QMap headers); bool checkAndAddToUploading(const QString& acc, const QString& jid, const QString id, const QString path); + std::list reportPathInvalid(const QString& path); signals: void loadFileProgress(const std::list& msgs, qreal value, bool up); diff --git a/core/squawk.cpp b/core/squawk.cpp index 83fedb6..411d4ab 100644 --- a/core/squawk.cpp +++ b/core/squawk.cpp @@ -751,3 +751,20 @@ void Core::Squawk::onAccountUploadFileError(const QString& jid, const QString id Account* acc = static_cast(sender()); emit fileError({{acc->getName(), jid, id}}, errorText, true); } + +void Core::Squawk::onLocalPathInvalid(const QString& path) +{ + std::list list = network.reportPathInvalid(path); + + QMap data({ + {"attachPath", ""} + }); + for (const Shared::MessageInfo& info : list) { + AccountsMap::const_iterator itr = amap.find(info.account); + if (itr != amap.end()) { + itr->second->requestChangeMessage(info.jid, info.messageId, data); + } else { + qDebug() << "Reacting on failure to reach file" << path << "there was an attempt to change message in account" << info.account << "which doesn't exist, skipping"; + } + } +} diff --git a/core/squawk.h b/core/squawk.h index 36301d8..25fdbda 100644 --- a/core/squawk.h +++ b/core/squawk.h @@ -121,6 +121,7 @@ public slots: void requestVCard(const QString& account, const QString& jid); void uploadVCard(const QString& account, const Shared::VCard& card); void responsePassword(const QString& account, const QString& password); + void onLocalPathInvalid(const QString& path); private: typedef std::deque Accounts; diff --git a/core/urlstorage.cpp b/core/urlstorage.cpp index 1ce7957..f59ff62 100644 --- a/core/urlstorage.cpp +++ b/core/urlstorage.cpp @@ -348,6 +348,7 @@ std::list Core::UrlStorage::deletedFile(const QString& path url = QString(surl.c_str()); } else if (rc == MDB_NOTFOUND) { qDebug() << "Have been asked to remove file" << path << ", which isn't in the database, skipping"; + mdb_txn_abort(txn); return list; } else { throw Archive::Unknown(name.toStdString(), mdb_strerror(rc)); diff --git a/main.cpp b/main.cpp index 45232cf..210dd70 100644 --- a/main.cpp +++ b/main.cpp @@ -116,6 +116,7 @@ int main(int argc, char *argv[]) QObject::connect(&w, &Squawk::requestVCard, squawk, &Core::Squawk::requestVCard); QObject::connect(&w, &Squawk::uploadVCard, squawk, &Core::Squawk::uploadVCard); QObject::connect(&w, &Squawk::responsePassword, squawk, &Core::Squawk::responsePassword); + QObject::connect(&w, &Squawk::localPathInvalid, squawk, &Core::Squawk::onLocalPathInvalid); QObject::connect(squawk, &Core::Squawk::newAccount, &w, &Squawk::newAccount); QObject::connect(squawk, &Core::Squawk::addContact, &w, &Squawk::addContact); diff --git a/shared/message.cpp b/shared/message.cpp index 6728bbe..e63b7d2 100644 --- a/shared/message.cpp +++ b/shared/message.cpp @@ -394,18 +394,21 @@ bool Shared::Message::change(const QMap& data) itr = data.find("body"); if (itr != data.end()) { - QMap::const_iterator dItr = data.find("stamp"); - QDateTime correctionDate; - if (dItr != data.end()) { - correctionDate = dItr.value().toDateTime(); - } else { - correctionDate = QDateTime::currentDateTimeUtc(); //in case there is no information about time of this correction it's applied - } - if (!edited || lastModified < correctionDate) { - originalMessage = body; - lastModified = correctionDate; - setBody(itr.value().toString()); - setEdited(true); + QString b = itr.value().toString(); + if (body != b) { + QMap::const_iterator dItr = data.find("stamp"); + QDateTime correctionDate; + if (dItr != data.end()) { + correctionDate = dItr.value().toDateTime(); + } else { + correctionDate = QDateTime::currentDateTimeUtc(); //in case there is no information about time of this correction it's applied + } + if (!edited || lastModified < correctionDate) { + originalMessage = body; + lastModified = correctionDate; + setBody(body); + setEdited(true); + } } } diff --git a/ui/models/element.cpp b/ui/models/element.cpp index 4bdc3d7..4e741a4 100644 --- a/ui/models/element.cpp +++ b/ui/models/element.cpp @@ -33,6 +33,7 @@ Models::Element::Element(Type p_type, const Models::Account* acc, const QString& connect(feed, &MessageFeed::fileDownloadRequest, this, &Element::fileDownloadRequest); connect(feed, &MessageFeed::unreadMessagesCountChanged, this, &Element::onFeedUnreadMessagesCountChanged); connect(feed, &MessageFeed::unnoticedMessage, this, &Element::onFeedUnnoticedMessage); + connect(feed, &MessageFeed::localPathInvalid, this, &Element::localPathInvalid); QMap::const_iterator itr = data.find("avatarState"); if (itr != data.end()) { diff --git a/ui/models/element.h b/ui/models/element.h index 1818405..af44791 100644 --- a/ui/models/element.h +++ b/ui/models/element.h @@ -51,6 +51,7 @@ signals: void requestArchive(const QString& before); void fileDownloadRequest(const QString& url); void unnoticedMessage(const QString& account, const Shared::Message& msg); + void localPathInvalid(const QString& path); protected: void setJid(const QString& p_jid); diff --git a/ui/models/messagefeed.cpp b/ui/models/messagefeed.cpp index 07dfe0a..d1024b8 100644 --- a/ui/models/messagefeed.cpp +++ b/ui/models/messagefeed.cpp @@ -116,37 +116,39 @@ void Models::MessageFeed::changeMessage(const QString& id, const QMap 0 || changeRoles.count(MessageRoles::Error); - if (dItr != downloads.end()) { - if (attachOrError) { - downloads.erase(dItr); - } else if (changeRoles.count(MessageRoles::Id) > 0) { - qreal progress = dItr->second; - downloads.erase(dItr); - downloads.insert(std::make_pair(msg->getId(), progress)); - } - } else { - dItr = uploads.find(id); - if (dItr != uploads.end()) { + if (changeRoles.size() > 0) { + //change message is a final event in download/upload event train + //only after changeMessage we can consider the download is done + Progress::const_iterator dItr = downloads.find(id); + bool attachOrError = changeRoles.count(MessageRoles::Attach) > 0 || changeRoles.count(MessageRoles::Error); + if (dItr != downloads.end()) { if (attachOrError) { - uploads.erase(dItr); + downloads.erase(dItr); } else if (changeRoles.count(MessageRoles::Id) > 0) { qreal progress = dItr->second; - uploads.erase(dItr); - uploads.insert(std::make_pair(msg->getId(), progress)); + downloads.erase(dItr); + downloads.insert(std::make_pair(msg->getId(), progress)); + } + } else { + dItr = uploads.find(id); + if (dItr != uploads.end()) { + if (attachOrError) { + uploads.erase(dItr); + } else if (changeRoles.count(MessageRoles::Id) > 0) { + qreal progress = dItr->second; + uploads.erase(dItr); + uploads.insert(std::make_pair(msg->getId(), progress)); + } } } + + QVector cr; + for (MessageRoles role : changeRoles) { + cr.push_back(role); + } + + emit dataChanged(index, index, cr); } - - QVector cr; - for (MessageRoles role : changeRoles) { - cr.push_back(role); - } - - emit dataChanged(index, index, cr); } std::set Models::MessageFeed::detectChanges(const Shared::Message& msg, const QMap& data) const @@ -174,13 +176,13 @@ std::set Models::MessageFeed::detectChanges(c if (state == Shared::Message::State::error) { itr = data.find("errorText"); - if (itr != data.end()) { + if (itr != data.end() && itr.value().toString() != msg.getErrorText()) { roles.insert(MessageRoles::Error); } } itr = data.find("body"); - if (itr != data.end()) { + if (itr != data.end() && itr.value().toString() != msg.getBody()) { QMap::const_iterator dItr = data.find("stamp"); QDateTime correctionDate; if (dItr != data.end()) { @@ -522,3 +524,22 @@ QModelIndex Models::MessageFeed::modelIndexByTime(const QString& id, const QDate return QModelIndex(); } + +void Models::MessageFeed::reportLocalPathInvalid(const QString& messageId) +{ + StorageById::iterator itr = indexById.find(messageId); + if (itr == indexById.end()) { + qDebug() << "received a command to change a message, but the message couldn't be found, skipping"; + return; + } + + Shared::Message* msg = *itr; + + emit localPathInvalid(msg->getAttachPath()); + + //gonna change the message in current model right away, to prevent spam on each attemt to draw element + QModelIndex index = modelIndexByTime(messageId, msg->getTime()); + msg->setAttachPath(""); + + emit dataChanged(index, index, {MessageRoles::Attach}); +} diff --git a/ui/models/messagefeed.h b/ui/models/messagefeed.h index 1b7bc43..5c5c019 100644 --- a/ui/models/messagefeed.h +++ b/ui/models/messagefeed.h @@ -60,6 +60,7 @@ public: void downloadAttachment(const QString& messageId); void uploadAttachment(const QString& messageId); bool registerUpload(const QString& messageId); + void reportLocalPathInvalid(const QString& messageId); unsigned int unreadMessagesCount() const; void fileProgress(const QString& messageId, qreal value, bool up); @@ -76,6 +77,7 @@ signals: void unreadMessagesCountChanged(); void newMessage(const Shared::Message& msg); void unnoticedMessage(const Shared::Message& msg); + void localPathInvalid(const QString& path); public: enum MessageRoles { diff --git a/ui/models/roster.cpp b/ui/models/roster.cpp index eb02942..d70d9d1 100644 --- a/ui/models/roster.cpp +++ b/ui/models/roster.cpp @@ -449,6 +449,7 @@ void Models::Roster::addContact(const QString& account, const QString& jid, cons connect(contact, &Contact::requestArchive, this, &Roster::onElementRequestArchive); connect(contact, &Contact::fileDownloadRequest, this, &Roster::fileDownloadRequest); connect(contact, &Contact::unnoticedMessage, this, &Roster::unnoticedMessage); + connect(contact, &Contact::localPathInvalid, this, &Roster::localPathInvalid); contacts.insert(std::make_pair(id, contact)); } else { contact = itr->second; @@ -787,6 +788,7 @@ void Models::Roster::addRoom(const QString& account, const QString jid, const QM connect(room, &Contact::requestArchive, this, &Roster::onElementRequestArchive); connect(room, &Contact::fileDownloadRequest, this, &Roster::fileDownloadRequest); connect(room, &Contact::unnoticedMessage, this, &Roster::unnoticedMessage); + connect(room, &Contact::localPathInvalid, this, &Roster::localPathInvalid); rooms.insert(std::make_pair(id, room)); acc->appendChild(room); } diff --git a/ui/models/roster.h b/ui/models/roster.h index 10da0fb..09261cd 100644 --- a/ui/models/roster.h +++ b/ui/models/roster.h @@ -93,6 +93,7 @@ signals: void requestArchive(const QString& account, const QString& jid, const QString& before); void fileDownloadRequest(const QString& url); void unnoticedMessage(const QString& account, const Shared::Message& msg); + void localPathInvalid(const QString& path); private: Element* getElement(const ElId& id); diff --git a/ui/squawk.cpp b/ui/squawk.cpp index d7085aa..fb79592 100644 --- a/ui/squawk.cpp +++ b/ui/squawk.cpp @@ -64,6 +64,7 @@ Squawk::Squawk(QWidget *parent) : connect(rosterModel.accountsModel, &Models::Accounts::sizeChanged, this, &Squawk::onAccountsSizeChanged); connect(&rosterModel, &Models::Roster::requestArchive, this, &Squawk::onRequestArchive); connect(&rosterModel, &Models::Roster::fileDownloadRequest, this, &Squawk::fileDownloadRequest); + connect(&rosterModel, &Models::Roster::localPathInvalid, this, &Squawk::localPathInvalid); connect(contextMenu, &QMenu::aboutToHide, this, &Squawk::onContextAboutToHide); //m_ui->mainToolBar->addWidget(m_ui->comboBox); diff --git a/ui/squawk.h b/ui/squawk.h index cda7c8c..fa92df7 100644 --- a/ui/squawk.h +++ b/ui/squawk.h @@ -79,6 +79,7 @@ signals: void requestVCard(const QString& account, const QString& jid); void uploadVCard(const QString& account, const Shared::VCard& card); void responsePassword(const QString& account, const QString& password); + void localPathInvalid(const QString& path); public slots: void readSettings(); diff --git a/ui/utils/feedview.cpp b/ui/utils/feedview.cpp index 550b8d4..05302b0 100644 --- a/ui/utils/feedview.cpp +++ b/ui/utils/feedview.cpp @@ -304,6 +304,7 @@ void FeedView::setItemDelegate(QAbstractItemDelegate* delegate) if (specialDelegate) { MessageDelegate* del = static_cast(itemDelegate()); disconnect(del, &MessageDelegate::buttonPushed, this, &FeedView::onMessageButtonPushed); + disconnect(del, &MessageDelegate::invalidPath, this, &FeedView::onMessageInvalidPath); } QAbstractItemView::setItemDelegate(delegate); @@ -312,6 +313,7 @@ void FeedView::setItemDelegate(QAbstractItemDelegate* delegate) if (del) { specialDelegate = true; connect(del, &MessageDelegate::buttonPushed, this, &FeedView::onMessageButtonPushed); + connect(del, &MessageDelegate::invalidPath, this, &FeedView::onMessageInvalidPath); } else { specialDelegate = false; } @@ -341,3 +343,12 @@ void FeedView::onMessageButtonPushed(const QString& messageId, bool download) } } } + +void FeedView::onMessageInvalidPath(const QString& messageId) +{ + if (specialModel) { + Models::MessageFeed* feed = static_cast(model()); + feed->reportLocalPathInvalid(messageId); + } +} + diff --git a/ui/utils/feedview.h b/ui/utils/feedview.h index 05e3025..8361ec9 100644 --- a/ui/utils/feedview.h +++ b/ui/utils/feedview.h @@ -55,6 +55,7 @@ protected slots: void verticalScrollbarValueChanged(int value) override; void dataChanged(const QModelIndex & topLeft, const QModelIndex & bottomRight, const QVector & roles) override; void onMessageButtonPushed(const QString& messageId, bool download); + void onMessageInvalidPath(const QString& messageId); protected: int verticalOffset() const override; diff --git a/ui/utils/messagedelegate.cpp b/ui/utils/messagedelegate.cpp index 910db72..c98710c 100644 --- a/ui/utils/messagedelegate.cpp +++ b/ui/utils/messagedelegate.cpp @@ -310,7 +310,11 @@ void MessageDelegate::paintPreview(const Models::FeedItem& data, QPainter* paint start = option.rect.topLeft(); } QImage img(data.attach.localPath); - painter->drawImage(QRect(start, size), img); + if (img.isNull()) { + emit invalidPath(data.id); + } else { + painter->drawImage(QRect(start, size), img); + } option.rect.adjust(0, size.height() + textMargin, 0, 0); } diff --git a/ui/utils/messagedelegate.h b/ui/utils/messagedelegate.h index ed42e2f..97822eb 100644 --- a/ui/utils/messagedelegate.h +++ b/ui/utils/messagedelegate.h @@ -55,6 +55,7 @@ public: signals: void buttonPushed(const QString& messageId, bool download) const; + void invalidPath(const QString& messageId) const; protected: void paintButton(QPushButton* btn, QPainter* painter, bool sentByMe, QStyleOptionViewItem& option) const;