Changeset View
Changeset View
Standalone View
Standalone View
plugins/sms/conversationsdbusinterface.cpp
Show All 16 Lines | |||||
17 | * You should have received a copy of the GNU General Public License | 17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | 19 | */ | ||
20 | 20 | | |||
21 | #include "conversationsdbusinterface.h" | 21 | #include "conversationsdbusinterface.h" | ||
22 | #include "interfaces/dbusinterfaces.h" | 22 | #include "interfaces/dbusinterfaces.h" | ||
23 | #include "interfaces/conversationmessage.h" | 23 | #include "interfaces/conversationmessage.h" | ||
24 | 24 | | |||
25 | #include "requestconversationworker.h" | ||||
26 | | ||||
25 | #include <QDBusConnection> | 27 | #include <QDBusConnection> | ||
26 | 28 | | |||
27 | #include <core/device.h> | 29 | #include <core/device.h> | ||
28 | #include <core/kdeconnectplugin.h> | 30 | #include <core/kdeconnectplugin.h> | ||
29 | 31 | | |||
30 | Q_LOGGING_CATEGORY(KDECONNECT_CONVERSATIONS, "kdeconnect.conversations") | 32 | Q_LOGGING_CATEGORY(KDECONNECT_CONVERSATIONS, "kdeconnect.conversations") | ||
31 | 33 | | |||
32 | ConversationsDbusInterface::ConversationsDbusInterface(KdeConnectPlugin* plugin) | 34 | ConversationsDbusInterface::ConversationsDbusInterface(KdeConnectPlugin* plugin) | ||
Show All 26 Lines | 53 | for (auto it = m_conversations.cbegin(); it != m_conversations.cend(); ++it) { | |||
59 | } | 61 | } | ||
60 | const QVariantMap& message = (*conversation.crbegin()).toVariant(); | 62 | const QVariantMap& message = (*conversation.crbegin()).toVariant(); | ||
61 | toReturn.append(message); | 63 | toReturn.append(message); | ||
62 | } | 64 | } | ||
63 | 65 | | |||
64 | return toReturn; | 66 | return toReturn; | ||
65 | } | 67 | } | ||
66 | 68 | | |||
67 | void ConversationsDbusInterface::requestConversation(const QString& conversationID, int start, int end) | 69 | void ConversationsDbusInterface::requestConversation(const qint32& conversationID, int start, int end) | ||
68 | { | 70 | { | ||
69 | const auto messagesList = m_conversations[conversationID].values(); | 71 | QThread* handlingThread = new QThread(); | ||
70 | 72 | RequestConversationWorker* worker = new RequestConversationWorker(conversationID, start, end, this); | |||
71 | if (messagesList.isEmpty()) { | 73 | worker->moveToThread(handlingThread); | ||
72 | // Since there are no messages in the conversation, it's likely that it is a junk ID, but go ahead anyway | 74 | connect(handlingThread, &QThread::started, | ||
73 | qCWarning(KDECONNECT_CONVERSATIONS) << "Got a conversationID for a conversation with no messages!" << conversationID; | 75 | worker, &RequestConversationWorker::handleRequestConversation); | ||
74 | } | 76 | connect(handlingThread, &QThread::finished, | ||
75 | 77 | handlingThread, &QObject::deleteLater); | |||
76 | // TODO: Check local cache before requesting new messages | 78 | connect(worker, &RequestConversationWorker::finished, | ||
77 | // TODO: Make Android interface capable of requesting small window of messages | 79 | handlingThread, &QThread::quit); | ||
78 | m_smsInterface.requestConversation(conversationID); | 80 | connect(worker, &RequestConversationWorker::finished, | ||
79 | 81 | worker, &QObject::deleteLater); | |||
80 | // Messages are sorted in ascending order of keys, meaning the front of the list has the oldest | 82 | connect(worker, &RequestConversationWorker::conversationMessageRead, | ||
81 | // messages (smallest timestamp number) | 83 | this, &ConversationsDbusInterface::conversationUpdated, | ||
82 | // Therefore, return the end of the list first (most recent messages) | 84 | Qt::QueuedConnection); | ||
83 | int i = start; | 85 | handlingThread->start(); | ||
84 | for(auto it = messagesList.crbegin() + start; it != messagesList.crend(); ++it) { | | |||
85 | Q_EMIT conversationMessageReceived(it->toVariant(), i); | | |||
86 | i++; | | |||
87 | if (i >= end) { | | |||
88 | break; | | |||
89 | } | | |||
90 | } | | |||
91 | } | 86 | } | ||
apol: Use `m_conversations.value(conversationID)`. Otherwise, if conversationId doesn't exist, it… | |||||
This is actually fixed in D16475 sredman: This is actually fixed in D16475 | |||||
92 | 87 | | |||
93 | void ConversationsDbusInterface::addMessage(const ConversationMessage &message) | 88 | void ConversationsDbusInterface::addMessages(const QList<ConversationMessage> &messages) | ||
94 | { | 89 | { | ||
95 | const QString& threadId = QString::number(message.threadID()); | 90 | QSet<qint32> updatedConversationIDs; | ||
91 | | ||||
92 | for (const auto& message : messages) { | ||||
93 | const qint32& threadId = message.threadID(); | ||||
apol: `messagesList.length() <= end` | |||||
96 | 94 | | |||
97 | if (m_known_messages[threadId].contains(message.uID())) { | 95 | if (m_known_messages[threadId].contains(message.uID())) { | ||
98 | // This message has already been processed. Don't do anything. | 96 | // This message has already been processed. Don't do anything. | ||
99 | return; | 97 | continue; | ||
100 | } | 98 | } | ||
101 | 99 | | |||
100 | updatedConversationIDs.insert(message.threadID()); | ||||
101 | | ||||
102 | // Store the Message in the list corresponding to its thread | 102 | // Store the Message in the list corresponding to its thread | ||
103 | bool newConversation = !m_conversations.contains(threadId); | 103 | bool newConversation = !m_conversations.contains(threadId); | ||
104 | m_conversations[threadId].insert(message.date(), message); | 104 | const auto& threadPosition = m_conversations[threadId].insert(message.date(), message); | ||
105 | m_known_messages[threadId].insert(message.uID()); | 105 | m_known_messages[threadId].insert(message.uID()); | ||
106 | 106 | | |||
107 | // If this message was inserted at the end of the list, it is the latest message in the conversation | ||||
108 | bool latestMessage = threadPosition == m_conversations[threadId].end() - 1; | ||||
109 | | ||||
107 | // Tell the world about what just happened | 110 | // Tell the world about what just happened | ||
108 | if (newConversation) { | 111 | if (newConversation) { | ||
109 | Q_EMIT conversationCreated(message.toVariant()); | 112 | Q_EMIT conversationCreated(message.toVariant()); | ||
110 | } else { | 113 | } else if (latestMessage) { | ||
111 | Q_EMIT conversationUpdated(message.toVariant()); | 114 | Q_EMIT conversationUpdated(message.toVariant()); | ||
112 | } | 115 | } | ||
113 | } | 116 | } | ||
114 | 117 | | |||
118 | waitingForMessagesLock.lock(); | ||||
119 | // Remove the waiting flag for all conversations which we just processed | ||||
120 | conversationsWaitingForMessages.subtract(updatedConversationIDs); | ||||
121 | waitingForMessages.wakeAll(); | ||||
122 | waitingForMessagesLock.unlock(); | ||||
123 | } | ||||
124 | | ||||
115 | void ConversationsDbusInterface::removeMessage(const QString& internalId) | 125 | void ConversationsDbusInterface::removeMessage(const QString& internalId) | ||
116 | { | 126 | { | ||
117 | // TODO: Delete the specified message from our internal structures | 127 | // TODO: Delete the specified message from our internal structures | ||
118 | } | 128 | } | ||
119 | 129 | | |||
120 | void ConversationsDbusInterface::replyToConversation(const QString& conversationID, const QString& message) | 130 | QList<ConversationMessage> ConversationsDbusInterface::getConversation(const qint32& conversationID) const | ||
131 | { | ||||
132 | return m_conversations.value(conversationID).values(); | ||||
133 | } | ||||
134 | | ||||
135 | void ConversationsDbusInterface::updateConversation(const qint32& conversationID) | ||||
136 | { | ||||
137 | waitingForMessagesLock.lock(); | ||||
138 | conversationsWaitingForMessages.insert(conversationID); | ||||
139 | m_smsInterface.requestConversation(conversationID); | ||||
140 | while (conversationsWaitingForMessages.contains(conversationID)) { | ||||
141 | waitingForMessages.wait(&waitingForMessagesLock); | ||||
142 | } | ||||
143 | waitingForMessagesLock.unlock(); | ||||
144 | } | ||||
145 | | ||||
146 | void ConversationsDbusInterface::replyToConversation(const qint32& conversationID, const QString& message) | ||||
121 | { | 147 | { | ||
122 | const auto messagesList = m_conversations[conversationID]; | 148 | const auto messagesList = m_conversations[conversationID]; | ||
123 | if (messagesList.isEmpty()) { | 149 | if (messagesList.isEmpty()) { | ||
124 | // Since there are no messages in the conversation, we can't do anything sensible | 150 | // Since there are no messages in the conversation, we can't do anything sensible | ||
125 | qCWarning(KDECONNECT_CONVERSATIONS) << "Got a conversationID for a conversation with no messages!"; | 151 | qCWarning(KDECONNECT_CONVERSATIONS) << "Got a conversationID for a conversation with no messages!"; | ||
126 | return; | 152 | return; | ||
127 | } | 153 | } | ||
128 | // Caution: | 154 | // Caution: | ||
Show All 17 Lines |
Use m_conversations.value(conversationID). Otherwise, if conversationId doesn't exist, it will create the entry and leave it empty.