qTox  Version: nightly | Commit: bc751c8e1cac455f9690654fcfe0f560d2d7dfdd
chathistory.cpp
Go to the documentation of this file.
1 /*
2  Copyright © 2019 by The qTox Project Contributors
3 
4  This file is part of qTox, a Qt-based graphical interface for Tox.
5 
6  qTox is libre software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  qTox is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with qTox. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "chathistory.h"
23 
24 namespace {
31 bool needsLoadFromHistory(ChatLogIdx idx, const SessionChatLog& sessionChatLog)
32 {
33  return idx < sessionChatLog.getFirstIdx();
34 }
35 
41 ChatLogIdx findFirstMessage(const SessionChatLog& sessionChatLog)
42 {
43  auto it = sessionChatLog.getFirstIdx();
44  while (it < sessionChatLog.getNextIdx()) {
45  if (sessionChatLog.at(it).getContentType() == ChatLogItem::ContentType::message) {
46  return it;
47  }
48  it++;
49  }
50  return ChatLogIdx(-1);
51 }
52 
58 bool handleActionPrefix(QString& content)
59 {
60  // Unfortunately due to legacy reasons we have to continue
61  // inserting and parsing for ACTION_PREFIX in our messages even
62  // though we have the ability to something more intelligent now
63  // that we aren't owned by chatform logic
64  auto isAction = content.startsWith(ChatForm::ACTION_PREFIX, Qt::CaseInsensitive);
65  if (isAction) {
66  content.remove(0, ChatForm::ACTION_PREFIX.size());
67  }
68 
69  return isAction;
70 }
71 } // namespace
72 
73 ChatHistory::ChatHistory(Friend& f_, History* history_, const ICoreIdHandler& coreIdHandler,
74  const Settings& settings_, IMessageDispatcher& messageDispatcher)
75  : f(f_)
76  , history(history_)
77  , settings(settings_)
78  , coreIdHandler(coreIdHandler)
79  , sessionChatLog(getInitialChatLogIdx(), coreIdHandler)
80 {
81  connect(&messageDispatcher, &IMessageDispatcher::messageComplete, this,
83  connect(&messageDispatcher, &IMessageDispatcher::messageReceived, this,
85  connect(&messageDispatcher, &IMessageDispatcher::messageBroken, this,
87 
88  if (canUseHistory()) {
89  // Defer messageSent callback until we finish firing off all our unsent messages.
90  // If it was connected all our unsent messages would be re-added ot history again
91  dispatchUnsentMessages(messageDispatcher);
92  }
93 
94  // Now that we've fired off our unsent messages we can connect the message
95  connect(&messageDispatcher, &IMessageDispatcher::messageSent, this, &ChatHistory::onMessageSent);
96 
97  // NOTE: this has to be done _after_ sending all sent messages since initial
98  // state of the message has to be marked according to our dispatch state
99  constexpr auto defaultNumMessagesToLoad = 100;
100  auto firstChatLogIdx = sessionChatLog.getFirstIdx().get() < defaultNumMessagesToLoad
101  ? ChatLogIdx(0)
102  : sessionChatLog.getFirstIdx() - defaultNumMessagesToLoad;
103 
104  if (canUseHistory()) {
105  loadHistoryIntoSessionChatLog(firstChatLogIdx);
106  }
107 
108  // We don't manage any of the item updates ourselves, we just forward along
109  // the underlying sessionChatLog's updates
111 }
112 
114 {
115  if (canUseHistory()) {
117  }
118 
119  return sessionChatLog.at(idx);
120 }
121 
122 SearchResult ChatHistory::searchForward(SearchPos startIdx, const QString& phrase,
123  const ParameterSearch& parameter) const
124 {
125  if (startIdx.logIdx >= getNextIdx()) {
126  SearchResult res;
127  res.found = false;
128  return res;
129  }
130 
131  if (canUseHistory()) {
133  }
134 
135  return sessionChatLog.searchForward(startIdx, phrase, parameter);
136 }
137 
138 SearchResult ChatHistory::searchBackward(SearchPos startIdx, const QString& phrase,
139  const ParameterSearch& parameter) const
140 {
141  auto res = sessionChatLog.searchBackward(startIdx, phrase, parameter);
142 
143  if (res.found || !canUseHistory()) {
144  return res;
145  }
146 
147  auto earliestMessage = findFirstMessage(sessionChatLog);
148 
149  auto earliestMessageDate =
150  (earliestMessage == ChatLogIdx(-1))
151  ? QDateTime::currentDateTime()
153 
154  // Roundabout way of getting the first idx but I don't want to have to
155  // deal with re-implementing so we'll just piece what we want together...
156  //
157  // If the double disk access is real bad we can optimize this by adding
158  // another function to history
159  auto dateWherePhraseFound =
160  history->getDateWhereFindPhrase(f.getPublicKey(), earliestMessageDate, phrase,
161  parameter);
162 
163  auto loadIdx = history->getNumMessagesForFriendBeforeDate(f.getPublicKey(), dateWherePhraseFound);
165 
166  // Reset search pos to the message we just loaded to avoid a double search
167  startIdx.logIdx = ChatLogIdx(loadIdx);
168  startIdx.numMatches = 0;
169  return sessionChatLog.searchBackward(startIdx, phrase, parameter);
170 }
171 
173 {
174  if (canUseHistory()) {
175  return ChatLogIdx(0);
176  } else {
177  return sessionChatLog.getFirstIdx();
178  }
179 }
180 
182 {
183  return sessionChatLog.getNextIdx();
184 }
185 
186 std::vector<IChatLog::DateChatLogIdxPair> ChatHistory::getDateIdxs(const QDate& startDate,
187  size_t maxDates) const
188 {
189  if (canUseHistory()) {
191  startDate, maxDates);
192 
193  std::vector<IChatLog::DateChatLogIdxPair> ret;
194  std::transform(counts.begin(), counts.end(), std::back_inserter(ret),
195  [&](const History::DateIdx& historyDateIdx) {
196  DateChatLogIdxPair pair;
197  pair.date = historyDateIdx.date;
198  pair.idx.get() = historyDateIdx.numMessagesIn;
199  return pair;
200  });
201 
202  // Do not re-search in the session chat log. If we have history the query to the history should have been sufficient
203  return ret;
204  } else {
205  return sessionChatLog.getDateIdxs(startDate, maxDates);
206  }
207 }
208 
210 {
211  if (canUseHistory()) {
213  }
214 
216 }
217 
218 
219 void ChatHistory::onFileUpdated(const ToxPk& sender, const ToxFile& file)
220 {
221  if (canUseHistory()) {
222  switch (file.status) {
223  case ToxFile::INITIALIZING: {
224  auto selfPk = coreIdHandler.getSelfPublicKey();
225  QString username(selfPk == sender ? coreIdHandler.getUsername() : f.getDisplayedName());
226 
227  // Note: There is some implcit coupling between history and the current
228  // chat log. Both rely on generating a new id based on the state of
229  // initializing. If this is changed in the session chat log we'll end up
230  // with a different order when loading from history
231  history->addNewFileMessage(f.getPublicKey(), file.resumeFileId, file.fileName,
232  file.filePath, file.progress.getFileSize(), sender,
233  QDateTime::currentDateTime(), username);
234  break;
235  }
236  case ToxFile::CANCELED:
237  case ToxFile::FINISHED:
238  case ToxFile::BROKEN: {
239  const bool isSuccess = file.status == ToxFile::FINISHED;
240  history->setFileFinished(file.resumeFileId, isSuccess, file.filePath,
241  file.hashGenerator->result());
242  break;
243  }
244  case ToxFile::PAUSED:
246  default:
247  break;
248  }
249  }
250 
252 }
253 
255  bool paused)
256 {
258 }
259 
260 void ChatHistory::onFileTransferBrokenUnbroken(const ToxPk& sender, const ToxFile& file, bool broken)
261 {
263 }
264 
265 void ChatHistory::onMessageReceived(const ToxPk& sender, const Message& message)
266 {
267  if (canUseHistory()) {
268  auto friendPk = f.getPublicKey();
269  auto displayName = f.getDisplayedName();
270  auto content = message.content;
271  if (message.isAction) {
272  content = ChatForm::ACTION_PREFIX + content;
273  }
274 
275  history->addNewMessage(friendPk, content, friendPk, message.timestamp, true, message.extensionSet, displayName);
276  }
277 
279 }
280 
282 {
283  if (canUseHistory()) {
284  auto selfPk = coreIdHandler.getSelfPublicKey();
285  auto friendPk = f.getPublicKey();
286 
287  auto content = message.content;
288  if (message.isAction) {
289  content = ChatForm::ACTION_PREFIX + content;
290  }
291 
292  auto username = coreIdHandler.getUsername();
293 
294  auto onInsertion = [this, id](RowId historyId) { handleDispatchedMessage(id, historyId); };
295 
296  history->addNewMessage(friendPk, content, selfPk, message.timestamp, false, message.extensionSet, username,
297  onInsertion);
298  }
299 
301 }
302 
304 {
305  if (canUseHistory()) {
306  completeMessage(id);
307  }
308 
310 }
311 
313 {
314  if (canUseHistory()) {
315  breakMessage(id, reason);
316  }
317 
318  sessionChatLog.onMessageBroken(id, reason);
319 }
320 
329 {
330  if (needsLoadFromHistory(idx, sessionChatLog)) {
332  }
333 }
345 {
346  if (!needsLoadFromHistory(start, sessionChatLog)) {
347  return;
348  }
349 
350  auto end = sessionChatLog.getFirstIdx();
351 
352  // We know that both history and us have a start index of 0 so the type
353  // conversion should be safe
354  assert(getFirstIdx() == ChatLogIdx(0));
355  auto messages = history->getMessagesForFriend(f.getPublicKey(), start.get(), end.get());
356 
357  assert(messages.size() == static_cast<int>(end.get() - start.get()));
358  ChatLogIdx nextIdx = start;
359 
360  for (const auto& message : messages) {
361  // Note that message.id is _not_ a valid conversion here since it is a
362  // global id not a per-chat id like the ChatLogIdx
363  auto currentIdx = nextIdx++;
364  switch (message.content.getType()) {
366  auto sender = ToxPk(message.sender);
367  const auto date = message.timestamp;
368  const auto file = message.content.asFile();
369  const auto chatLogFile = ChatLogFile{date, file};
370  sessionChatLog.insertFileAtIdx(currentIdx, sender, message.dispName, chatLogFile);
371  break;
372  }
374  auto sender = ToxPk(message.sender);
375  auto messageContent = message.content.asMessage();
376 
377  auto isAction = handleActionPrefix(messageContent);
378 
379  // It's okay to skip the message processor here. The processor is
380  // meant to convert between boundaries of our internal
381  // representation. We already had to go through the processor before
382  // we hit IMessageDispatcher's signals which history listens for.
383  // Items added to history have already been sent so we know they already
384  // reflect what was sent/received.
385  auto processedMessage = Message{isAction, messageContent, message.timestamp};
386 
387  auto dispatchedMessageIt =
388  std::find_if(dispatchedMessageRowIdMap.begin(), dispatchedMessageRowIdMap.end(),
389  [&](RowId dispatchedId) { return dispatchedId == message.id; });
390 
391  assert((message.state != MessageState::pending && dispatchedMessageIt == dispatchedMessageRowIdMap.end()) ||
392  (message.state == MessageState::pending && dispatchedMessageIt != dispatchedMessageRowIdMap.end()));
393 
394  auto chatLogMessage = ChatLogMessage{message.state, processedMessage};
395  switch (message.state) {
397  sessionChatLog.insertCompleteMessageAtIdx(currentIdx, sender, message.dispName,
398  chatLogMessage);
399  break;
401  sessionChatLog.insertIncompleteMessageAtIdx(currentIdx, sender, message.dispName,
402  chatLogMessage, dispatchedMessageIt.key());
403  break;
405  sessionChatLog.insertBrokenMessageAtIdx(currentIdx, sender, message.dispName,
406  chatLogMessage);
407  break;
408  }
409  break;
410  }
412  const auto& systemMessage = message.content.asSystemMessage();
413  sessionChatLog.insertSystemMessageAtIdx(currentIdx, systemMessage);
414  break;
415  }
416  }
417  }
418 
419  assert(nextIdx == end);
420 }
421 
427 {
428  auto unsentMessages = history->getUndeliveredMessagesForFriend(f.getPublicKey());
429 
430  auto requiredExtensions = std::accumulate(
431  unsentMessages.begin(), unsentMessages.end(),
432  ExtensionSet(), [] (const ExtensionSet& a, const History::HistMessage& b) {
433  return a | b.extensionSet;
434  });
435 
436  for (auto& message : unsentMessages) {
437  // We should only store messages as unsent, if this changes in the
438  // future we need to extend this logic
439  assert(message.content.getType() == HistMessageContentType::message);
440 
441  auto messageContent = message.content.asMessage();
442  auto isAction = handleActionPrefix(messageContent);
443 
444  // NOTE: timestamp will be generated in messageDispatcher but we haven't
445  // hooked up our history callback so it will not be shown in our chatlog
446  // with the new timestamp. This is intentional as everywhere else we use
447  // attempted send time (which is whenever the it was initially inserted
448  // into history
449  auto dispatchId = requiredExtensions.none()
450  // We should only send a single message, but in the odd case where we end
451  // up having to split more than when we added the message to history we'll
452  // just associate the last dispatched id with the history message
453  ? messageDispatcher.sendMessage(isAction, messageContent).second
454  : messageDispatcher.sendExtendedMessage(messageContent, requiredExtensions).second;
455 
456  handleDispatchedMessage(dispatchId, message.id);
457 
458  // We don't add the messages to the underlying chatlog since
459  // 1. We don't even know the ChatLogIdx of this message
460  // 2. We only want to display the latest N messages on boot by default,
461  // even if there are more than N messages that haven't been sent
462  }
463 }
464 
466 {
467  auto completedMessageIt = completedMessages.find(dispatchId);
468  auto brokenMessageIt = brokenMessages.find(dispatchId);
469 
470  const auto isCompleted = completedMessageIt != completedMessages.end();
471  const auto isBroken = brokenMessageIt != brokenMessages.end();
472  assert(!(isCompleted && isBroken));
473 
474  if (isCompleted) {
475  history->markAsDelivered(historyId);
476  completedMessages.erase(completedMessageIt);
477  } else if (isBroken) {
478  history->markAsBroken(historyId, brokenMessageIt.value());
479  brokenMessages.erase(brokenMessageIt);
480  } else {
481  dispatchedMessageRowIdMap.insert(dispatchId, historyId);
482  }
483 }
484 
486 {
487  auto dispatchedMessageIt = dispatchedMessageRowIdMap.find(id);
488 
489  if (dispatchedMessageIt == dispatchedMessageRowIdMap.end()) {
490  completedMessages.insert(id);
491  } else {
492  history->markAsDelivered(*dispatchedMessageIt);
493  dispatchedMessageRowIdMap.erase(dispatchedMessageIt);
494  }
495 }
496 
498 {
499  auto dispatchedMessageIt = dispatchedMessageRowIdMap.find(id);
500 
501  if (dispatchedMessageIt == dispatchedMessageRowIdMap.end()) {
502  brokenMessages.insert(id, reason);
503  } else {
504  history->markAsBroken(*dispatchedMessageIt, reason);
505  dispatchedMessageRowIdMap.erase(dispatchedMessageIt);
506  }
507 }
508 
510 {
511  return history && settings.getEnableLogging();
512 }
513 
522 {
523  if (canUseHistory()) {
525  }
526  return ChatLogIdx(0);
527 }
ChatHistory::loadHistoryIntoSessionChatLog
void loadHistoryIntoSessionChatLog(ChatLogIdx start) const
Unconditionally loads the given index and all future messages that are not in the session chat log in...
Definition: chathistory.cpp:344
SessionChatLog::getFirstIdx
ChatLogIdx getFirstIdx() const override
The underlying chat log instance may not want to start at 0.
Definition: sessionchatlog.cpp:280
Settings
Definition: settings.h:51
SessionChatLog::onMessageBroken
void onMessageBroken(DispatchedMessageId id, BrokenMessageReason reason)
Definition: sessionchatlog.cpp:439
History::setFileFinished
void setFileFinished(const QString &fileId, bool success, const QString &filePath, const QByteArray &fileHash)
Definition: history.cpp:989
ChatHistory::history
History * history
Definition: chathistory.h:70
ChatLogItem
Definition: chatlogitem.h:42
ChatHistory::getNextIdx
ChatLogIdx getNextIdx() const override
Definition: chathistory.cpp:181
SessionChatLog::onFileUpdated
void onFileUpdated(const ToxPk &sender, const ToxFile &file)
Updates file state in the chatlog.
Definition: sessionchatlog.cpp:467
ToxFile::BROKEN
@ BROKEN
Definition: toxfile.h:41
settings.h
SessionChatLog::getDateIdxs
std::vector< DateChatLogIdxPair > getDateIdxs(const QDate &startDate, size_t maxDates) const override
Gets indexes for each new date starting at startDate.
Definition: sessionchatlog.cpp:294
ChatHistory::onMessageSent
void onMessageSent(DispatchedMessageId id, const Message &message)
Definition: chathistory.cpp:281
ICoreIdHandler::getUsername
virtual QString getUsername() const =0
ChatHistory::onFileTransferRemotePausedUnpaused
void onFileTransferRemotePausedUnpaused(const ToxPk &sender, const ToxFile &file, bool paused)
Definition: chathistory.cpp:254
History::markAsBroken
void markAsBroken(RowId messageId, BrokenMessageReason reason)
Definition: history.cpp:1402
ParameterSearch
Definition: searchtypes.h:47
SessionChatLog::onMessageSent
void onMessageSent(DispatchedMessageId id, const Message &message)
Inserts message data into the chatlog buffer.
Definition: sessionchatlog.cpp:397
RowId
NamedType< int64_t, struct RowIdTag, Orderable > RowId
Definition: rawdatabase.h:49
ChatHistory::getFirstIdx
ChatLogIdx getFirstIdx() const override
The underlying chat log instance may not want to start at 0.
Definition: chathistory.cpp:172
ChatHistory::at
const ChatLogItem & at(ChatLogIdx idx) const override
Returns reference to item at idx.
Definition: chathistory.cpp:113
ToxFile::TRANSMITTING
@ TRANSMITTING
Definition: toxfile.h:40
ChatLogItem::ContentType::message
@ message
HistMessageContentType::file
@ file
chathistory.h
IMessageDispatcher::sendMessage
virtual std::pair< DispatchedMessageId, DispatchedMessageId > sendMessage(bool isAction, const QString &content)=0
Sends message to associated chat.
SessionChatLog::searchBackward
SearchResult searchBackward(SearchPos startIdx, const QString &phrase, const ParameterSearch &parameter) const override
searches backwards through the chat log until phrase is found according to parameter
Definition: sessionchatlog.cpp:213
SystemMessage
Definition: systemmessage.h:47
IMessageDispatcher
Definition: imessagedispatcher.h:34
ChatHistory::f
Friend & f
Definition: chathistory.h:69
ChatHistory::onMessageBroken
void onMessageBroken(DispatchedMessageId id, BrokenMessageReason reason)
Definition: chathistory.cpp:312
IMessageDispatcher::messageSent
void messageSent(DispatchedMessageId id, const Message &message)
Emitted when a message is processed and sent.
SessionChatLog::addSystemMessage
void addSystemMessage(const SystemMessage &message) override
Inserts a system message at the end of the chat.
Definition: sessionchatlog.cpp:322
History::HistMessage::extensionSet
ExtensionSet extensionSet
Definition: history.h:178
ChatHistory::onFileTransferBrokenUnbroken
void onFileTransferBrokenUnbroken(const ToxPk &sender, const ToxFile &file, bool broken)
Definition: chathistory.cpp:260
ChatLogItem::getContentType
ContentType getContentType() const
Definition: chatlogitem.cpp:70
HistMessageContentType::system
@ system
SessionChatLog
Definition: sessionchatlog.h:31
SessionChatLog::onFileTransferRemotePausedUnpaused
void onFileTransferRemotePausedUnpaused(const ToxPk &sender, const ToxFile &file, bool paused)
Definition: sessionchatlog.cpp:501
SessionChatLog::at
const ChatLogItem & at(ChatLogIdx idx) const override
Returns reference to item at idx.
Definition: sessionchatlog.cpp:150
SessionChatLog::onFileTransferBrokenUnbroken
void onFileTransferBrokenUnbroken(const ToxPk &sender, const ToxFile &file, bool broken)
Definition: sessionchatlog.cpp:507
SessionChatLog::insertBrokenMessageAtIdx
void insertBrokenMessageAtIdx(ChatLogIdx idx, const ToxPk &sender, QString senderName, const ChatLogMessage &message)
Definition: sessionchatlog.cpp:353
History::addNewSystemMessage
void addNewSystemMessage(const ToxPk &friendPk, const SystemMessage &systemMessage)
Definition: history.cpp:957
History::markAsDelivered
void markAsDelivered(RowId messageId)
Marks a message as delivered. Removing message from the faux-offline pending messages list.
Definition: history.cpp:1374
FileTransferList::Column::size
@ size
ChatHistory::brokenMessages
QMap< DispatchedMessageId, BrokenMessageReason > brokenMessages
Definition: chathistory.h:80
chatform.h
History::getNumMessagesForFriendBeforeDate
size_t getNumMessagesForFriendBeforeDate(const ToxPk &friendPk, const QDateTime &date)
Definition: history.cpp:1018
ChatHistory::dispatchedMessageRowIdMap
QMap< DispatchedMessageId, RowId > dispatchedMessageRowIdMap
Definition: chathistory.h:84
ChatHistory::completedMessages
QSet< DispatchedMessageId > completedMessages
Definition: chathistory.h:77
History::getUndeliveredMessagesForFriend
QList< HistMessage > getUndeliveredMessagesForFriend(const ToxPk &friendPk)
Definition: history.cpp:1158
ChatHistory::settings
const Settings & settings
Definition: chathistory.h:71
HistMessageContentType::message
@ message
IMessageDispatcher::messageComplete
void messageComplete(DispatchedMessageId id)
Emitted when a receiver report is received from the associated chat.
SessionChatLog::insertCompleteMessageAtIdx
void insertCompleteMessageAtIdx(ChatLogIdx idx, const ToxPk &sender, QString senderName, const ChatLogMessage &message)
Definition: sessionchatlog.cpp:331
ToxPk
This class represents a Tox Public Key, which is a part of Tox ID.
Definition: toxpk.h:26
ChatHistory::ensureIdxInSessionChatLog
void ensureIdxInSessionChatLog(ChatLogIdx idx) const
Forces the given index and all future indexes to be in the chatlog.
Definition: chathistory.cpp:328
Friend
Definition: friend.h:31
SessionChatLog::getNextIdx
ChatLogIdx getNextIdx() const override
Definition: sessionchatlog.cpp:289
ToxFile::INITIALIZING
@ INITIALIZING
Definition: toxfile.h:38
ToxFile::PAUSED
@ PAUSED
Definition: toxfile.h:39
ChatLogMessage
Definition: chatlogitem.h:30
History::getNumMessagesForFriendBeforeDateBoundaries
QList< DateIdx > getNumMessagesForFriendBeforeDateBoundaries(const ToxPk &friendPk, const QDate &from, size_t maxNum)
Gets date boundaries in conversation with friendPk. History doesn't model conversation indexes,...
Definition: history.cpp:1313
ICoreIdHandler::getSelfPublicKey
virtual ToxPk getSelfPublicKey() const =0
ToxFile::CANCELED
@ CANCELED
Definition: toxfile.h:42
ChatHistory::handleDispatchedMessage
void handleDispatchedMessage(DispatchedMessageId dispatchId, RowId historyId)
Definition: chathistory.cpp:465
History::getMessagesForFriend
QList< HistMessage > getMessagesForFriend(const ToxPk &friendPk, size_t firstIdx, size_t lastIdx)
Definition: history.cpp:1046
DispatchedMessageId
NamedType< size_t, struct SentMessageIdTag, Orderable, Incrementable > DispatchedMessageId
Definition: imessagedispatcher.h:31
ToxFile::FINISHED
@ FINISHED
Definition: toxfile.h:43
ChatHistory::onMessageReceived
void onMessageReceived(const ToxPk &sender, const Message &message)
Definition: chathistory.cpp:265
ChatHistory::completeMessage
void completeMessage(DispatchedMessageId id)
Definition: chathistory.cpp:485
ChatHistory::breakMessage
void breakMessage(DispatchedMessageId id, BrokenMessageReason reason)
Definition: chathistory.cpp:497
IChatLog::itemUpdated
void itemUpdated(ChatLogIdx idx)
History::DateIdx
Definition: history.h:182
SessionChatLog::insertIncompleteMessageAtIdx
void insertIncompleteMessageAtIdx(ChatLogIdx idx, const ToxPk &sender, QString senderName, const ChatLogMessage &message, DispatchedMessageId dispatchId)
Definition: sessionchatlog.cpp:341
ChatHistory::sessionChatLog
SessionChatLog sessionChatLog
Definition: chathistory.h:73
Friend::getDisplayedName
QString getDisplayedName() const override
Friend::getDisplayedName Gets the name that should be displayed for a user.
Definition: friend.cpp:112
BrokenMessageReason
BrokenMessageReason
Definition: brokenmessagereason.h:23
SearchPos::numMatches
size_t numMatches
Definition: ichatlog.h:47
ChatLogIdx
NamedType< size_t, struct ChatLogIdxTag, Orderable, UnderlyingAddable, UnitlessDifferencable, Incrementable > ChatLogIdx
Definition: ichatlog.h:38
ChatLogItem::getContentAsMessage
ChatLogMessage & getContentAsMessage()
Definition: chatlogitem.cpp:87
ExtensionSet
std::bitset< ExtensionType::max > ExtensionSet
Definition: extension.h:32
History
Interacts with the profile database to save the chat history.
Definition: history.h:135
History::addNewFileMessage
void addNewFileMessage(const ToxPk &friendPk, const QString &fileId, const QString &fileName, const QString &filePath, int64_t size, const ToxPk &sender, const QDateTime &time, QString const &dispName)
Definition: history.cpp:915
History::getNumMessagesForFriend
size_t getNumMessagesForFriend(const ToxPk &friendPk)
Definition: history.cpp:1009
SearchPos
Definition: ichatlog.h:41
Settings::getEnableLogging
bool getEnableLogging() const
Definition: settings.cpp:1241
Friend::getPublicKey
const ToxPk & getPublicKey() const
Definition: friend.cpp:131
MessageState::complete
@ complete
ICoreIdHandler
Definition: icoreidhandler.h:25
SessionChatLog::insertSystemMessageAtIdx
void insertSystemMessageAtIdx(ChatLogIdx idx, SystemMessage message)
Definition: sessionchatlog.cpp:370
SessionChatLog::searchForward
SearchResult searchForward(SearchPos startIdx, const QString &phrase, const ParameterSearch &parameter) const override
searches forwards through the chat log until phrase is found according to parameter
Definition: sessionchatlog.cpp:160
IMessageDispatcher::messageReceived
void messageReceived(const ToxPk &sender, const Message &message)
Emitted when a message is received and processed.
History::addNewMessage
void addNewMessage(const ToxPk &friendPk, const QString &message, const ToxPk &sender, const QDateTime &time, bool isDelivered, ExtensionSet extensions, QString dispName, const std::function< void(RowId)> &insertIdCallback={})
Saves a chat message in the database.
Definition: history.cpp:977
ChatHistory::coreIdHandler
const ICoreIdHandler & coreIdHandler
Definition: chathistory.h:72
IMessageDispatcher::sendExtendedMessage
virtual std::pair< DispatchedMessageId, DispatchedMessageId > sendExtendedMessage(const QString &content, ExtensionSet extensions)=0
Sends message to associated chat ensuring that extensions are available.
Message::timestamp
QDateTime timestamp
Definition: message.h:56
ChatHistory::onFileUpdated
void onFileUpdated(const ToxPk &sender, const ToxFile &file)
Definition: chathistory.cpp:219
ChatHistory::ChatHistory
ChatHistory(Friend &f_, History *history_, const ICoreIdHandler &coreIdHandler, const Settings &settings, IMessageDispatcher &messageDispatcher)
Definition: chathistory.cpp:73
ChatLogMessage::message
Message message
Definition: chatlogitem.h:33
ChatForm::ACTION_PREFIX
static const QString ACTION_PREFIX
Definition: chatform.h:58
ChatHistory::addSystemMessage
void addSystemMessage(const SystemMessage &message) override
Inserts a system message at the end of the chat.
Definition: chathistory.cpp:209
SessionChatLog::onMessageReceived
void onMessageReceived(const ToxPk &sender, const Message &message)
Inserts message data into the chatlog buffer.
Definition: sessionchatlog.cpp:381
SessionChatLog::onMessageComplete
void onMessageComplete(DispatchedMessageId id)
Marks the associated message as complete and notifies any listeners.
Definition: sessionchatlog.cpp:417
ChatHistory::searchForward
SearchResult searchForward(SearchPos startIdx, const QString &phrase, const ParameterSearch &parameter) const override
searches forwards through the chat log until phrase is found according to parameter
Definition: chathistory.cpp:122
ChatHistory::canUseHistory
bool canUseHistory() const
Definition: chathistory.cpp:509
ToxFile
Definition: toxfile.h:32
MessageState::broken
@ broken
History::getDateWhereFindPhrase
QDateTime getDateWhereFindPhrase(const ToxPk &friendPk, const QDateTime &from, QString phrase, const ParameterSearch &parameter)
Search phrase in chat messages.
Definition: history.cpp:1211
SessionChatLog::insertFileAtIdx
void insertFileAtIdx(ChatLogIdx idx, const ToxPk &sender, QString senderName, const ChatLogFile &file)
Definition: sessionchatlog.cpp:363
ChatHistory::getDateIdxs
std::vector< DateChatLogIdxPair > getDateIdxs(const QDate &startDate, size_t maxDates) const override
Gets indexes for each new date starting at startDate.
Definition: chathistory.cpp:186
SearchPos::logIdx
ChatLogIdx logIdx
Definition: ichatlog.h:44
ChatHistory::searchBackward
SearchResult searchBackward(SearchPos startIdx, const QString &phrase, const ParameterSearch &parameter) const override
searches backwards through the chat log until phrase is found according to parameter
Definition: chathistory.cpp:138
IMessageDispatcher::messageBroken
void messageBroken(DispatchedMessageId id, BrokenMessageReason reason)
ChatHistory::getInitialChatLogIdx
ChatLogIdx getInitialChatLogIdx() const
Gets the initial chat log index for a sessionChatLog with 0 items loaded from history....
Definition: chathistory.cpp:521
ChatHistory::onMessageComplete
void onMessageComplete(DispatchedMessageId id)
Definition: chathistory.cpp:303
Message
Definition: message.h:52
History::HistMessage
Definition: history.h:139
SearchResult
Definition: ichatlog.h:70
SearchResult::found
bool found
Definition: ichatlog.h:72
ChatLogFile
Definition: chatlogitem.h:36
MessageState::pending
@ pending
ChatHistory::dispatchUnsentMessages
void dispatchUnsentMessages(IMessageDispatcher &messageDispatcher)
Sends any unsent messages in history to the underlying message dispatcher.
Definition: chathistory.cpp:426