ctrl+pageup/pagedown/tab/shift+tab now work in search results

This commit is contained in:
John Preston 2014-08-22 11:41:39 +04:00
parent 7bff0bcdb2
commit ceb899b69b
5 changed files with 149 additions and 61 deletions

View File

@ -26,7 +26,7 @@ Copyright (c) 2014 John Preston, https://tdesktop.com
#include "boxes/newgroupbox.h" #include "boxes/newgroupbox.h"
DialogsListWidget::DialogsListWidget(QWidget *parent, MainWidget *main) : QWidget(parent), 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(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(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 *))); connect(main, SIGNAL(peerPhotoChanged(PeerData *)), this, SLOT(onPeerPhotoChanged(PeerData *)));
@ -355,6 +355,7 @@ void DialogsListWidget::onFilterUpdate(QString newFilter, bool force) {
_state = DefaultState; _state = DefaultState;
filterResults.clear(); filterResults.clear();
searchResults.clear(); searchResults.clear();
_lastSearchId = 0;
} else { } else {
QStringList::const_iterator fb = f.cbegin(), fe = f.cend(), fi; QStringList::const_iterator fb = f.cbegin(), fe = f.cend(), fi;
@ -449,6 +450,7 @@ void DialogsListWidget::clearSearchResults() {
} }
searchResults.clear(); searchResults.clear();
} }
_lastSearchId = 0;
} }
void DialogsListWidget::onItemReplaced(HistoryItem *oldItem, HistoryItem *newItem) { void DialogsListWidget::onItemReplaced(HistoryItem *oldItem, HistoryItem *newItem) {
@ -494,6 +496,7 @@ void DialogsListWidget::searchReceived(const QVector<MTPMessage> &messages, bool
for (QVector<MTPMessage>::const_iterator i = messages.cbegin(), e = messages.cend(); i != e; ++i) { for (QVector<MTPMessage>::const_iterator i = messages.cbegin(), e = messages.cend(); i != e; ++i) {
HistoryItem *item = App::histories().addToBack(*i, -1); HistoryItem *item = App::histories().addToBack(*i, -1);
searchResults.push_back(new FakeDialogRow(item)); searchResults.push_back(new FakeDialogRow(item));
_lastSearchId = item->id;
} }
searchedCount = fullCount; searchedCount = fullCount;
if (_state == FilteredState) { if (_state == FilteredState) {
@ -588,6 +591,7 @@ void DialogsListWidget::clearFilter() {
_state = DefaultState; _state = DefaultState;
filterResults.clear(); filterResults.clear();
searchResults.clear(); searchResults.clear();
_lastSearchId = 0;
filter = QString(); filter = QString();
refresh(true); 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; int32 fromY = -1;
if (_state == DefaultState) { if (_state == DefaultState) {
DialogsList::RowByPeer::const_iterator i = dialogs.list.rowByPeer.constFind(peer); DialogsList::RowByPeer::const_iterator i = dialogs.list.rowByPeer.constFind(peer);
@ -694,7 +698,16 @@ void DialogsListWidget::scrollToPeer(const PeerId &peer) {
fromY = (i.value()->pos + dialogs.list.count) * st::dlgHeight; fromY = (i.value()->pos + dialogs.list.count) * st::dlgHeight;
} }
} }
} else if (_state == FilteredState) { } 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) { for (int32 i = 0, c = filterResults.size(); i < c; ++i) {
if (filterResults[i]->history->peer->id == peer) { if (filterResults[i]->history->peer->id == peer) {
fromY = i * st::dlgHeight; fromY = i * st::dlgHeight;
@ -702,6 +715,7 @@ void DialogsListWidget::scrollToPeer(const PeerId &peer) {
} }
} }
} }
}
if (fromY >= 0) { if (fromY >= 0) {
emit mustScrollTo(fromY, fromY + st::dlgHeight); emit mustScrollTo(fromY, fromY + st::dlgHeight);
} }
@ -832,65 +846,115 @@ void DialogsListWidget::destroyData() {
dialogs.clear(); 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) { 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()) { 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()) { if (i == contactsNoDialogs.list.rowByPeer.cend()) {
return 0; outPeer = 0;
outMsg = 0;
return;
} }
if (i.value()->prev) { if (i.value()->prev) {
return i.value()->prev->history->peer; outPeer = i.value()->prev->history->peer;
outMsg = 0;
return;
} else if (dialogs.list.count) { } 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) { 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) { } 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) { 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; 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) { 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()) { 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()) { if (i == contactsNoDialogs.list.rowByPeer.cend()) {
return 0; outPeer = 0;
outMsg = 0;
return;
} }
if (i.value()->next != contactsNoDialogs.list.end) { 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) { 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) { } 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) { } else if (_state == FilteredState || _state == SearchedState) {
for (FilteredDialogs::const_iterator i = filterResults.cbegin(), e = filterResults.cend(); i != e; ++i) { if (inMsg) {
if ((*i)->history->peer == peer) { for (SearchResults::const_iterator i = searchResults.cbegin(), e = searchResults.cend(); i != e; ++i) {
if ((*i)->_item->history()->peer == inPeer && (*i)->_item->id == inMsg) {
++i; ++i;
return (i == e) ? 0 : (*i)->history->peer; outPeer = (i == e) ? 0 : (*i)->_item->history()->peer;
outMsg = (i == e) ? 0 : (*i)->_item->id;
return;
} }
} }
} }
return 0; for (FilteredDialogs::const_iterator i = filterResults.cbegin(), e = filterResults.cend(); i != e; ++i) {
if ((*i)->history->peer == inPeer) {
++i;
outPeer = (i == e) ? 0 : (*i)->history->peer;
outMsg = 0;
return;
}
}
}
outPeer = 0;
outMsg = 0;
} }
DialogsIndexed &DialogsListWidget::contactsList() { DialogsIndexed &DialogsListWidget::contactsList() {
@ -905,6 +969,10 @@ DialogsListWidget::SearchResults &DialogsListWidget::searchList() {
return searchResults; return searchResults;
} }
MsgId DialogsListWidget::lastSearchId() const {
return _lastSearchId;
}
DialogsWidget::DialogsWidget(MainWidget *parent) : QWidget(parent) DialogsWidget::DialogsWidget(MainWidget *parent) : QWidget(parent)
, _drawShadow(true) , _drawShadow(true)
, dlgOffset(0) , dlgOffset(0)
@ -1188,6 +1256,7 @@ void DialogsWidget::searchReceived(bool fromStart, const MTPmessages_Messages &r
} }
_searchRequest = 0; _searchRequest = 0;
onListScroll();
} }
} }
@ -1214,7 +1283,7 @@ void DialogsWidget::onListScroll() {
if (list.state() == DialogsListWidget::SearchedState) { if (list.state() == DialogsListWidget::SearchedState) {
DialogsListWidget::SearchResults &res(list.searchList()); DialogsListWidget::SearchResults &res(list.searchList());
if (scroll.scrollTop() > res.size() * st::dlgHeight - 2 * scroll.height()) { 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()) { } else if (scroll.scrollTop() > list.dialogsList().list.count * st::dlgHeight - scroll.height()) {
loadDialogs(); loadDialogs();
@ -1285,18 +1354,16 @@ void DialogsWidget::destroyData() {
list.destroyData(); list.destroyData();
} }
PeerData *DialogsWidget::peerBefore(const PeerData *peer) const { void DialogsWidget::peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const {
return list.peerBefore(peer); return list.peerBefore(inPeer, inMsg, outPeer, outMsg);
} }
PeerData *DialogsWidget::peerAfter(const PeerData *peer) const { void DialogsWidget::peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const {
return list.peerAfter(peer); return list.peerAfter(inPeer, inMsg, outPeer, outMsg);
} }
void DialogsWidget::scrollToPeer(const PeerId &peer) { void DialogsWidget::scrollToPeer(const PeerId &peer, MsgId msgId) {
if (list.state() != DialogsListWidget::SearchedState) { list.scrollToPeer(peer, msgId);
list.scrollToPeer(peer);
}
} }
void DialogsWidget::removePeer(PeerData *peer) { void DialogsWidget::removePeer(PeerData *peer) {

View File

@ -58,15 +58,16 @@ public:
void destroyData(); void destroyData();
PeerData *peerBefore(const PeerData *peer) const; void peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const;
PeerData *peerAfter(const PeerData *peer) const; void peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const;
void scrollToPeer(const PeerId &peer); void scrollToPeer(const PeerId &peer, MsgId msgId);
typedef QVector<FakeDialogRow*> SearchResults; typedef QVector<FakeDialogRow*> SearchResults;
DialogsIndexed &contactsList(); DialogsIndexed &contactsList();
DialogsIndexed &dialogsList(); DialogsIndexed &dialogsList();
SearchResults &searchList(); SearchResults &searchList();
MsgId lastSearchId() const;
void setMouseSel(bool msel, bool toTop = false); void setMouseSel(bool msel, bool toTop = false);
@ -121,6 +122,8 @@ private:
SearchResults searchResults; SearchResults searchResults;
int32 searchedCount, searchedSel; int32 searchedCount, searchedSel;
MsgId _lastSearchId;
State _state; State _state;
QPoint lastMousePos; QPoint lastMousePos;
@ -159,9 +162,9 @@ public:
void destroyData(); void destroyData();
PeerData *peerBefore(const PeerData *peer) const; void peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const;
PeerData *peerAfter(const PeerData *peer) const; void peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const;
void scrollToPeer(const PeerId &peer); void scrollToPeer(const PeerId &peer, MsgId msgId);
void removePeer(PeerData *peer); void removePeer(PeerData *peer);
void removeContact(UserData *user); void removeContact(UserData *user);

View File

@ -2949,15 +2949,19 @@ void HistoryWidget::keyPressEvent(QKeyEvent *e) {
e->ignore(); e->ignore();
} else if (e->key() == Qt::Key_PageDown) { } else if (e->key() == Qt::Key_PageDown) {
if ((e->modifiers() & Qt::ControlModifier) || (e->modifiers() & Qt::MetaModifier)) { if ((e->modifiers() & Qt::ControlModifier) || (e->modifiers() & Qt::MetaModifier)) {
PeerData *after = App::main()->peerAfter(histPeer); PeerData *after = 0;
if (after) App::main()->showPeer(after->id); MsgId afterMsgId = 0;
App::main()->peerAfter(histPeer, hist ? hist->activeMsgId : 0, after, afterMsgId);
if (after) App::main()->showPeer(after->id, afterMsgId);
} else { } else {
_scroll.scrollToY(_scroll.scrollTop() + _scroll.height()); _scroll.scrollToY(_scroll.scrollTop() + _scroll.height());
} }
} else if (e->key() == Qt::Key_PageUp) { } else if (e->key() == Qt::Key_PageUp) {
if ((e->modifiers() & Qt::ControlModifier) || (e->modifiers() & Qt::MetaModifier)) { if ((e->modifiers() & Qt::ControlModifier) || (e->modifiers() & Qt::MetaModifier)) {
PeerData *before = App::main()->peerBefore(histPeer); PeerData *before = 0;
if (before) App::main()->showPeer(before->id); MsgId beforeMsgId = 0;
App::main()->peerBefore(histPeer, hist ? hist->activeMsgId : 0, before, beforeMsgId);
if (before) App::main()->showPeer(before->id, beforeMsgId);
} else { } else {
_scroll.scrollToY(_scroll.scrollTop() - _scroll.height()); _scroll.scrollToY(_scroll.scrollTop() - _scroll.height());
} }
@ -2966,8 +2970,14 @@ void HistoryWidget::keyPressEvent(QKeyEvent *e) {
} else if (e->key() == Qt::Key_Up) { } else if (e->key() == Qt::Key_Up) {
_scroll.scrollToY(_scroll.scrollTop() - _scroll.height() / 10); _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))) { } 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); PeerData *p = 0;
if (p) App::main()->showPeer(p->id); 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 { } else {
e->ignore(); e->ignore();
} }

View File

@ -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(); dialogs.update();
} }
PeerData *MainWidget::peerBefore(const PeerData *peer) { void MainWidget::peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) {
if (selectingPeer()) return 0; if (selectingPeer()) {
return dialogs.peerBefore(peer); outPeer = 0;
outMsg = 0;
return;
}
dialogs.peerBefore(inPeer, inMsg, outPeer, outMsg);
} }
PeerData *MainWidget::peerAfter(const PeerData *peer) { void MainWidget::peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) {
if (selectingPeer()) return 0; if (selectingPeer()) {
return dialogs.peerAfter(peer); outPeer = 0;
outMsg = 0;
return;
}
dialogs.peerAfter(inPeer, inMsg, outPeer, outMsg);
} }
PeerData *MainWidget::peer() { PeerData *MainWidget::peer() {

View File

@ -201,8 +201,8 @@ public:
void updUpdated(int32 pts, int32 date, int32 qts, int32 seq); void updUpdated(int32 pts, int32 date, int32 qts, int32 seq);
void historyWasRead(); void historyWasRead();
PeerData *peerBefore(const PeerData *peer); void peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg);
PeerData *peerAfter(const PeerData *peer); void peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg);
PeerData *peer(); PeerData *peer();
PeerData *activePeer(); PeerData *activePeer();
MsgId activeMsgId(); MsgId activeMsgId();