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"
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<MTPMessage> &messages, bool
for (QVector<MTPMessage>::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) {

View File

@ -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<FakeDialogRow*> 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);

View File

@ -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();
}

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();
}
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() {

View File

@ -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();