diff --git a/global.cpp b/global.cpp index 223cf10..6ff87c5 100644 --- a/global.cpp +++ b/global.cpp @@ -290,6 +290,31 @@ void Shared::Message::deserialize(QDataStream& data) data >> edited; } +bool Shared::Message::change(const QMap& data) +{ + QMap::const_iterator itr = data.find("state"); + if (itr != data.end()) { + setState(static_cast(itr.value().toUInt())); + } + + bool idChanged = false; + itr = data.find("id"); + if (itr != data.end()) { + QString newId = itr.value().toString(); + if (id != newId) { + setId(newId); + idChanged = true; + } + } + itr = data.find("body"); + if (itr != data.end()) { + setBody(itr.value().toString()); + setEdited(true); + } + + return idChanged; +} + QString Shared::generateUUID() { uuid_t uuid; diff --git a/global.h b/global.h index c815149..29b7969 100644 --- a/global.h +++ b/global.h @@ -20,6 +20,7 @@ #define GLOBAL_H #include +#include #include #include #include @@ -189,6 +190,7 @@ public: void setOutOfBandUrl(const QString& url); void setState(State p_state); void setEdited(bool p_edited); + bool change(const QMap& data); QString getFrom() const; QString getFromJid() const; diff --git a/ui/models/contact.cpp b/ui/models/contact.cpp index a5390fb..de9d312 100644 --- a/ui/models/contact.cpp +++ b/ui/models/contact.cpp @@ -290,6 +290,27 @@ void Models::Contact::addMessage(const Shared::Message& data) } } +void Models::Contact::changeMessage(const QString& id, const QMap& data) +{ + + bool found = false; + for (Shared::Message& msg : messages) { + if (msg.getId() == id) { + msg.change(data); + found = true; + break; + } + } + if (!found) { + for (Presence* pr : presences) { + found = pr->changeMessage(id, data); + if (found) { + break; + } + } + } +} + unsigned int Models::Contact::getMessagesCount() const { return messages.size() + childMessages; diff --git a/ui/models/contact.h b/ui/models/contact.h index f8ac346..cffc53c 100644 --- a/ui/models/contact.h +++ b/ui/models/contact.h @@ -57,6 +57,7 @@ public: QString getStatus() const; void addMessage(const Shared::Message& data); + void changeMessage(const QString& id, const QMap& data); unsigned int getMessagesCount() const; void dropMessages(); void getMessages(Messages& container) const; diff --git a/ui/models/presence.cpp b/ui/models/presence.cpp index 36b07d2..bf2ef12 100644 --- a/ui/models/presence.cpp +++ b/ui/models/presence.cpp @@ -61,6 +61,19 @@ void Models::Presence::addMessage(const Shared::Message& data) changed(4); } +bool Models::Presence::changeMessage(const QString& id, const QMap& data) +{ + bool found = false; + for (Shared::Message& msg : messages) { + if (msg.getId() == id) { + msg.change(data); + found = true; + break; + } + } + return found; +} + void Models::Presence::dropMessages() { if (messages.size() > 0) { diff --git a/ui/models/presence.h b/ui/models/presence.h index 8371be7..5073e7a 100644 --- a/ui/models/presence.h +++ b/ui/models/presence.h @@ -43,6 +43,7 @@ public: unsigned int getMessagesCount() const; void dropMessages(); void addMessage(const Shared::Message& data); + bool changeMessage(const QString& id, const QMap& data); void getMessages(Messages& container) const; diff --git a/ui/models/room.cpp b/ui/models/room.cpp index 55e64ca..afcf8e9 100644 --- a/ui/models/room.cpp +++ b/ui/models/room.cpp @@ -236,6 +236,16 @@ void Models::Room::addMessage(const Shared::Message& data) changed(5); } +void Models::Room::changeMessage(const QString& id, const QMap& data) +{ + for (Shared::Message& msg : messages) { + if (msg.getId() == id) { + msg.change(data); + break; + } + } +} + void Models::Room::dropMessages() { if (messages.size() > 0) { diff --git a/ui/models/room.h b/ui/models/room.h index 4c3b9d9..6a87a83 100644 --- a/ui/models/room.h +++ b/ui/models/room.h @@ -59,6 +59,7 @@ public: void update(const QString& field, const QVariant& value); void addMessage(const Shared::Message& data); + void changeMessage(const QString& id, const QMap& data); unsigned int getMessagesCount() const; void dropMessages(); void getMessages(Messages& container) const; diff --git a/ui/models/roster.cpp b/ui/models/roster.cpp index 7f4cfc5..23e39af 100644 --- a/ui/models/roster.cpp +++ b/ui/models/roster.cpp @@ -549,14 +549,34 @@ void Models::Roster::changeContact(const QString& account, const QString& jid, c for (; cBeg != cEnd; ++cBeg) { for (QMap::const_iterator itr = data.begin(), end = data.end(); itr != end; ++itr) { - cBeg->second->update(itr.key(), itr.value());; + cBeg->second->update(itr.key(), itr.value()); } } std::map::iterator rItr = rooms.find(id); if (rItr != rooms.end()) { for (QMap::const_iterator itr = data.begin(), end = data.end(); itr != end; ++itr) { - rItr->second->update(itr.key(), itr.value());; + rItr->second->update(itr.key(), itr.value()); + } + } +} + +void Models::Roster::changeMessage(const QString& account, const QString& jid, const QString& id, const QMap& data) +{ + ElId elid(account, jid); + std::multimap::iterator cBeg = contacts.lower_bound(elid); + std::multimap::iterator cEnd = contacts.upper_bound(elid); + + for (; cBeg != cEnd; ++cBeg) { + for (QMap::const_iterator itr = data.begin(), end = data.end(); itr != end; ++itr) { + cBeg->second->changeMessage(id, data); + } + } + + std::map::iterator rItr = rooms.find(elid); + if (rItr != rooms.end()) { + for (QMap::const_iterator itr = data.begin(), end = data.end(); itr != end; ++itr) { + rItr->second->changeMessage(id, data); } } } diff --git a/ui/models/roster.h b/ui/models/roster.h index 542d0b7..dde6370 100644 --- a/ui/models/roster.h +++ b/ui/models/roster.h @@ -23,7 +23,8 @@ #include #include #include -#include "../../global.h" + +#include "global.h" #include "accounts.h" #include "item.h" #include "account.h" @@ -54,6 +55,7 @@ public: void addPresence(const QString& account, const QString& jid, const QString& name, const QMap& data); void removePresence(const QString& account, const QString& jid, const QString& name); void addMessage(const QString& account, const Shared::Message& data); + void changeMessage(const QString& account, const QString& jid, const QString& id, const QMap& data); void dropMessages(const QString& account, const QString& jid); void addRoom(const QString& account, const QString jid, const QMap& data); void changeRoom(const QString& account, const QString jid, const QMap& data); diff --git a/ui/squawk.cpp b/ui/squawk.cpp index 722f2c7..fd9b6ff 100644 --- a/ui/squawk.cpp +++ b/ui/squawk.cpp @@ -480,9 +480,9 @@ void Squawk::accountMessage(const QString& account, const Shared::Message& data) QApplication::alert(conv); if (conv->isMinimized()) { rosterModel.addMessage(account, data); - if (!data.getForwarded()) { - notify(account, data); - } + } + if (!conv->isVisible() && !data.getForwarded()) { + notify(account, data); } } else { rosterModel.addMessage(account, data); @@ -493,6 +493,20 @@ void Squawk::accountMessage(const QString& account, const Shared::Message& data) } } +void Squawk::changeMessage(const QString& account, const QString& jid, const QString& id, const QMap& data) +{ + Conversations::iterator itr = conversations.find({account, jid}); + if (itr != conversations.end()) { + Conversation* conv = itr->second; + conv->changeMessage(id, data); + if (conv->isMinimized()) { + rosterModel.changeMessage(account, jid, id, data); + } + } else { + rosterModel.changeMessage(account, jid, id, data); + } +} + void Squawk::notify(const QString& account, const Shared::Message& msg) { QString name = QString(rosterModel.getContactName(account, msg.getPenPalJid())); diff --git a/ui/squawk.h b/ui/squawk.h index f0b21c7..a3fbcba 100644 --- a/ui/squawk.h +++ b/ui/squawk.h @@ -106,7 +106,7 @@ public slots: void fileError(const QString& messageId, const QString& error); void fileProgress(const QString& messageId, qreal value); void responseVCard(const QString& jid, const Shared::VCard& card); - void onItemCollepsed(const QModelIndex& index); + void changeMessage(const QString& account, const QString& jid, const QString& id, const QMap& data); private: typedef std::map Conversations; @@ -145,6 +145,7 @@ private slots: void onConversationShown(); void onConversationRequestLocalFile(const QString& messageId, const QString& url); void onConversationDownloadFile(const QString& messageId, const QString& url); + void onItemCollepsed(const QModelIndex& index); }; diff --git a/ui/utils/message.cpp b/ui/utils/message.cpp index ac8be9c..f3f162b 100644 --- a/ui/utils/message.cpp +++ b/ui/utils/message.cpp @@ -35,8 +35,9 @@ const QRegularExpression urlReg("(?setContentsMargins(10, 5, 10, 5); @@ -102,8 +107,8 @@ Message::Message(const Shared::Message& source, bool outgoing, const QString& p_ if (outgoing) { sender->setAlignment(Qt::AlignRight); date->setAlignment(Qt::AlignRight); + statusIcon = new QLabel(); QIcon q(Shared::icon(Shared::messageStateThemeIcons[static_cast(source.getState())])); - QLabel* statusIcon = new QLabel(); statusIcon->setToolTip(QCoreApplication::translate("Global", Shared::messageStateNames[static_cast(source.getState())].toLatin1())); statusIcon->setPixmap(q.pixmap(12, 12)); statusLay->addWidget(statusIcon); @@ -111,6 +116,7 @@ Message::Message(const Shared::Message& source, bool outgoing, const QString& p_ layout->addStretch(); layout->addWidget(body); layout->addWidget(avatar); + hasStatusIcon = true; } else { layout->addWidget(avatar); layout->addWidget(body); @@ -127,8 +133,8 @@ Message::~Message() if (!commentAdded) { delete fileComment; } - delete body; - delete avatar; + //delete body; //not sure if I should delete it here, it's probably already owned by the infrastructure and gonna die with the rest of the widget + //delete avatar; } QString Message::getId() const @@ -136,6 +142,16 @@ QString Message::getId() const return msg.getId(); } +QString Message::getSenderJid() const +{ + return msg.getFromJid(); +} + +QString Message::getSenderResource() const +{ + return msg.getFromResource(); +} + QString Message::getFileUrl() const { return msg.getOutOfBandUrl(); @@ -286,3 +302,42 @@ void Message::setAvatarPath(const QString& p_path) avatar->setPath(p_path); } } + +bool Message::change(const QMap& data) +{ + bool idChanged = msg.change(data); + + QString bd = msg.getBody(); + //bd.replace(imgReg, ""); + bd.replace(urlReg, "\\1"); + text->setText(bd); + if (bd.size() > 0) { + text->show(); + } else { + text->hide(); + } + if (msg.getEdited()) { + if (!hasEditedLabel) { + editedLabel = new QLabel(); + QFont eFont = editedLabel->font(); + eFont.setItalic(true); + eFont.setPointSize(eFont.pointSize() - 2); + editedLabel->setFont(eFont); + hasEditedLabel = true; + QHBoxLayout* statusLay = static_cast(statusBar->layout()); + if (hasStatusIcon) { + statusLay->insertWidget(1, editedLabel); + } else { + statusLay->insertWidget(0, editedLabel); + } + } + } + if (hasStatusIcon) { + QIcon q(Shared::icon(Shared::messageStateThemeIcons[static_cast(msg.getState())])); + statusIcon->setToolTip(QCoreApplication::translate("Global", Shared::messageStateNames[static_cast(msg.getState())].toLatin1())); + statusIcon->setPixmap(q.pixmap(12, 12)); + } + + + return idChanged; +} diff --git a/ui/utils/message.h b/ui/utils/message.h index b9d76ee..b041b87 100644 --- a/ui/utils/message.h +++ b/ui/utils/message.h @@ -29,6 +29,7 @@ #include #include #include +#include #include "global.h" #include "resizer.h" @@ -46,6 +47,8 @@ public: void setSender(const QString& sender); QString getId() const; + QString getSenderJid() const; + QString getSenderResource() const; QString getFileUrl() const; const Shared::Message& getMessage() const; @@ -55,6 +58,9 @@ public: void showFile(const QString& path); void setProgress(qreal value); void setAvatarPath(const QString& p_path); + bool change(const QMap& data); + + bool const outgoing; signals: void buttonClicked(); @@ -73,11 +79,15 @@ private: QLabel* file; QProgressBar* progress; QLabel* fileComment; + QLabel* statusIcon; + QLabel* editedLabel; Image* avatar; bool hasButton; bool hasProgress; bool hasFile; bool commentAdded; + bool hasStatusIcon; + bool hasEditedLabel; private: void hideButton(); diff --git a/ui/utils/messageline.cpp b/ui/utils/messageline.cpp index c436c57..d941b2e 100644 --- a/ui/utils/messageline.cpp +++ b/ui/utils/messageline.cpp @@ -122,7 +122,7 @@ MessageLine::Position MessageLine::message(const Shared::Message& msg, bool forc if (room) { senderId = sender; } else { - QString jid = msg.getFromJid(); + senderId = msg.getFromJid(); } std::map::iterator pItr = palMessages.find(senderId); @@ -161,6 +161,48 @@ MessageLine::Position MessageLine::message(const Shared::Message& msg, bool forc return res; } +void MessageLine::changeMessage(const QString& id, const QMap& data) +{ + Index::const_iterator itr = messageIndex.find(id); + if (itr != messageIndex.end()) { + Message* msg = itr->second; + if (msg->change(data)) { //if ID changed (stanza in replace of another) + QString newId = msg->getId(); //need to updated IDs of that message in all maps + messageIndex.erase(itr); + messageIndex.insert(std::make_pair(newId, msg)); + if (msg->outgoing) { + QString senderId; + if (room) { + senderId = msg->getSenderResource(); + } else { + senderId = msg->getSenderJid(); + } + + std::map::iterator pItr = palMessages.find(senderId); + if (pItr != palMessages.end()) { + Index::const_iterator sItr = pItr->second.find(id); + if (sItr != pItr->second.end()) { + pItr->second.erase(sItr); + pItr->second.insert(std::make_pair(newId, msg)); + } else { + qDebug() << "Was trying to replace message in open conversations, couldn't find it among pal's messages, probably an error"; + } + } else { + qDebug() << "Was trying to replace message in open conversations, couldn't find pal messages, probably an error"; + } + } else { + Index::const_iterator mItr = myMessages.find(id); + if (mItr != myMessages.end()) { + myMessages.erase(mItr); + myMessages.insert(std::make_pair(newId, msg)); + } else { + qDebug() << "Was trying to replace message in open conversations, couldn't find it among my messages, probably an error"; + } + } + } + } +} + void MessageLine::onDownload() { Message* msg = static_cast(sender()); diff --git a/ui/utils/messageline.h b/ui/utils/messageline.h index 707ff39..16eea21 100644 --- a/ui/utils/messageline.h +++ b/ui/utils/messageline.h @@ -26,7 +26,7 @@ #include #include -#include "../../global.h" +#include "global.h" #include "message.h" #include "progress.h" @@ -57,6 +57,7 @@ public: void setMyAvatarPath(const QString& p_path); void setPalAvatar(const QString& jid, const QString& path); void dropPalAvatar(const QString& jid); + void changeMessage(const QString& id, const QMap& data); signals: void resize(int amount); diff --git a/ui/widgets/conversation.cpp b/ui/widgets/conversation.cpp index 6b3613f..0749daa 100644 --- a/ui/widgets/conversation.cpp +++ b/ui/widgets/conversation.cpp @@ -149,6 +149,11 @@ void Conversation::addMessage(const Shared::Message& data) } } +void Conversation::changeMessage(const QString& id, const QMap& data) +{ + line->changeMessage(id, data); +} + KeyEnterReceiver::KeyEnterReceiver(QObject* parent): QObject(parent), ownEvent(false) {} bool KeyEnterReceiver::eventFilter(QObject* obj, QEvent* event) diff --git a/ui/widgets/conversation.h b/ui/widgets/conversation.h index 311db65..d9f6dda 100644 --- a/ui/widgets/conversation.h +++ b/ui/widgets/conversation.h @@ -21,13 +21,15 @@ #include #include +#include + #include "global.h" #include "order.h" -#include "../models/account.h" -#include "../utils/messageline.h" -#include "../utils/resizer.h" -#include "../utils/flowlayout.h" -#include "../utils/badge.h" +#include "ui/models/account.h" +#include "ui/utils/messageline.h" +#include "ui/utils/resizer.h" +#include "ui/utils/flowlayout.h" +#include "ui/utils/badge.h" namespace Ui { @@ -79,6 +81,7 @@ public: void fileError(const QString& messageId, const QString& error); void responseFileProgress(const QString& messageId, qreal progress); virtual void setAvatar(const QString& path); + void changeMessage(const QString& id, const QMap& data); signals: void sendMessage(const Shared::Message& message);