From ceb899b69bc02ab4d692781ba65f7228bb170271 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 22 Aug 2014 11:41:39 +0400 Subject: [PATCH] ctrl+pageup/pagedown/tab/shift+tab now work in search results --- Telegram/SourceFiles/dialogswidget.cpp | 145 ++++++++++++++++++------- Telegram/SourceFiles/dialogswidget.h | 17 +-- Telegram/SourceFiles/historywidget.cpp | 22 +++- Telegram/SourceFiles/mainwidget.cpp | 22 ++-- Telegram/SourceFiles/mainwidget.h | 4 +- 5 files changed, 149 insertions(+), 61 deletions(-) diff --git a/Telegram/SourceFiles/dialogswidget.cpp b/Telegram/SourceFiles/dialogswidget.cpp index 32d98c263..2a53c27d8 100644 --- a/Telegram/SourceFiles/dialogswidget.cpp +++ b/Telegram/SourceFiles/dialogswidget.cpp @@ -26,7 +26,7 @@ Copyright (c) 2014 John Preston, https://tdesktop.com #include "boxes/newgroupbox.h" DialogsListWidget::DialogsListWidget(QWidget *parent, MainWidget *main) : QWidget(parent), - dialogs(false), contactsNoDialogs(true), contacts(true), sel(0), contactSel(false), selByMouse(false), filteredSel(-1), searchedCount(0), searchedSel(-1), _state(DefaultState) { +dialogs(false), contactsNoDialogs(true), contacts(true), sel(0), contactSel(false), selByMouse(false), filteredSel(-1), searchedCount(0), searchedSel(-1), _lastSearchId(0), _state(DefaultState) { connect(main, SIGNAL(dialogToTop(const History::DialogLinks &)), this, SLOT(onDialogToTop(const History::DialogLinks &))); connect(main, SIGNAL(peerNameChanged(PeerData *, const PeerData::Names &, const PeerData::NameFirstChars &)), this, SLOT(onPeerNameChanged(PeerData *, const PeerData::Names &, const PeerData::NameFirstChars &))); connect(main, SIGNAL(peerPhotoChanged(PeerData *)), this, SLOT(onPeerPhotoChanged(PeerData *))); @@ -355,6 +355,7 @@ void DialogsListWidget::onFilterUpdate(QString newFilter, bool force) { _state = DefaultState; filterResults.clear(); searchResults.clear(); + _lastSearchId = 0; } else { QStringList::const_iterator fb = f.cbegin(), fe = f.cend(), fi; @@ -449,6 +450,7 @@ void DialogsListWidget::clearSearchResults() { } searchResults.clear(); } + _lastSearchId = 0; } void DialogsListWidget::onItemReplaced(HistoryItem *oldItem, HistoryItem *newItem) { @@ -494,6 +496,7 @@ void DialogsListWidget::searchReceived(const QVector &messages, bool for (QVector::const_iterator i = messages.cbegin(), e = messages.cend(); i != e; ++i) { HistoryItem *item = App::histories().addToBack(*i, -1); searchResults.push_back(new FakeDialogRow(item)); + _lastSearchId = item->id; } searchedCount = fullCount; if (_state == FilteredState) { @@ -588,6 +591,7 @@ void DialogsListWidget::clearFilter() { _state = DefaultState; filterResults.clear(); searchResults.clear(); + _lastSearchId = 0; filter = QString(); refresh(true); } @@ -682,7 +686,7 @@ void DialogsListWidget::selectSkip(int32 direction) { } } -void DialogsListWidget::scrollToPeer(const PeerId &peer) { +void DialogsListWidget::scrollToPeer(const PeerId &peer, MsgId msgId) { int32 fromY = -1; if (_state == DefaultState) { DialogsList::RowByPeer::const_iterator i = dialogs.list.rowByPeer.constFind(peer); @@ -694,11 +698,21 @@ void DialogsListWidget::scrollToPeer(const PeerId &peer) { fromY = (i.value()->pos + dialogs.list.count) * st::dlgHeight; } } - } else if (_state == FilteredState) { - for (int32 i = 0, c = filterResults.size(); i < c; ++i) { - if (filterResults[i]->history->peer->id == peer) { - fromY = i * st::dlgHeight; - break; + } else if (_state == FilteredState || _state == SearchedState) { + if (msgId) { + for (int32 i = 0, c = searchResults.size(); i < c; ++i) { + if (searchResults[i]->_item->history()->peer->id == peer && searchResults[i]->_item->id == msgId) { + fromY = filterResults.size() * st::dlgHeight + st::searchedBarHeight + i * st::dlgHeight; + break; + } + } + } + if (fromY < 0) { + for (int32 i = 0, c = filterResults.size(); i < c; ++i) { + if (filterResults[i]->history->peer->id == peer) { + fromY = i * st::dlgHeight; + break; + } } } } @@ -832,65 +846,115 @@ void DialogsListWidget::destroyData() { dialogs.clear(); } -PeerData *DialogsListWidget::peerBefore(const PeerData *peer) const { +void DialogsListWidget::peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const { if (_state == DefaultState) { - DialogsList::RowByPeer::const_iterator i = dialogs.list.rowByPeer.constFind(peer->id); + DialogsList::RowByPeer::const_iterator i = dialogs.list.rowByPeer.constFind(inPeer->id); if (i == dialogs.list.rowByPeer.constEnd()) { - i = contactsNoDialogs.list.rowByPeer.constFind(peer->id); + i = contactsNoDialogs.list.rowByPeer.constFind(inPeer->id); if (i == contactsNoDialogs.list.rowByPeer.cend()) { - return 0; + outPeer = 0; + outMsg = 0; + return; } if (i.value()->prev) { - return i.value()->prev->history->peer; + outPeer = i.value()->prev->history->peer; + outMsg = 0; + return; } else if (dialogs.list.count) { - return dialogs.list.end->prev->history->peer; + outPeer = dialogs.list.end->prev->history->peer; + outMsg = 0; + return; } - return 0; + outPeer = 0; + outMsg = 0; + return; } if (i.value()->prev) { - return i.value()->prev->history->peer; + outPeer = i.value()->prev->history->peer; + outMsg = 0; + return; } } else if (_state == FilteredState || _state == SearchedState) { - if (filterResults.isEmpty() || filterResults.at(0)->history->peer == peer) return 0; + if (inMsg && !searchResults.isEmpty()) { + for (SearchResults::const_iterator b = searchResults.cbegin(), i = b + 1, e = searchResults.cend(); i != e; ++i) { + if ((*i)->_item->history()->peer == inPeer && (*i)->_item->id == inMsg) { + SearchResults::const_iterator j = i - 1; + outPeer = (*j)->_item->history()->peer; + outMsg = (*j)->_item->id; + return; + } + } + } + if (filterResults.isEmpty() || filterResults.at(0)->history->peer == inPeer) { + outPeer = 0; + outMsg = 0; + return; + } for (FilteredDialogs::const_iterator b = filterResults.cbegin(), i = b + 1, e = filterResults.cend(); i != e; ++i) { - if ((*i)->history->peer == peer) { + if ((*i)->history->peer == inPeer) { FilteredDialogs::const_iterator j = i - 1; - return (*j)->history->peer; + outPeer = (*j)->history->peer; + outMsg = 0; + return; } } } - return 0; + outPeer = 0; + outMsg = 0; } -PeerData *DialogsListWidget::peerAfter(const PeerData *peer) const { +void DialogsListWidget::peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const { if (_state == DefaultState) { - DialogsList::RowByPeer::const_iterator i = dialogs.list.rowByPeer.constFind(peer->id); + DialogsList::RowByPeer::const_iterator i = dialogs.list.rowByPeer.constFind(inPeer->id); if (i == dialogs.list.rowByPeer.constEnd()) { - i = contactsNoDialogs.list.rowByPeer.constFind(peer->id); + i = contactsNoDialogs.list.rowByPeer.constFind(inPeer->id); if (i == contactsNoDialogs.list.rowByPeer.cend()) { - return 0; + outPeer = 0; + outMsg = 0; + return; } if (i.value()->next != contactsNoDialogs.list.end) { - return i.value()->next->history->peer; + outPeer = i.value()->next->history->peer; + outMsg = 0; + return; } - return 0; + outPeer = 0; + outMsg = 0; + return; } if (i.value()->next != dialogs.list.end) { - return i.value()->next->history->peer; + outPeer = i.value()->next->history->peer; + outMsg = 0; + return; } else if (contactsNoDialogs.list.count) { - return contactsNoDialogs.list.begin->history->peer; + outPeer = contactsNoDialogs.list.begin->history->peer; + outMsg = 0; + return; } } else if (_state == FilteredState || _state == SearchedState) { + if (inMsg) { + for (SearchResults::const_iterator i = searchResults.cbegin(), e = searchResults.cend(); i != e; ++i) { + if ((*i)->_item->history()->peer == inPeer && (*i)->_item->id == inMsg) { + ++i; + outPeer = (i == e) ? 0 : (*i)->_item->history()->peer; + outMsg = (i == e) ? 0 : (*i)->_item->id; + return; + } + } + } for (FilteredDialogs::const_iterator i = filterResults.cbegin(), e = filterResults.cend(); i != e; ++i) { - if ((*i)->history->peer == peer) { + if ((*i)->history->peer == inPeer) { ++i; - return (i == e) ? 0 : (*i)->history->peer; + outPeer = (i == e) ? 0 : (*i)->history->peer; + outMsg = 0; + return; } } } - return 0; + outPeer = 0; + outMsg = 0; } DialogsIndexed &DialogsListWidget::contactsList() { @@ -905,6 +969,10 @@ DialogsListWidget::SearchResults &DialogsListWidget::searchList() { return searchResults; } +MsgId DialogsListWidget::lastSearchId() const { + return _lastSearchId; +} + DialogsWidget::DialogsWidget(MainWidget *parent) : QWidget(parent) , _drawShadow(true) , dlgOffset(0) @@ -1188,6 +1256,7 @@ void DialogsWidget::searchReceived(bool fromStart, const MTPmessages_Messages &r } _searchRequest = 0; + onListScroll(); } } @@ -1214,7 +1283,7 @@ void DialogsWidget::onListScroll() { if (list.state() == DialogsListWidget::SearchedState) { DialogsListWidget::SearchResults &res(list.searchList()); if (scroll.scrollTop() > res.size() * st::dlgHeight - 2 * scroll.height()) { - onSearchMore(res.isEmpty() ? 0 : res.back()->_item->id); + onSearchMore(list.lastSearchId()); } } else if (scroll.scrollTop() > list.dialogsList().list.count * st::dlgHeight - scroll.height()) { loadDialogs(); @@ -1285,18 +1354,16 @@ void DialogsWidget::destroyData() { list.destroyData(); } -PeerData *DialogsWidget::peerBefore(const PeerData *peer) const { - return list.peerBefore(peer); +void DialogsWidget::peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const { + return list.peerBefore(inPeer, inMsg, outPeer, outMsg); } -PeerData *DialogsWidget::peerAfter(const PeerData *peer) const { - return list.peerAfter(peer); +void DialogsWidget::peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const { + return list.peerAfter(inPeer, inMsg, outPeer, outMsg); } -void DialogsWidget::scrollToPeer(const PeerId &peer) { - if (list.state() != DialogsListWidget::SearchedState) { - list.scrollToPeer(peer); - } +void DialogsWidget::scrollToPeer(const PeerId &peer, MsgId msgId) { + list.scrollToPeer(peer, msgId); } void DialogsWidget::removePeer(PeerData *peer) { diff --git a/Telegram/SourceFiles/dialogswidget.h b/Telegram/SourceFiles/dialogswidget.h index 59ef5e396..45b7a22ea 100644 --- a/Telegram/SourceFiles/dialogswidget.h +++ b/Telegram/SourceFiles/dialogswidget.h @@ -58,15 +58,16 @@ public: void destroyData(); - PeerData *peerBefore(const PeerData *peer) const; - PeerData *peerAfter(const PeerData *peer) const; - void scrollToPeer(const PeerId &peer); - + void peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const; + void peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const; + void scrollToPeer(const PeerId &peer, MsgId msgId); + typedef QVector SearchResults; DialogsIndexed &contactsList(); DialogsIndexed &dialogsList(); SearchResults &searchList(); + MsgId lastSearchId() const; void setMouseSel(bool msel, bool toTop = false); @@ -121,6 +122,8 @@ private: SearchResults searchResults; int32 searchedCount, searchedSel; + MsgId _lastSearchId; + State _state; QPoint lastMousePos; @@ -159,9 +162,9 @@ public: void destroyData(); - PeerData *peerBefore(const PeerData *peer) const; - PeerData *peerAfter(const PeerData *peer) const; - void scrollToPeer(const PeerId &peer); + void peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const; + void peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const; + void scrollToPeer(const PeerId &peer, MsgId msgId); void removePeer(PeerData *peer); void removeContact(UserData *user); diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index dcb111be9..0ccff69f7 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -2949,15 +2949,19 @@ void HistoryWidget::keyPressEvent(QKeyEvent *e) { e->ignore(); } else if (e->key() == Qt::Key_PageDown) { if ((e->modifiers() & Qt::ControlModifier) || (e->modifiers() & Qt::MetaModifier)) { - PeerData *after = App::main()->peerAfter(histPeer); - if (after) App::main()->showPeer(after->id); + PeerData *after = 0; + MsgId afterMsgId = 0; + App::main()->peerAfter(histPeer, hist ? hist->activeMsgId : 0, after, afterMsgId); + if (after) App::main()->showPeer(after->id, afterMsgId); } else { _scroll.scrollToY(_scroll.scrollTop() + _scroll.height()); } } else if (e->key() == Qt::Key_PageUp) { if ((e->modifiers() & Qt::ControlModifier) || (e->modifiers() & Qt::MetaModifier)) { - PeerData *before = App::main()->peerBefore(histPeer); - if (before) App::main()->showPeer(before->id); + PeerData *before = 0; + MsgId beforeMsgId = 0; + App::main()->peerBefore(histPeer, hist ? hist->activeMsgId : 0, before, beforeMsgId); + if (before) App::main()->showPeer(before->id, beforeMsgId); } else { _scroll.scrollToY(_scroll.scrollTop() - _scroll.height()); } @@ -2966,8 +2970,14 @@ void HistoryWidget::keyPressEvent(QKeyEvent *e) { } else if (e->key() == Qt::Key_Up) { _scroll.scrollToY(_scroll.scrollTop() - _scroll.height() / 10); } else if ((e->key() == Qt::Key_Tab || e->key() == Qt::Key_Backtab) && ((e->modifiers() & Qt::ControlModifier) || (e->modifiers() & Qt::MetaModifier))) { - PeerData *p = ((e->modifiers() & Qt::ShiftModifier) || e->key() == Qt::Key_Backtab) ? App::main()->peerBefore(histPeer) : App::main()->peerAfter(histPeer); - if (p) App::main()->showPeer(p->id); + PeerData *p = 0; + MsgId m = 0; + if ((e->modifiers() & Qt::ShiftModifier) || e->key() == Qt::Key_Backtab) { + App::main()->peerBefore(histPeer, hist ? hist->activeMsgId : 0, p, m); + } else { + App::main()->peerAfter(histPeer, hist ? hist->activeMsgId : 0, p, m); + } + if (p) App::main()->showPeer(p->id, m); } else { e->ignore(); } diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 08bb82469..4cc208f57 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -998,18 +998,26 @@ void MainWidget::showPeer(const PeerId &peerId, MsgId msgId, bool back, bool for } } } - dialogs.scrollToPeer(peerId); + dialogs.scrollToPeer(peerId, msgId); dialogs.update(); } -PeerData *MainWidget::peerBefore(const PeerData *peer) { - if (selectingPeer()) return 0; - return dialogs.peerBefore(peer); +void MainWidget::peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) { + if (selectingPeer()) { + outPeer = 0; + outMsg = 0; + return; + } + dialogs.peerBefore(inPeer, inMsg, outPeer, outMsg); } -PeerData *MainWidget::peerAfter(const PeerData *peer) { - if (selectingPeer()) return 0; - return dialogs.peerAfter(peer); +void MainWidget::peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) { + if (selectingPeer()) { + outPeer = 0; + outMsg = 0; + return; + } + dialogs.peerAfter(inPeer, inMsg, outPeer, outMsg); } PeerData *MainWidget::peer() { diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 64fcde0c2..08faa79eb 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -201,8 +201,8 @@ public: void updUpdated(int32 pts, int32 date, int32 qts, int32 seq); void historyWasRead(); - PeerData *peerBefore(const PeerData *peer); - PeerData *peerAfter(const PeerData *peer); + void peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg); + void peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg); PeerData *peer(); PeerData *activePeer(); MsgId activeMsgId();