diff --git a/Telegram/Resources/lang.txt b/Telegram/Resources/lang.txt index e43b37c7c..7d51dd799 100644 --- a/Telegram/Resources/lang.txt +++ b/Telegram/Resources/lang.txt @@ -241,9 +241,9 @@ lng_profile_no_media: "No media in this conversation."; lng_profile_photo: "{count} photo »"; lng_profile_photos: "{count} photos »"; lng_profile_photos_header: "Photos overview"; -lng_profile_video: "{count} videofile »"; -lng_profile_videos: "{count} videofiles »"; -lng_profile_videos_header: "Videofiles overview"; +lng_profile_video: "{count} video file »"; +lng_profile_videos: "{count} video files »"; +lng_profile_videos_header: "Video files overview"; lng_profile_document: "{count} document »"; lng_profile_documents: "{count} documents »"; lng_profile_documents_header: "Documents overview"; @@ -288,21 +288,27 @@ lng_action_checked_in: "{from} checked in"; lng_forwarded_from: "Forwarded from "; lng_attach_failed: "Failed"; -lng_attach_file: "File"; +lng_attach_file: "Document"; lng_attach_photo: "Photo"; +lng_media_type: "Media type"; +lng_media_type_photos: "Photos"; +lng_media_type_videos: "Video files"; +lng_media_type_documents: "Documents"; +lng_media_type_audios: "Voice messages"; + lng_media_open_with: "Open With"; lng_media_download: "Download"; lng_media_cancel: "Cancel"; -lng_media_video: "Video"; -lng_media_audio: "Audio"; +lng_media_video: "Video file"; +lng_media_audio: "Voice message"; lng_in_dlg_photo: "Photo"; lng_in_dlg_video: "Video"; lng_in_dlg_geo: "Map"; lng_in_dlg_contact: "Contact"; lng_in_dlg_audio: "Audio"; -lng_in_dlg_document: "File"; +lng_in_dlg_document: "Document"; lng_send_button: "Send"; lng_message_ph: "Write a message..."; diff --git a/Telegram/Resources/style.txt b/Telegram/Resources/style.txt index 9d6073fe8..ea297c726 100644 --- a/Telegram/Resources/style.txt +++ b/Telegram/Resources/style.txt @@ -1303,6 +1303,20 @@ dropdownAttachPhoto: iconedButton(dropdownAttachDocument) { icon: sprite(113px, 0px, 24px, 24px); downIcon: sprite(113px, 0px, 24px, 24px); } +dropdownMediaPhotos: iconedButton(dropdownAttachPhoto) { + width: 200px; +} +dropdownMediaVideos: iconedButton(dropdownMediaPhotos) { + icon: sprite(79px, 348px, 24px, 24px); + downIcon: sprite(79px, 348px, 24px, 24px); +} +dropdownMediaDocuments: iconedButton(dropdownAttachDocument) { + width: 200px; +} +dropdownMediaAudios: iconedButton(dropdownMediaDocuments) { + icon: sprite(49px, 348px, 24px, 24px); + downIcon: sprite(49px, 348px, 24px, 24px); +} dragFont: font(28px semibold); dragSubfont: font(20px semibold); diff --git a/Telegram/SourceFiles/art/sprite.png b/Telegram/SourceFiles/art/sprite.png index dd716c3f6..1a270bcaf 100644 Binary files a/Telegram/SourceFiles/art/sprite.png and b/Telegram/SourceFiles/art/sprite.png differ diff --git a/Telegram/SourceFiles/art/sprite_200x.png b/Telegram/SourceFiles/art/sprite_200x.png index cac720556..b0030a2b9 100644 Binary files a/Telegram/SourceFiles/art/sprite_200x.png and b/Telegram/SourceFiles/art/sprite_200x.png differ diff --git a/Telegram/SourceFiles/dialogswidget.cpp b/Telegram/SourceFiles/dialogswidget.cpp index eb35b0acc..32d98c263 100644 --- a/Telegram/SourceFiles/dialogswidget.cpp +++ b/Telegram/SourceFiles/dialogswidget.cpp @@ -461,7 +461,7 @@ void DialogsListWidget::onItemReplaced(HistoryItem *oldItem, HistoryItem *newIte void DialogsListWidget::onItemRemoved(HistoryItem *item) { int wasCount = searchResults.size(); - for (int i = 0; i < searchResults.size(); ++i) { + for (int i = 0; i < searchResults.size();) { if (searchResults[i]->_item == item) { searchResults.remove(i); } else { diff --git a/Telegram/SourceFiles/dropdown.cpp b/Telegram/SourceFiles/dropdown.cpp index a1b50545a..25664b1cc 100644 --- a/Telegram/SourceFiles/dropdown.cpp +++ b/Telegram/SourceFiles/dropdown.cpp @@ -24,9 +24,7 @@ Copyright (c) 2014 John Preston, https://tdesktop.com Dropdown::Dropdown(QWidget *parent) : TWidget(parent), _hiding(false), a_opacity(0), _shadow(st::dropdownShadow) { - _width = st::dropdownPadding.left() + st::dropdownPadding.right(); - _height = st::dropdownPadding.top() + st::dropdownPadding.bottom(); - resize(_width, _height); + resetButtons(); _hideTimer.setSingleShot(true); connect(&_hideTimer, SIGNAL(timeout()), this, SLOT(hideStart())); @@ -48,6 +46,16 @@ IconedButton *Dropdown::addButton(IconedButton *button) { return button; } +void Dropdown::resetButtons() { + _width = st::dropdownPadding.left() + st::dropdownPadding.right(); + _height = st::dropdownPadding.top() + st::dropdownPadding.bottom(); + resize(_width, _height); + for (int32 i = 0, l = _buttons.size(); i < l; ++i) { + delete _buttons[i]; + } + _buttons.clear(); +} + void Dropdown::resizeEvent(QResizeEvent *e) { int32 top = st::dropdownPadding.top(); for (Buttons::const_iterator i = _buttons.cbegin(), e = _buttons.cend(); i != e; ++i) { diff --git a/Telegram/SourceFiles/dropdown.h b/Telegram/SourceFiles/dropdown.h index 92b46d9f1..797551721 100644 --- a/Telegram/SourceFiles/dropdown.h +++ b/Telegram/SourceFiles/dropdown.h @@ -28,6 +28,7 @@ public: Dropdown(QWidget *parent); IconedButton *addButton(IconedButton *button); + void resetButtons(); void resizeEvent(QResizeEvent *e); void paintEvent(QPaintEvent *e); diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h index 2e321c166..5f6cf59ac 100644 --- a/Telegram/SourceFiles/history.h +++ b/Telegram/SourceFiles/history.h @@ -126,15 +126,15 @@ struct PeerData { class PeerLink : public ITextLink { public: - PeerLink(const PeerData *peer) : _peer(peer) { + PeerLink(PeerData *peer) : _peer(peer) { } void onClick(Qt::MouseButton button) const; - const PeerData *peer() const { + PeerData *peer() const { return _peer; } private: - const PeerData *_peer; + PeerData *_peer; }; struct PhotoData; diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 3cd5ac269..dcb111be9 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -241,6 +241,10 @@ void HistoryList::touchEvent(QTouchEvent *e) { switch (e->type()) { case QEvent::TouchBegin: + if (_menu) { + e->accept(); + return; // ignore mouse press, that was hiding context menu + } if (_touchInProgress) return; if (e->touchPoints().isEmpty()) return; diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 9b3cf8aa9..08bb82469 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -34,7 +34,8 @@ TopBarWidget::TopBarWidget(MainWidget *w) : QWidget(w), _edit(this, lang(lng_profile_edit_contact), st::topBarButton), _leaveGroup(this, lang(lng_profile_delete_and_exit), st::topBarButton), _addContact(this, lang(lng_profile_add_contact), st::topBarButton), - _deleteContact(this, lang(lng_profile_delete_contact), st::topBarButton) { + _deleteContact(this, lang(lng_profile_delete_contact), st::topBarButton), + _mediaType(this, lang(lng_media_type), st::topBarButton) { connect(&_forward, SIGNAL(clicked()), this, SLOT(onForwardSelection())); connect(&_delete, SIGNAL(clicked()), this, SLOT(onDeleteSelection())); @@ -178,6 +179,7 @@ void TopBarWidget::resizeEvent(QResizeEvent *e) { if (!_leaveGroup.isHidden()) _leaveGroup.move(r -= _leaveGroup.width(), 0); if (!_edit.isHidden()) _edit.move(r -= _edit.width(), 0); if (!_addContact.isHidden()) _addContact.move(r -= _addContact.width(), 0); + if (!_mediaType.isHidden()) _mediaType.move(r -= _mediaType.width(), 0); } void TopBarWidget::startAnim() { @@ -188,6 +190,7 @@ void TopBarWidget::startAnim() { _clearSelection.hide(); _delete.hide(); _forward.hide(); + _mediaType.hide(); _animating = true; } @@ -226,6 +229,7 @@ void TopBarWidget::showAll() { _clearSelection.hide(); _delete.hide(); _forward.hide(); + _mediaType.hide(); } else { _edit.hide(); _leaveGroup.hide(); @@ -235,10 +239,16 @@ void TopBarWidget::showAll() { _clearSelection.show(); _delete.show(); _forward.show(); + _mediaType.hide(); } else { _clearSelection.hide(); _delete.hide(); _forward.hide(); + if (App::main() && App::main()->mediaTypeSwitch()) { + _mediaType.show(); + } else { + _mediaType.hide(); + } } } resizeEvent(0); @@ -253,13 +263,17 @@ void TopBarWidget::showSelected(uint32 selCount) { showAll(); } +FlatButton *TopBarWidget::mediaTypeButton() { + return &_mediaType; +} + MainWidget *TopBarWidget::main() { return static_cast<MainWidget*>(parentWidget()); } MainWidget::MainWidget(Window *window) : QWidget(window), failedObjId(0), _dialogsWidth(st::dlgMinWidth), - dialogs(this), history(this), profile(0), overview(0), _topBar(this), hider(0), - updPts(0), updDate(0), updQts(0), updSeq(0), updInited(false), onlineRequest(0) { +dialogs(this), history(this), profile(0), overview(0), _topBar(this), hider(0), _mediaType(this), _mediaTypeMask(0), + updPts(0), updDate(0), updQts(0), updSeq(0), updInited(false), onlineRequest(0) { setGeometry(QRect(0, st::titleHeight, App::wnd()->width(), App::wnd()->height() - st::titleHeight)); connect(window, SIGNAL(resized(const QSize &)), this, SLOT(onParentResize(const QSize &))); @@ -286,9 +300,13 @@ MainWidget::MainWidget(Window *window) : QWidget(window), failedObjId(0), _dialo _topBar.raise(); dialogs.raise(); + _mediaType.raise(); MTP::setGlobalFailHandler(rpcFail(&MainWidget::updateFail)); + _mediaType.hide(); + _topBar.mediaTypeButton()->installEventFilter(&_mediaType); + show(); setFocus(); } @@ -639,7 +657,35 @@ void MainWidget::overviewPreloaded(PeerData *peer, const MTPmessages_Messages &r void MainWidget::mediaOverviewUpdated(PeerData *peer) { if (profile) profile->mediaOverviewUpdated(peer); - if (overview) overview->mediaOverviewUpdated(peer); + if (overview && overview->peer() == peer) { + overview->mediaOverviewUpdated(peer); + + int32 mask = 0; + History *h = peer ? App::historyLoaded(peer->id) : 0; + if (h) { + for (int32 i = 0; i < OverviewCount; ++i) { + if (!h->_overview[i].isEmpty() || h->_overviewCount[i] > 0 || i == overview->type()) { + mask |= (1 << i); + } + } + } + if (mask != _mediaTypeMask) { + _mediaType.resetButtons(); + for (int32 i = 0; i < OverviewCount; ++i) { + if (mask & (1 << i)) { + switch (i) { + case OverviewPhotos: connect(_mediaType.addButton(new IconedButton(this, st::dropdownMediaPhotos, lang(lng_media_type_photos))), SIGNAL(clicked()), this, SLOT(onPhotosSelect())); break; + case OverviewVideos: connect(_mediaType.addButton(new IconedButton(this, st::dropdownMediaVideos, lang(lng_media_type_videos))), SIGNAL(clicked()), this, SLOT(onVideosSelect())); break; + case OverviewDocuments: connect(_mediaType.addButton(new IconedButton(this, st::dropdownMediaDocuments, lang(lng_media_type_documents))), SIGNAL(clicked()), this, SLOT(onDocumentsSelect())); break; + case OverviewAudios: connect(_mediaType.addButton(new IconedButton(this, st::dropdownMediaAudios, lang(lng_media_type_audios))), SIGNAL(clicked()), this, SLOT(onAudiosSelect())); break; + } + } + } + _mediaTypeMask = mask; + _mediaType.move(width() - _mediaType.width(), st::topBarHeight); + overview->updateTopBarSelection(); + } + } } void MainWidget::changingMsgId(HistoryItem *row, MsgId newId) { @@ -982,7 +1028,18 @@ PeerData *MainWidget::profilePeer() { return profile ? profile->peer() : 0; } -void MainWidget::showMediaOverview(const PeerData *peer, MediaOverviewType type, bool back, int32 lastScrollTop) { +bool MainWidget::mediaTypeSwitch() { + if (!overview) return false; + + for (int32 i = 0; i < OverviewCount; ++i) { + if (!(_mediaTypeMask & ~(1 << i))) { + return false; + } + } + return true; +} + +void MainWidget::showMediaOverview(PeerData *peer, MediaOverviewType type, bool back, int32 lastScrollTop) { App::wnd()->hideSettings(); if (overview && overview->peer() == peer) { if (overview->type() != type) { @@ -1018,6 +1075,8 @@ void MainWidget::showMediaOverview(const PeerData *peer, MediaOverviewType type, profile = 0; } overview = new OverviewWidget(this, peer, type); + _mediaTypeMask = 0; + mediaOverviewUpdated(peer); _topBar.show(); resizeEvent(0); overview->animShow(animCache, animTopBarCache, back, lastScrollTop); @@ -1026,10 +1085,11 @@ void MainWidget::showMediaOverview(const PeerData *peer, MediaOverviewType type, history.hide(); _topBar.raise(); dialogs.raise(); + _mediaType.raise(); if (hider) hider->raise(); } -void MainWidget::showPeerProfile(const PeerData *peer, bool back, int32 lastScrollTop, bool allMediaShown) { +void MainWidget::showPeerProfile(PeerData *peer, bool back, int32 lastScrollTop, bool allMediaShown) { App::wnd()->hideSettings(); if (profile && profile->peer() == peer) return; @@ -1068,6 +1128,7 @@ void MainWidget::showPeerProfile(const PeerData *peer, bool back, int32 lastScro history.hide(); _topBar.raise(); dialogs.raise(); + _mediaType.raise(); if (hider) hider->raise(); } @@ -1338,6 +1399,7 @@ void MainWidget::hideAll() { overview->hide(); } _topBar.hide(); + _mediaType.hide(); } void MainWidget::showAll() { @@ -1360,6 +1422,7 @@ void MainWidget::resizeEvent(QResizeEvent *e) { int32 tbh = _topBar.isHidden() ? 0 : st::topBarHeight; dialogs.setGeometry(0, 0, _dialogsWidth + st::dlgShadow, height()); _topBar.setGeometry(_dialogsWidth, 0, width() - _dialogsWidth, st::topBarHeight + st::titleShadow); + _mediaType.move(width() - _mediaType.width(), st::topBarHeight); history.setGeometry(_dialogsWidth, tbh, width() - _dialogsWidth, height() - tbh); if (profile) profile->setGeometry(history.geometry()); if (overview) overview->setGeometry(history.geometry()); @@ -1379,6 +1442,26 @@ void MainWidget::paintTopBar(QPainter &p, float64 over, int32 decreaseWidth) { } } +void MainWidget::onPhotosSelect() { + if (overview) overview->switchType(OverviewPhotos); + _mediaType.hideStart(); +} + +void MainWidget::onVideosSelect() { + if (overview) overview->switchType(OverviewVideos); + _mediaType.hideStart(); +} + +void MainWidget::onDocumentsSelect() { + if (overview) overview->switchType(OverviewDocuments); + _mediaType.hideStart(); +} + +void MainWidget::onAudiosSelect() { + if (overview) overview->switchType(OverviewAudios); + _mediaType.hideStart(); +} + TopBarWidget *MainWidget::topBar() { return &_topBar; } diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index e41b2325e..64fcde0c2 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -50,6 +50,8 @@ public: void showAll(); void showSelected(uint32 selCount); + FlatButton *mediaTypeButton(); + public slots: void onForwardSelection(); @@ -81,6 +83,7 @@ private: FlatButton _clearSelection; FlatButton _forward, _delete; FlatButton _edit, _leaveGroup, _addContact, _deleteContact; + FlatButton _mediaType; }; @@ -204,8 +207,9 @@ public: PeerData *activePeer(); MsgId activeMsgId(); PeerData *profilePeer(); - void showPeerProfile(const PeerData *peer, bool back = false, int32 lastScrollTop = -1, bool allMediaShown = false); - void showMediaOverview(const PeerData *peer, MediaOverviewType type, bool back = false, int32 lastScrollTop = -1); + bool mediaTypeSwitch(); + void showPeerProfile(PeerData *peer, bool back = false, int32 lastScrollTop = -1, bool allMediaShown = false); + void showMediaOverview(PeerData *peer, MediaOverviewType type, bool back = false, int32 lastScrollTop = -1); void showBackFromStack(); QRect historyRect() const; @@ -316,6 +320,11 @@ public slots: void onUpdateNotifySettings(); + void onPhotosSelect(); + void onVideosSelect(); + void onDocumentsSelect(); + void onAudiosSelect(); + private: void partWasRead(PeerData *peer, const MTPmessages_AffectedHistory &result); @@ -360,6 +369,9 @@ private: StackItems _stack; QPixmap profileAnimCache; + Dropdown _mediaType; + int32 _mediaTypeMask; + int updPts, updDate, updQts, updSeq; bool updInited; QTimer noUpdatesTimer; diff --git a/Telegram/SourceFiles/mediaview.cpp b/Telegram/SourceFiles/mediaview.cpp index f273abc0e..bfcced5d6 100644 --- a/Telegram/SourceFiles/mediaview.cpp +++ b/Telegram/SourceFiles/mediaview.cpp @@ -245,15 +245,17 @@ void MediaView::showPhoto(PhotoData *photo, HistoryItem *context) { _index = -1; _msgid = context ? context->id : 0; - for (int i = 0, l = _history->_overview[OverviewPhotos].size(); i < l; ++i) { - if (_history->_overview[OverviewPhotos].at(i) == _msgid) { - _index = i; - break; + if (_history) { + for (int i = 0, l = _history->_overview[OverviewPhotos].size(); i < l; ++i) { + if (_history->_overview[OverviewPhotos].at(i) == _msgid) { + _index = i; + break; + } } - } - if (_history->_overviewCount[OverviewPhotos] < 0) { - loadPhotosBack(); + if (_history->_overviewCount[OverviewPhotos] < 0) { + loadPhotosBack(); + } } showPhoto(photo); diff --git a/Telegram/SourceFiles/overviewwidget.cpp b/Telegram/SourceFiles/overviewwidget.cpp index a16e9d5e3..67c4d38c8 100644 --- a/Telegram/SourceFiles/overviewwidget.cpp +++ b/Telegram/SourceFiles/overviewwidget.cpp @@ -381,7 +381,23 @@ void OverviewInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton but if (_dragAction == NoDrag && _dragItem) { bool afterDragSymbol = false , uponSymbol = false; uint16 symbol = 0; - _dragAction = PrepareSelect; // start items select + if (textlnkDown()) { + _dragSymbol = symbol; + uint32 selStatus = (_dragSymbol << 16) | _dragSymbol; + if (selStatus != FullItemSel && (_selected.isEmpty() || _selected.cbegin().value() != FullItemSel)) { + if (!_selected.isEmpty()) { + updateMsg(_selected.cbegin().key(), -1); + _selected.clear(); + } + _selected.insert(_dragItem, selStatus); + _dragAction = Selecting; + updateMsg(_dragItem, _dragItemIndex); + } else { + _dragAction = PrepareSelect; + } + } else { + _dragAction = PrepareSelect; // start items select + } } if (!_dragItem) { @@ -831,66 +847,73 @@ void OverviewInner::onUpdateSelected() { } cur = textlnkDown() ? style::cur_pointer : style::cur_default; if (_dragAction == Selecting) { - 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 (_type == OverviewPhotos) { - if (_dragStartPos.x() >= _vsize || ((_mousedItem == dragSelFrom) && (m.x() < _dragStartPos.x() + QApplication::startDragDistance()))) { - moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, 1); + if (_mousedItem == _dragItem && lnk && !_selected.isEmpty() && _selected.cbegin().value() != FullItemSel) { + bool afterSymbol = false, uponSymbol = false; + uint16 second = 0; + _selected[_dragItem] = 0; + updateDragSelection(0, -1, 0, -1, false); + } else { + 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 (_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() >= (itemHeight(dragSelFrom, dragSelFromIndex) - st::msgMargin.bottom()) || ((_mousedItem == dragSelFrom) && (m.y() < _dragStartPos.y() + QApplication::startDragDistance()))) { - moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, -1); - } - } - } else { - 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 (_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 (_type == OverviewPhotos) { - if (m.x() < 0) { - moveToNextItem(dragSelTo, dragSelToIndex, dragSelFrom, -1); + if (_dragItem != _mousedItem) { // maybe exclude dragSelTo + if (selectingDown) { + 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() < st::msgMargin.top()) { - moveToNextItem(dragSelTo, dragSelToIndex, dragSelFrom, 1); - } - } - } else { - 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); + 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); + } } } } + bool dragSelecting = false; + MsgId dragFirstAffected = dragSelFrom; + int32 dragFirstAffectedIndex = dragSelFromIndex; + while (dragFirstAffectedIndex >= 0 && dragFirstAffected <= 0) { + moveToNextItem(dragFirstAffected, dragFirstAffectedIndex, dragSelTo, ((selectingDown && (_type == OverviewPhotos)) || (!selectingDown && (_type != OverviewPhotos))) ? -1 : 1); + } + if (dragFirstAffectedIndex >= 0) { + SelectedItems::const_iterator i = _selected.constFind(dragFirstAffected); + dragSelecting = (i == _selected.cend() || i.value() != FullItemSel); + } + updateDragSelection(dragSelFrom, dragSelFromIndex, dragSelTo, dragSelToIndex, dragSelecting); } - bool dragSelecting = false; - MsgId dragFirstAffected = dragSelFrom; - int32 dragFirstAffectedIndex = dragSelFromIndex; - while (dragFirstAffectedIndex >= 0 && dragFirstAffected <= 0) { - moveToNextItem(dragFirstAffected, dragFirstAffectedIndex, dragSelTo, ((selectingDown && (_type == OverviewPhotos)) || (!selectingDown && (_type != OverviewPhotos))) ? -1 : 1); - } - if (dragFirstAffectedIndex >= 0) { - SelectedItems::const_iterator i = _selected.constFind(dragFirstAffected); - dragSelecting = (i == _selected.cend() || i.value() != FullItemSel); - } - updateDragSelection(dragSelFrom, dragSelFromIndex, dragSelTo, dragSelToIndex, dragSelecting); } else if (_dragAction == Dragging) { } @@ -987,6 +1010,23 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { dragActionUpdate(e->globalPos()); } + // -2 - has full selected items, but not over, 0 - no selection, 2 - over full selected items + int32 isUponSelected = 0, hasSelected = 0; + if (!_selected.isEmpty()) { + isUponSelected = -1; + if (_selected.cbegin().value() == FullItemSel) { + hasSelected = 2; + if (App::hoveredLinkItem() && _selected.constFind(App::hoveredLinkItem()->id) != _selected.cend()) { + isUponSelected = 2; + } else { + isUponSelected = -2; + } + } + } + if (showFromTouch && hasSelected && isUponSelected < hasSelected) { + isUponSelected = hasSelected; + } + _contextMenuLnk = textlnkOver(); PhotoLink *lnkPhoto = dynamic_cast<PhotoLink*>(_contextMenuLnk.data()); VideoLink *lnkVideo = dynamic_cast<VideoLink*>(_contextMenuLnk.data()); @@ -1010,13 +1050,17 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { _menu->addAction(lang(lnkVideo ? lng_context_save_video : (lnkAudio ? lng_context_save_audio : lng_context_save_document)), this, SLOT(saveContextFile()))->setEnabled(true); } } - if (App::hoveredLinkItem()) { + if (isUponSelected > 1) { + _menu->addAction(lang(lng_context_forward_selected), _overview, SLOT(onForwardSelected())); + _menu->addAction(lang(lng_context_delete_selected), _overview, SLOT(onDeleteSelected())); + _menu->addAction(lang(lng_context_clear_selection), _overview, SLOT(onClearSelected())); + } else if (isUponSelected != -2 && App::hoveredLinkItem()) { if (dynamic_cast<HistoryMessage*>(App::hoveredLinkItem())) { _menu->addAction(lang(lng_context_forward_msg), this, SLOT(forwardMessage()))->setEnabled(true); } _menu->addAction(lang(lng_context_delete_msg), this, SLOT(deleteMessage()))->setEnabled(true); - App::contextItem(App::hoveredLinkItem()); } + App::contextItem(App::hoveredLinkItem()); } if (_menu) { _menu->setAttribute(Qt::WA_DeleteOnClose); @@ -1029,6 +1073,7 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { int32 OverviewInner::resizeToWidth(int32 nwidth, int32 scrollTop, int32 minHeight) { if (width() == nwidth && minHeight == _minHeight) return scrollTop; _minHeight = minHeight; + _addToY = (_height < _minHeight) ? (_minHeight - _height) : 0; if (_type == OverviewPhotos && _resizeIndex < 0) { _resizeIndex = _photosInRow * ((scrollTop + minHeight) / int32(_vsize + st::overviewPhotoSkip)) + _photosInRow - 1; _resizeSkip = (scrollTop + minHeight) - ((scrollTop + minHeight) / int32(_vsize + st::overviewPhotoSkip)) * int32(_vsize + st::overviewPhotoSkip); @@ -1055,7 +1100,14 @@ MediaOverviewType OverviewInner::type() const { } void OverviewInner::switchType(MediaOverviewType type) { - _type = type; + if (_type != type) { + _selected.clear(); + _dragItemIndex = _mousedItemIndex = _dragSelFromIndex = _dragSelToIndex = -1; + _dragItem = _mousedItem = _dragSelFrom = _dragSelTo = 0; + _items.clear(); + _cached.clear(); + _type = type; + } mediaOverviewUpdated(); if (App::wnd()) App::wnd()->update(); } @@ -1502,6 +1554,8 @@ void OverviewWidget::switchType(MediaOverviewType type) { _selCount = 0; App::main()->topBar()->showSelected(0); updateTopBarSelection(); + _scroll.scrollToY(_scroll.scrollTopMax()); + onScroll(); } void OverviewWidget::updateTopBarSelection() { @@ -1577,6 +1631,7 @@ void OverviewWidget::mediaOverviewUpdated(PeerData *p) { if (peer() == p) { _inner.mediaOverviewUpdated(); onScroll(); + updateTopBarSelection(); } } @@ -1700,4 +1755,3 @@ void OverviewWidget::onDeleteContextSure() { void OverviewWidget::onClearSelected() { _inner.clearSelectedItems(); } -