From e3c35c9153cd5f843848eadea47a969b83da33da Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Tue, 20 Aug 2019 15:17:46 +0300 Subject: [PATCH 1/5] fix: data validation during the search (fix: #5791, #5723) --- src/model/chathistory.cpp | 18 ++++++++++++------ src/widget/form/genericchatform.cpp | 9 ++++++++- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/model/chathistory.cpp b/src/model/chathistory.cpp index 24096f710..82798a70b 100644 --- a/src/model/chathistory.cpp +++ b/src/model/chathistory.cpp @@ -174,13 +174,19 @@ SearchResult ChatHistory::searchBackward(SearchPos startIdx, const QString& phra history->getDateWhereFindPhrase(f.getPublicKey().toString(), earliestMessageDate, phrase, parameter); - auto loadIdx = history->getNumMessagesForFriendBeforeDate(f.getPublicKey(), dateWherePhraseFound); - loadHistoryIntoSessionChatLog(ChatLogIdx(loadIdx)); + if (dateWherePhraseFound.isValid()) { + auto loadIdx = history->getNumMessagesForFriendBeforeDate(f.getPublicKey(), dateWherePhraseFound); + loadHistoryIntoSessionChatLog(ChatLogIdx(loadIdx)); - // Reset search pos to the message we just loaded to avoid a double search - startIdx.logIdx = ChatLogIdx(loadIdx); - startIdx.numMatches = 0; - return sessionChatLog.searchBackward(startIdx, phrase, parameter); + // Reset search pos to the message we just loaded to avoid a double search + startIdx.logIdx = ChatLogIdx(loadIdx); + startIdx.numMatches = 0; + return sessionChatLog.searchBackward(startIdx, phrase, parameter); + } + + SearchResult ret; + ret.found = false; + return ret; } ChatLogIdx ChatHistory::getFirstIdx() const diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp index b1b883cd8..102854b2b 100644 --- a/src/widget/form/genericchatform.cpp +++ b/src/widget/form/genericchatform.cpp @@ -992,7 +992,13 @@ void GenericChatForm::onSearchUp(const QString& phrase, const ParameterSearch& p void GenericChatForm::onSearchDown(const QString& phrase, const ParameterSearch& parameter) { - auto result = chatLog.searchForward(searchPos, phrase, parameter); + auto result = chatLog.searchForward(searchPos, phrase, parameter); + + if (result.found && result.pos.logIdx.get() > messages.end()->first.get()) { + const auto dt = chatLog.at(result.pos.logIdx).getTimestamp(); + loadHistory(dt, LoadHistoryDialog::from); + } + handleSearchResult(result, SearchDirection::Down); } @@ -1014,6 +1020,7 @@ void GenericChatForm::handleSearchResult(SearchResult result, SearchDirection di chatWidget->scrollToLine(msg); auto text = qobject_cast(msg->getContent(1)); + text->visibilityChanged(true); text->selectText(result.exp, std::make_pair(result.start, result.len)); }); } From 76679de2e09a0a5abae794289bdce15f2871f9e4 Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Wed, 21 Aug 2019 15:30:17 +0300 Subject: [PATCH 2/5] feat: check chat status before start a search --- src/widget/form/genericchatform.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp index 102854b2b..1a99b1253 100644 --- a/src/widget/form/genericchatform.cpp +++ b/src/widget/form/genericchatform.cpp @@ -940,7 +940,17 @@ void GenericChatForm::onSearchTriggered() void GenericChatForm::searchInBegin(const QString& phrase, const ParameterSearch& parameter) { - disableSearchText(); + if (phrase.isEmpty()) { + disableSearchText(); + + return; + } + + if (chatLog.getNextIdx().get() == messages.rbegin()->first.get() + 1) { + disableSearchText(); + } else { + goToCurrentDate(); + } if (!parameter.time.isNull()) { LoadHistoryDialog::LoadType type = (parameter.period == PeriodSearch::BeforeDate) @@ -992,7 +1002,7 @@ void GenericChatForm::onSearchUp(const QString& phrase, const ParameterSearch& p void GenericChatForm::onSearchDown(const QString& phrase, const ParameterSearch& parameter) { - auto result = chatLog.searchForward(searchPos, phrase, parameter); + auto result = chatLog.searchForward(searchPos, phrase, parameter); if (result.found && result.pos.logIdx.get() > messages.end()->first.get()) { const auto dt = chatLog.at(result.pos.logIdx).getTimestamp(); From a6a0481ddccfddbc2237c067c709d4a3d8d28612 Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Thu, 22 Aug 2019 15:11:18 +0300 Subject: [PATCH 3/5] feat: save selected search text after scrolling up --- src/chatlog/chatlog.cpp | 2 +- src/model/ichatlog.h | 2 +- src/widget/form/genericchatform.cpp | 50 +++++++++++++++++------------ src/widget/form/genericchatform.h | 3 +- 4 files changed, 33 insertions(+), 24 deletions(-) diff --git a/src/chatlog/chatlog.cpp b/src/chatlog/chatlog.cpp index 5dd113365..6258a2f39 100644 --- a/src/chatlog/chatlog.cpp +++ b/src/chatlog/chatlog.cpp @@ -683,7 +683,7 @@ void ChatLog::scrollToLine(ChatLine::Ptr line) workerStb = false; } else { updateSceneRect(); - verticalScrollBar()->setValue(line->sceneBoundingRect().top()); // NOTE: start here + verticalScrollBar()->setValue(line->sceneBoundingRect().top()); } } diff --git a/src/model/ichatlog.h b/src/model/ichatlog.h index 2144c2d0d..a4928e9f2 100644 --- a/src/model/ichatlog.h +++ b/src/model/ichatlog.h @@ -70,7 +70,7 @@ struct SearchPos struct SearchResult { - bool found; + bool found{false}; SearchPos pos; size_t start; size_t len; diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp index 1a99b1253..b8b6a103a 100644 --- a/src/widget/form/genericchatform.cpp +++ b/src/widget/form/genericchatform.cpp @@ -685,7 +685,11 @@ void GenericChatForm::loadHistoryTo(const QDateTime &time) } if (begin != end) { - renderMessages(begin, end); + if (searchResult.found == true) { + renderMessages(begin, searchResult.pos.logIdx, [this]{enableSearchText();}); + } else { + renderMessages(begin, end); + } } else { chatWidget->setScroll(true); } @@ -730,13 +734,23 @@ void GenericChatForm::removeLastsMessages(const int num) void GenericChatForm::disableSearchText() { - auto msgIt = messages.find(searchPos.logIdx); + auto msgIt = messages.find(searchResult.pos.logIdx); if (msgIt != messages.end()) { auto text = qobject_cast(msgIt->second->getContent(1)); text->deselectText(); } } +void GenericChatForm::enableSearchText() +{ + auto msg = messages.at(searchResult.pos.logIdx); + chatWidget->scrollToLine(msg); + + auto text = qobject_cast(msg->getContent(1)); + text->visibilityChanged(true); + text->selectText(searchResult.exp, std::make_pair(searchResult.start, searchResult.len)); +} + void GenericChatForm::clearChatArea() { clearChatArea(/* confirm = */ true, /* inform = */ true); @@ -933,6 +947,7 @@ void GenericChatForm::onExportChat() void GenericChatForm::onSearchTriggered() { if (searchForm->isHidden()) { + searchResult.found = false; searchForm->removeSearchPhrase(); } disableSearchText(); @@ -962,27 +977,27 @@ void GenericChatForm::searchInBegin(const QString& phrase, const ParameterSearch switch (parameter.period) { case PeriodSearch::WithTheFirst: { bForwardSearch = true; - searchPos.logIdx = chatLog.getFirstIdx(); - searchPos.numMatches = 0; + searchResult.pos.logIdx = chatLog.getFirstIdx(); + searchResult.pos.numMatches = 0; break; } case PeriodSearch::WithTheEnd: case PeriodSearch::None: { bForwardSearch = false; - searchPos.logIdx = chatLog.getNextIdx(); - searchPos.numMatches = 0; + searchResult.pos.logIdx = chatLog.getNextIdx(); + searchResult.pos.numMatches = 0; break; } case PeriodSearch::AfterDate: { bForwardSearch = true; - searchPos.logIdx = firstItemAfterDate(parameter.time.date(), chatLog); - searchPos.numMatches = 0; + searchResult.pos.logIdx = firstItemAfterDate(parameter.time.date(), chatLog); + searchResult.pos.numMatches = 0; break; } case PeriodSearch::BeforeDate: { bForwardSearch = false; - searchPos.logIdx = firstItemAfterDate(parameter.time.date(), chatLog); - searchPos.numMatches = 0; + searchResult.pos.logIdx = firstItemAfterDate(parameter.time.date(), chatLog); + searchResult.pos.numMatches = 0; break; } } @@ -996,13 +1011,13 @@ void GenericChatForm::searchInBegin(const QString& phrase, const ParameterSearch void GenericChatForm::onSearchUp(const QString& phrase, const ParameterSearch& parameter) { - auto result = chatLog.searchBackward(searchPos, phrase, parameter); + auto result = chatLog.searchBackward(searchResult.pos, phrase, parameter); handleSearchResult(result, SearchDirection::Up); } void GenericChatForm::onSearchDown(const QString& phrase, const ParameterSearch& parameter) { - auto result = chatLog.searchForward(searchPos, phrase, parameter); + auto result = chatLog.searchForward(searchResult.pos, phrase, parameter); if (result.found && result.pos.logIdx.get() > messages.end()->first.get()) { const auto dt = chatLog.at(result.pos.logIdx).getTimestamp(); @@ -1021,18 +1036,11 @@ void GenericChatForm::handleSearchResult(SearchResult result, SearchDirection di disableSearchText(); - searchPos = result.pos; + searchResult = result; auto const firstRenderedIdx = (messages.empty()) ? chatLog.getNextIdx() : messages.begin()->first; - renderMessages(searchPos.logIdx, firstRenderedIdx, [this, result] { - auto msg = messages.at(searchPos.logIdx); - chatWidget->scrollToLine(msg); - - auto text = qobject_cast(msg->getContent(1)); - text->visibilityChanged(true); - text->selectText(result.exp, std::make_pair(result.start, result.len)); - }); + renderMessages(searchResult.pos.logIdx, firstRenderedIdx, [this]{enableSearchText();}); } void GenericChatForm::renderMessage(ChatLogIdx idx) diff --git a/src/widget/form/genericchatform.h b/src/widget/form/genericchatform.h index e4cb253ba..3358de41b 100644 --- a/src/widget/form/genericchatform.h +++ b/src/widget/form/genericchatform.h @@ -156,6 +156,7 @@ protected: virtual void resizeEvent(QResizeEvent* event) final override; virtual bool eventFilter(QObject* object, QEvent* event) final override; void disableSearchText(); + void enableSearchText(); bool searchInText(const QString& phrase, const ParameterSearch& parameter, SearchDirection direction); std::pair indexForSearchInLine(const QString& txt, const QString& phrase, const ParameterSearch& parameter, SearchDirection direction); @@ -198,7 +199,7 @@ protected: IChatLog& chatLog; IMessageDispatcher& messageDispatcher; - SearchPos searchPos; + SearchResult searchResult; std::map messages; bool colorizeNames = false; }; From e2efe443fe3bdd93700536fe350f0393f9f0a49b Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Fri, 23 Aug 2019 14:07:28 +0300 Subject: [PATCH 4/5] refactor: optimize load messages during the search --- src/widget/form/genericchatform.cpp | 67 ++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 16 deletions(-) diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp index b8b6a103a..bd4593ec1 100644 --- a/src/widget/form/genericchatform.cpp +++ b/src/widget/form/genericchatform.cpp @@ -685,8 +685,8 @@ void GenericChatForm::loadHistoryTo(const QDateTime &time) } if (begin != end) { - if (searchResult.found == true) { - renderMessages(begin, searchResult.pos.logIdx, [this]{enableSearchText();}); + if (searchResult.found == true && searchResult.pos.logIdx == end) { + renderMessages(begin, end, [this]{enableSearchText();}); } else { renderMessages(begin, end); } @@ -967,12 +967,6 @@ void GenericChatForm::searchInBegin(const QString& phrase, const ParameterSearch goToCurrentDate(); } - if (!parameter.time.isNull()) { - LoadHistoryDialog::LoadType type = (parameter.period == PeriodSearch::BeforeDate) - ? LoadHistoryDialog::to : LoadHistoryDialog::from; - loadHistory(parameter.time, type); - } - bool bForwardSearch = false; switch (parameter.period) { case PeriodSearch::WithTheFirst: { @@ -1018,12 +1012,6 @@ void GenericChatForm::onSearchUp(const QString& phrase, const ParameterSearch& p void GenericChatForm::onSearchDown(const QString& phrase, const ParameterSearch& parameter) { auto result = chatLog.searchForward(searchResult.pos, phrase, parameter); - - if (result.found && result.pos.logIdx.get() > messages.end()->first.get()) { - const auto dt = chatLog.at(result.pos.logIdx).getTimestamp(); - loadHistory(dt, LoadHistoryDialog::from); - } - handleSearchResult(result, SearchDirection::Down); } @@ -1038,9 +1026,56 @@ void GenericChatForm::handleSearchResult(SearchResult result, SearchDirection di searchResult = result; - auto const firstRenderedIdx = (messages.empty()) ? chatLog.getNextIdx() : messages.begin()->first; + auto searchIdx = result.pos.logIdx; - renderMessages(searchResult.pos.logIdx, firstRenderedIdx, [this]{enableSearchText();}); + auto firstRenderedIdx = messages.begin()->first; + auto endRenderedIdx = messages.rbegin()->first; + + if (direction == SearchDirection::Up) { + if (searchIdx.get() < firstRenderedIdx.get()) { + if (searchIdx.get() > DEF_NUM_MSG_TO_LOAD / 2) { + firstRenderedIdx = ChatLogIdx(searchIdx.get() - DEF_NUM_MSG_TO_LOAD / 2); + } else { + firstRenderedIdx = ChatLogIdx(0); + } + } + + if (endRenderedIdx.get() - firstRenderedIdx.get() > DEF_NUM_MSG_TO_LOAD) { + endRenderedIdx = ChatLogIdx(firstRenderedIdx.get() + DEF_NUM_MSG_TO_LOAD); + } + } else { + if (searchIdx.get() < firstRenderedIdx.get()) { + firstRenderedIdx = searchIdx; + } + + if (firstRenderedIdx == searchIdx || searchIdx.get() > endRenderedIdx.get()) { + if (searchIdx.get() + DEF_NUM_MSG_TO_LOAD > chatLog.getNextIdx().get()) { + endRenderedIdx = chatLog.getNextIdx(); + } else { + endRenderedIdx = ChatLogIdx(searchIdx.get() + DEF_NUM_MSG_TO_LOAD); + } + } + + if (endRenderedIdx.get() - firstRenderedIdx.get() > DEF_NUM_MSG_TO_LOAD) { + if (endRenderedIdx.get() > DEF_NUM_MSG_TO_LOAD) { + firstRenderedIdx = ChatLogIdx(endRenderedIdx.get() - DEF_NUM_MSG_TO_LOAD); + } else { + firstRenderedIdx = ChatLogIdx(0); + } + } + } + + if (!messages.empty() && (firstRenderedIdx.get() < messages.begin()->first.get() + || endRenderedIdx.get() > messages.rbegin()->first.get())) { + chatWidget->clear(); + messages.clear(); + + auto mediator = endRenderedIdx; + endRenderedIdx = firstRenderedIdx; + firstRenderedIdx = mediator; + } + + renderMessages(endRenderedIdx, firstRenderedIdx, [this]{enableSearchText();}); } void GenericChatForm::renderMessage(ChatLogIdx idx) From dedbd184b0df6bc708a2274231d288dae2f22c81 Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Fri, 23 Aug 2019 16:48:21 +0300 Subject: [PATCH 5/5] fix: update workerStb --- src/chatlog/chatlog.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/chatlog/chatlog.cpp b/src/chatlog/chatlog.cpp index 6258a2f39..face3aa8d 100644 --- a/src/chatlog/chatlog.cpp +++ b/src/chatlog/chatlog.cpp @@ -936,10 +936,12 @@ void ChatLog::onWorkerTimeout() updateMultiSelectionRect(); // scroll - if (workerStb) + if (workerStb) { scrollToBottom(); - else + workerStb = false; + } else { scrollToLine(workerAnchorLine); + } // don't keep a Ptr to the anchor line workerAnchorLine = ChatLine::Ptr();