34 struct MessageDateAdaptor
36 static const QDateTime invalidDateTime;
37 MessageDateAdaptor(
const std::pair<const ChatLogIdx, ChatLogItem>& item)
39 ? item.second.getContentAsMessage().
message.timestamp
43 MessageDateAdaptor(
const QDateTime& timestamp)
44 : timestamp(timestamp)
47 const QDateTime& timestamp;
50 const QDateTime MessageDateAdaptor::invalidDateTime;
57 QRegularExpression getRegexpForPhrase(
const QString& phrase,
FilterSearch filter)
59 constexpr
auto regexFlags = QRegularExpression::UseUnicodePropertiesOption;
60 constexpr
auto caseInsensitiveFlags = QRegularExpression::CaseInsensitiveOption;
64 return QRegularExpression(QRegularExpression::escape(phrase), regexFlags);
67 caseInsensitiveFlags);
71 return QRegularExpression(phrase, regexFlags);
73 return QRegularExpression(phrase, caseInsensitiveFlags);
75 return QRegularExpression(QRegularExpression::escape(phrase), caseInsensitiveFlags);
97 std::map<ChatLogIdx, ChatLogItem>::const_iterator
98 firstItemAfterDate(QDate date,
const std::map<ChatLogIdx, ChatLogItem>& items)
100 #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
101 return std::lower_bound(items.begin(), items.end(), QDateTime(date.startOfDay()),
103 return std::lower_bound(items.begin(), items.end(), QDateTime(date),
105 [](
const MessageDateAdaptor& a, MessageDateAdaptor
const& b) {
106 return a.timestamp.date() < b.timestamp.date();
110 QString resolveToxPk(
const ToxPk& pk)
118 QString res = it->resolveToxPk(pk);
119 if (!res.isEmpty()) {
129 : coreIdHandler(coreIdHandler)
136 : coreIdHandler(coreIdHandler)
137 , nextIdx(initialIdx)
147 return isSelf ? myNickName : resolveToxPk(sender);
152 auto item =
items.find(idx);
153 if (item ==
items.end()) {
169 auto currentPos = startPos;
171 auto regexp = getRegexpForPhrase(phrase, parameter.
filter);
173 for (
auto it =
items.find(currentPos.logIdx); it !=
items.end(); ++it) {
174 const auto& key = it->first;
175 const auto& item = it->second;
181 const auto& content = item.getContentAsMessage();
183 auto match = regexp.globalMatch(content.message.content, 0);
186 QRegularExpressionMatch lastMatch;
187 while (match.isValid() && numMatches <=
static_cast<int>(currentPos.numMatches) && match.hasNext()) {
188 lastMatch = match.next();
192 if (numMatches >
static_cast<int>(currentPos.numMatches)) {
197 res.
start = lastMatch.capturedStart();
198 res.
len = lastMatch.capturedLength();
204 currentPos.numMatches = 0;
216 auto currentPos = startPos;
217 auto regexp = getRegexpForPhrase(phrase, parameter.
filter);
218 auto startIt =
items.find(currentPos.logIdx);
221 if (startIt ==
items.end()) {
227 startIt = std::prev(
items.end());
232 auto rStartIt = std::reverse_iterator<decltype(startIt)>(std::next(startIt));
233 auto rEnd = std::reverse_iterator<decltype(startIt)>(
items.begin());
235 for (
auto it = rStartIt; it != rEnd; ++it) {
236 const auto& key = it->first;
237 const auto& item = it->second;
243 const auto& content = item.getContentAsMessage();
244 auto match = regexp.globalMatch(content.message.content, 0);
246 auto totalMatches = 0;
247 auto numMatchesBeforePos = 0;
248 QRegularExpressionMatch lastMatch;
249 while (match.isValid() && match.hasNext()) {
250 auto currentMatch = match.next();
252 if (currentPos.numMatches == 0 ||
static_cast<int>(currentPos.numMatches) > numMatchesBeforePos) {
253 lastMatch = currentMatch;
254 numMatchesBeforePos++;
258 if ((numMatchesBeforePos <
static_cast<int>(currentPos.numMatches) || currentPos.numMatches == 0)
259 && numMatchesBeforePos > 0) {
264 res.
start = lastMatch.capturedStart();
265 res.
len = lastMatch.capturedLength();
271 currentPos.numMatches = 0;
286 return items.begin()->first;
295 size_t maxDates)
const
297 std::vector<DateChatLogIdxPair> ret;
298 auto dateIt = startDate;
301 auto it = firstItemAfterDate(dateIt,
items);
303 if (it ==
items.end()) {
309 pair.
idx = it->first;
311 ret.push_back(std::move(pair));
313 dateIt = dateIt.addDays(1);
314 if (startDate.daysTo(dateIt) >
static_cast<long>(maxDates) && maxDates != 0) {
338 items.emplace(idx, std::move(item));
349 items.emplace(idx, std::move(item));
360 items.emplace(idx, std::move(item));
367 items.emplace(idx, std::move(item));
374 items.emplace(idx, std::move(item));
422 qWarning() <<
"Failed to find outgoing message";
426 const auto& chatLogIdx = *chatLogIdxIt;
427 auto messageIt =
items.find(chatLogIdx);
429 if (messageIt ==
items.end()) {
430 qWarning() <<
"Failed to look up message in chat log";
444 qWarning() <<
"Failed to find outgoing message";
448 const auto& chatLogIdx = *chatLogIdxIt;
449 auto messageIt =
items.find(chatLogIdx);
451 if (messageIt ==
items.end()) {
452 qWarning() <<
"Failed to look up message in chat log";
481 const auto chatLogFile =
ChatLogFile{QDateTime::currentDateTime(),
file};
483 messageIdx = currentTransfer.
idx;
485 messageIdx = fileIt->idx;
488 items.at(messageIdx).getContentAsFile().file =
file;
494 if (toxFileIsComplete(
file.status)) {