From db7fa9ba2fc7a98bac8a9e00d8784c06c9936a91 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 20 Aug 2014 23:13:00 +0400 Subject: [PATCH] multi select in media overview done properly --- .../SourceFiles/boxes/addparticipantbox.cpp | 14 +- .../SourceFiles/boxes/addparticipantbox.h | 1 + Telegram/SourceFiles/boxes/newgroupbox.cpp | 14 +- Telegram/SourceFiles/boxes/newgroupbox.h | 1 + Telegram/SourceFiles/historywidget.cpp | 7 +- Telegram/SourceFiles/mainwidget.cpp | 4 + Telegram/SourceFiles/mainwidget.h | 1 + Telegram/SourceFiles/overviewwidget.cpp | 139 ++++++++++++++---- Telegram/SourceFiles/overviewwidget.h | 4 + Telegram/SourceFiles/window.cpp | 1 + 10 files changed, 127 insertions(+), 59 deletions(-) diff --git a/Telegram/SourceFiles/boxes/addparticipantbox.cpp b/Telegram/SourceFiles/boxes/addparticipantbox.cpp index 5659c657c..d9db93b38 100644 --- a/Telegram/SourceFiles/boxes/addparticipantbox.cpp +++ b/Telegram/SourceFiles/boxes/addparticipantbox.cpp @@ -242,18 +242,7 @@ void AddParticipantInner::chooseParticipant() { changeCheckState(row); PeerData *peer = row->history->peer; - updateFilter(); - - for (_sel = _contacts->list.begin; _sel != _contacts->list.end; _sel = _sel->next) { - if (_sel->history->peer == peer) { - break; - } - } - if (_sel == _contacts->list.end) { - _sel = 0; - } else { - emit mustScrollTo(_sel->pos * rh, (_sel->pos + 1) * rh); - } + emit selectAllQuery(); } parentWidget()->update(); } @@ -530,6 +519,7 @@ AddParticipantBox::AddParticipantBox(ChatData *chat) : connect(&_filter, SIGNAL(changed()), this, SLOT(onFilterUpdate())); connect(&_filter, SIGNAL(cancelled()), this, SIGNAL(onClose())); connect(&_inner, SIGNAL(mustScrollTo(int,int)), &_scroll, SLOT(scrollToY(int,int))); + connect(&_inner, SIGNAL(selectAllQuery()), &_filter, SLOT(selectAll())); showAll(); _cache = myGrab(this, rect()); diff --git a/Telegram/SourceFiles/boxes/addparticipantbox.h b/Telegram/SourceFiles/boxes/addparticipantbox.h index 966ab1778..8f797997b 100644 --- a/Telegram/SourceFiles/boxes/addparticipantbox.h +++ b/Telegram/SourceFiles/boxes/addparticipantbox.h @@ -50,6 +50,7 @@ public: signals: void mustScrollTo(int ymin, int ymax); + void selectAllQuery(); public slots: diff --git a/Telegram/SourceFiles/boxes/newgroupbox.cpp b/Telegram/SourceFiles/boxes/newgroupbox.cpp index a2822e94a..d93e3518c 100644 --- a/Telegram/SourceFiles/boxes/newgroupbox.cpp +++ b/Telegram/SourceFiles/boxes/newgroupbox.cpp @@ -233,18 +233,7 @@ void NewGroupInner::chooseParticipant() { changeCheckState(row); PeerData *peer = row->history->peer; - updateFilter(); - - for (_sel = _contacts->list.begin; _sel != _contacts->list.end; _sel = _sel->next) { - if (_sel->history->peer == peer) { - break; - } - } - if (_sel == _contacts->list.end) { - _sel = 0; - } else { - emit mustScrollTo(_sel->pos * rh, (_sel->pos + 1) * rh); - } + emit selectAllQuery(); } parentWidget()->update(); @@ -469,6 +458,7 @@ NewGroupBox::NewGroupBox() : _scroll(this, st::newGroupScroll), _inner(), connect(&_filter, SIGNAL(changed()), this, SLOT(onFilterUpdate())); connect(&_filter, SIGNAL(cancelled()), this, SIGNAL(onClose())); connect(&_inner, SIGNAL(mustScrollTo(int,int)), &_scroll, SLOT(scrollToY(int,int))); + connect(&_inner, SIGNAL(selectAllQuery()), &_filter, SLOT(selectAll())); showAll(); _cache = myGrab(this, rect()); diff --git a/Telegram/SourceFiles/boxes/newgroupbox.h b/Telegram/SourceFiles/boxes/newgroupbox.h index f08804f13..7cb856eca 100644 --- a/Telegram/SourceFiles/boxes/newgroupbox.h +++ b/Telegram/SourceFiles/boxes/newgroupbox.h @@ -50,6 +50,7 @@ public: signals: void mustScrollTo(int ymin, int ymax); + void selectAllQuery(); public slots: diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 138d7e00d..3cd5ac269 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -467,7 +467,7 @@ void HistoryList::itemRemoved(HistoryItem *item) { SelectedItems::iterator i = _selected.find(item); if (i != _selected.cend()) { _selected.erase(i); - update(); + historyWidget->updateTopBarSelection(); } onUpdateSelected(); @@ -475,8 +475,6 @@ void HistoryList::itemRemoved(HistoryItem *item) { if (_dragSelFrom == item) _dragSelFrom = 0; if (_dragSelTo == item) _dragSelTo = 0; updateDragSelection(_dragSelFrom, _dragSelTo, _dragSelecting, true); - - parentWidget()->update(); } void HistoryList::dragActionFinish(const QPoint &screenPos, Qt::MouseButton button) { @@ -1154,8 +1152,8 @@ void HistoryList::applyDragSelection() { HistoryBlock *block = (*hist)[fromblock]; for (int32 cnt = (fromblock < toblock) ? block->size() : (toitem + 1); fromitem < cnt; ++fromitem) { HistoryItem *item = (*block)[fromitem]; + SelectedItems::iterator i = _selected.find(item); if (item->id > 0 && !item->serviceMsg()) { - SelectedItems::iterator i = _selected.find(item); if (i == _selected.cend()) { if (_selected.size() >= MaxSelectedItems) break; _selected.insert(item, FullItemSel); @@ -1163,7 +1161,6 @@ void HistoryList::applyDragSelection() { *i = FullItemSel; } } else { - SelectedItems::iterator i = _selected.find(item); if (i != _selected.cend()) { _selected.erase(i); } diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 3f3c7e0f2..9b3cf8aa9 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -642,6 +642,10 @@ void MainWidget::mediaOverviewUpdated(PeerData *peer) { if (overview) overview->mediaOverviewUpdated(peer); } +void MainWidget::changingMsgId(HistoryItem *row, MsgId newId) { + if (overview) overview->changingMsgId(row, newId); +} + bool MainWidget::overviewFailed(PeerData *peer, const RPCError &error, mtpRequestId req) { MediaOverviewType type = OverviewCount; for (int32 i = 0; i < OverviewCount; ++i) { diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 6dc6fc966..e41b2325e 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -271,6 +271,7 @@ public: void searchMessages(const QString &query); void preloadOverviews(PeerData *peer); void mediaOverviewUpdated(PeerData *peer); + void changingMsgId(HistoryItem *row, MsgId newId); void loadMediaBack(PeerData *peer, MediaOverviewType type, bool many = false); diff --git a/Telegram/SourceFiles/overviewwidget.cpp b/Telegram/SourceFiles/overviewwidget.cpp index e1678d4cc..a16e9d5e3 100644 --- a/Telegram/SourceFiles/overviewwidget.cpp +++ b/Telegram/SourceFiles/overviewwidget.cpp @@ -161,26 +161,20 @@ bool OverviewInner::itemHasPoint(MsgId msgId, int32 index, int32 x, int32 y) con if (index < 0) return false; if (_type == OverviewPhotos) { - int32 row = (_photosToAdd + index) / _photosInRow, col = (_photosToAdd + index) % _photosInRow, vsize = _vsize + st::overviewPhotoSkip; - if (y >= _addToY + row * vsize + st::overviewPhotoSkip && y < _addToY + (row + 1) * vsize) { - float64 w = (_width - st::overviewPhotoSkip) / float64(_photosInRow); - if (x >= int32(col * w + st::overviewPhotoSkip) && x < int32(col * w + vsize)) { - return true; - } + if (x >= 0 && x < _vsize && y >= 0 && y < _vsize) { + return true; } } else { HistoryItem *item = App::histItemById(msgId); HistoryMedia *media = item ? item->getMedia(true) : 0; if (media) { int32 w = _width - st::msgMargin.left() - st::msgMargin.right(); - y -= _addToY + (_height - _items[index].y); bool out = item->out(); int32 mw = media->maxWidth(), left = (out ? st::msgMargin.right() : st::msgMargin.left()) + (out && mw < w ? (w - mw) : 0); if (!out && _hist->peer->chat) { left += st::msgPhotoSkip; } - x -= left; - return media->hasPoint(x, y, w); + return media->hasPoint(x - left, y - st::msgMargin.top(), w); } } return false; @@ -485,11 +479,17 @@ void OverviewInner::applyDragSelection() { if (!msgid) continue; SelectedItems::iterator j = _selected.find(msgid); - if (j == _selected.cend()) { - if (_selected.size() >= MaxSelectedItems) break; - _selected.insert(msgid, FullItemSel); - } else if (j.value() != FullItemSel) { - *j = FullItemSel; + if (msgid > 0) { + if (j == _selected.cend()) { + if (_selected.size() >= MaxSelectedItems) break; + _selected.insert(msgid, FullItemSel); + } else if (j.value() != FullItemSel) { + *j = FullItemSel; + } + } else { + if (j != _selected.cend()) { + _selected.erase(j); + } } } } else { @@ -514,7 +514,7 @@ QPoint OverviewInner::mapMouseToItem(QPoint p, MsgId itemId, int32 itemIndex) { if (_type == OverviewPhotos) { int32 row = (_photosToAdd + itemIndex) / _photosInRow, col = (_photosToAdd + itemIndex) % _photosInRow; float64 w = (_width - st::overviewPhotoSkip) / float64(_photosInRow); - p.setX(p.x() - col * int32(w) - st::overviewPhotoSkip); + p.setX(p.x() - int32(col * w) - st::overviewPhotoSkip); p.setY(p.y() - _addToY - row * (_vsize + st::overviewPhotoSkip) - st::overviewPhotoSkip); } else { p.setY(p.y() - _addToY - (_height - _items[itemIndex].y)); @@ -616,7 +616,7 @@ void OverviewInner::paintEvent(QPaintEvent *e) { } uint32 sel = 0; - if (count - index - 1 >= selfrom && count - index - 1 <= selto) { + if (index >= selfrom && index <= selto) { sel = (_dragSelecting && item->id > 0) ? FullItemSel : 0; } else if (hasSel) { SelectedItems::const_iterator i = _selected.constFind(item->id); @@ -713,8 +713,8 @@ void OverviewInner::onUpdateSelected() { int32 index = -1; if (_type == OverviewPhotos) { float64 w = (float64(_width - st::overviewPhotoSkip) / _photosInRow); - int32 inRow = int32(m.x() / w), vsize = (_vsize + st::overviewPhotoSkip); - int32 row = int32((m.y() - _addToY) / vsize); + int32 inRow = int32((m.x() - (st::overviewPhotoSkip / 2)) / w), vsize = (_vsize + st::overviewPhotoSkip); + int32 row = int32((m.y() - _addToY - (st::overviewPhotoSkip / 2)) / vsize); if (inRow < 0) inRow = 0; if (row < 0) row = 0; bool upon = true; @@ -761,9 +761,11 @@ void OverviewInner::onUpdateSelected() { if (i > 0 && ((y + h / 2) < m.y() || i == _items.size() - 1)) { --i; if (!_items[i].msgid) break; // wtf + y = _addToY + _height - _items[i].y; } else if (i < _items.size() - 1 && ((y + h / 2) >= m.y() || !i)) { ++i; if (!_items[i].msgid) break; // wtf + y = _addToY + _height - _items[i].y; } else { break; // wtf } @@ -816,7 +818,7 @@ void OverviewInner::onUpdateSelected() { cur = style::cur_pointer; } } else { - if (_dragItemIndex < 0 || _mousedItem < 0) { + if (_dragItemIndex < 0 || _mousedItemIndex < 0) { _dragAction = NoDrag; return; } @@ -829,28 +831,52 @@ void OverviewInner::onUpdateSelected() { } cur = textlnkDown() ? style::cur_pointer : style::cur_default; if (_dragAction == Selecting) { - bool selectingDown = (_mousedItemIndex < _dragItemIndex) || (_mousedItemIndex == _dragItemIndex && _dragStartPos.y() < m.y()); + bool selectingDown = (_type == OverviewPhotos ? (_mousedItemIndex > _dragItemIndex) : (_mousedItemIndex < _dragItemIndex)) || (_mousedItemIndex == _dragItemIndex && (_type == OverviewPhotos ? (_dragStartPos.x() < m.x()) : (_dragStartPos.y() < m.y()))); MsgId dragSelFrom = _dragItem, dragSelTo = _mousedItem; int32 dragSelFromIndex = _dragItemIndex, dragSelToIndex = _mousedItemIndex; if (!itemHasPoint(dragSelFrom, dragSelFromIndex, _dragStartPos.x(), _dragStartPos.y())) { // maybe exclude dragSelFrom if (selectingDown) { - if (_dragStartPos.y() >= ((_type == OverviewPhotos) ? _vsize : (itemHeight(dragSelFrom, dragSelFromIndex) - st::msgMargin.bottom())) || ((_mousedItem == dragSelFrom) && (m.y() < _dragStartPos.y() + QApplication::startDragDistance()))) { - moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, -1); + if (_type == OverviewPhotos) { + if (_dragStartPos.x() >= _vsize || ((_mousedItem == dragSelFrom) && (m.x() < _dragStartPos.x() + QApplication::startDragDistance()))) { + moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, 1); + } + } else { + if (_dragStartPos.y() >= (itemHeight(dragSelFrom, dragSelFromIndex) - st::msgMargin.bottom()) || ((_mousedItem == dragSelFrom) && (m.y() < _dragStartPos.y() + QApplication::startDragDistance()))) { + moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, -1); + } } } else { - if (_dragStartPos.y() < ((_type == OverviewPhotos ? 0 : st::msgMargin.top())) || ((_mousedItem == dragSelFrom) && (m.y() >= _dragStartPos.y() - QApplication::startDragDistance()))) { - moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, 1); + if (_type == OverviewPhotos) { + if (_dragStartPos.x() < 0 || ((_mousedItem == dragSelFrom) && (m.x() >= _dragStartPos.x() - QApplication::startDragDistance()))) { + moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, -1); + } + } else { + if (_dragStartPos.y() < st::msgMargin.top() || ((_mousedItem == dragSelFrom) && (m.y() >= _dragStartPos.y() - QApplication::startDragDistance()))) { + moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, 1); + } } } } if (_dragItem != _mousedItem) { // maybe exclude dragSelTo if (selectingDown) { - if (m.y() < ((_type == OverviewPhotos) ? 0 : st::msgMargin.top())) { - moveToNextItem(dragSelTo, dragSelToIndex, dragSelFrom, 1); + if (_type == OverviewPhotos) { + if (m.x() < 0) { + moveToNextItem(dragSelTo, dragSelToIndex, dragSelFrom, -1); + } + } else { + if (m.y() < st::msgMargin.top()) { + moveToNextItem(dragSelTo, dragSelToIndex, dragSelFrom, 1); + } } } else { - if (m.y() >= ((_type == OverviewPhotos) ? _vsize : (itemHeight(dragSelTo, dragSelToIndex) - st::msgMargin.bottom()))) { - moveToNextItem(dragSelTo, dragSelToIndex, dragSelFrom, -1); + if (_type == OverviewPhotos) { + if (m.x() >= _vsize) { + moveToNextItem(dragSelTo, dragSelToIndex, dragSelFrom, 1); + } + } else { + if (m.y() >= itemHeight(dragSelTo, dragSelToIndex) - st::msgMargin.bottom()) { + moveToNextItem(dragSelTo, dragSelToIndex, dragSelFrom, -1); + } } } } @@ -858,7 +884,7 @@ void OverviewInner::onUpdateSelected() { MsgId dragFirstAffected = dragSelFrom; int32 dragFirstAffectedIndex = dragSelFromIndex; while (dragFirstAffectedIndex >= 0 && dragFirstAffected <= 0) { - moveToNextItem(dragFirstAffected, dragFirstAffectedIndex, dragSelTo, selectingDown ? -1 : 1); + moveToNextItem(dragFirstAffected, dragFirstAffectedIndex, dragSelTo, ((selectingDown && (_type == OverviewPhotos)) || (!selectingDown && (_type != OverviewPhotos))) ? -1 : 1); } if (dragFirstAffectedIndex >= 0) { SelectedItems::const_iterator i = _selected.constFind(dragFirstAffected); @@ -1132,7 +1158,7 @@ void OverviewInner::fillSelectedItems(SelectedItemSet &sel, bool forDelete) { for (SelectedItems::const_iterator i = _selected.cbegin(), e = _selected.cend(); i != e; ++i) { HistoryItem *item = App::histItemById(i.key()); if (item && item->itemType() == HistoryItem::MsgType && ((item->id > 0 && !item->serviceMsg()) || forDelete)) { - sel.insert(item->y + item->block()->y, item); + sel.insert(item->id, item); } } } @@ -1251,6 +1277,53 @@ void OverviewInner::mediaOverviewUpdated() { } } +void OverviewInner::changingMsgId(HistoryItem *row, MsgId newId) { + if (_dragSelFrom == row->id) _dragSelFrom = newId; + if (_dragSelTo == row->id) _dragSelTo = newId; + if (_mousedItem == row->id) _mousedItem = newId; + if (_dragItem == row->id) _dragItem = newId; + for (SelectedItems::iterator i = _selected.begin(), e = _selected.end(); i != e; ++i) { + if (i.key() == row->id) { + uint32 sel = i.value(); + _selected.erase(i); + _selected.insert(newId, sel); + break; + } + } + for (CachedItems::iterator i = _items.begin(), e = _items.end(); i != e; ++i) { + if (i->msgid == row->id) { + i->msgid = newId; + break; + } + } +} + +void OverviewInner::itemRemoved(HistoryItem *item) { + if (_dragItem == item->id) { + dragActionCancel(); + } + + SelectedItems::iterator i = _selected.find(item->id); + if (i != _selected.cend()) { + _selected.erase(i); + _overview->updateTopBarSelection(); + } + + onUpdateSelected(); + + if (_dragSelFrom == item->id) { + _dragSelFrom = 0; + _dragSelFromIndex = -1; + } + if (_dragSelTo == item->id) { + _dragSelTo = 0; + _dragSelToIndex = -1; + } + updateDragSelection(_dragSelFrom, _dragSelFromIndex, _dragSelTo, _dragSelToIndex, _dragSelecting); + + parentWidget()->update(); +} + void OverviewInner::msgUpdated(HistoryItem *msg) { if (!msg || _hist != msg->history()) return; MsgId msgid = msg->id; @@ -1507,6 +1580,12 @@ void OverviewWidget::mediaOverviewUpdated(PeerData *p) { } } +void OverviewWidget::changingMsgId(HistoryItem *row, MsgId newId) { + if (peer() == row->history()->peer) { + _inner.changingMsgId(row, newId); + } +} + void OverviewWidget::msgUpdated(PeerId p, HistoryItem *msg) { if (peer()->id == p) { _inner.msgUpdated(msg); diff --git a/Telegram/SourceFiles/overviewwidget.h b/Telegram/SourceFiles/overviewwidget.h index 26f2059d7..bbe3084bd 100644 --- a/Telegram/SourceFiles/overviewwidget.h +++ b/Telegram/SourceFiles/overviewwidget.h @@ -56,6 +56,7 @@ public: void switchType(MediaOverviewType type); void mediaOverviewUpdated(); + void changingMsgId(HistoryItem *row, MsgId newId); void msgUpdated(HistoryItem *msg); void getSelectionState(int32 &selectedForForward, int32 &selectedForDelete) const; @@ -82,6 +83,8 @@ public slots: void onTouchSelect(); void onTouchScrollTimer(); + void itemRemoved(HistoryItem *item); + private: void fixItemIndex(int32 ¤t, MsgId msgId) const; @@ -208,6 +211,7 @@ public: bool animStep(float64 ms); void mediaOverviewUpdated(PeerData *peer); + void changingMsgId(HistoryItem *row, MsgId newId); void msgUpdated(PeerId peer, HistoryItem *msg); QPoint clampMousePosition(QPoint point); diff --git a/Telegram/SourceFiles/window.cpp b/Telegram/SourceFiles/window.cpp index fc79a3d73..206b2d9b2 100644 --- a/Telegram/SourceFiles/window.cpp +++ b/Telegram/SourceFiles/window.cpp @@ -1214,6 +1214,7 @@ void Window::mediaOverviewUpdated(PeerData *peer) { } void Window::changingMsgId(HistoryItem *row, MsgId newId) { + if (main) main->changingMsgId(row, newId); if (!_mediaView || _mediaView->isHidden()) return; _mediaView->changingMsgId(row, newId); }