diff --git a/Telegram/SourceFiles/dialogswidget.cpp b/Telegram/SourceFiles/dialogswidget.cpp index 037cc13029..2fb1c38b52 100644 --- a/Telegram/SourceFiles/dialogswidget.cpp +++ b/Telegram/SourceFiles/dialogswidget.cpp @@ -41,7 +41,8 @@ searchedSel(-1), peopleSel(-1), _lastSearchId(0), _state(DefaultState), -_addContactLnk(this, lang(lng_add_contact_button)) { +_addContactLnk(this, lang(lng_add_contact_button)), +_overDelete(false) { 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*))); @@ -100,7 +101,11 @@ void DialogsListWidget::paintEvent(QPaintEvent *e) { p.setPen(st::black->p); for (; from < to; ++from) { bool selected = (from == hashtagSel); - if (selected) p.fillRect(0, 0, w, st::mentionHeight, st::dlgHoverBG->b); + if (selected) { + p.fillRect(0, 0, w, st::mentionHeight, st::dlgHoverBG->b); + int skip = (st::mentionHeight - st::notifyClose.icon.pxHeight()) / 2; + p.drawPixmap(QPoint(w - st::notifyClose.icon.pxWidth() - skip, skip), App::sprite(), st::notifyClose.icon); + } QString tag = st::mentionFont->m.elidedText('#' + hashtagResults.at(from), Qt::ElideRight, w - st::dlgPaddingHor * 2); p.drawText(st::dlgPaddingHor, st::mentionTop + st::mentionFont->ascent, tag); p.translate(0, st::mentionHeight); @@ -241,6 +246,7 @@ void DialogsListWidget::onUpdateSelected(bool force) { if ((!force && !rect().contains(mouse)) || !selByMouse) return; int w = width(), mouseY = mouse.y(); + _overDelete = false; if (_state == DefaultState) { DialogRow *newSel = dialogs.list.rowAtY(mouseY, st::dlgHeight); int32 otherStart = dialogs.list.count * st::dlgHeight; @@ -266,6 +272,9 @@ void DialogsListWidget::onUpdateSelected(bool force) { setCursor((hashtagSel >= 0) ? style::cur_pointer : style::cur_default); parentWidget()->update(); } + if (hashtagSel >= 0) { + _overDelete = (mouse.x() >= w - st::mentionHeight); + } mouseY -= filteredOffset(); } if (!filterResults.isEmpty()) { @@ -1041,8 +1050,28 @@ bool DialogsListWidget::choosePeer() { if (sel) history = sel->history; } else if (_state == FilteredState || _state == SearchedState) { if (hashtagSel >= 0 && hashtagSel < hashtagResults.size()) { - saveRecentHashtags('#' + hashtagResults.at(hashtagSel)); - emit completeHashtag(hashtagResults.at(hashtagSel)); + QString hashtag = hashtagResults.at(hashtagSel); + if (_overDelete) { + lastMousePos = QCursor::pos(); + + RecentHashtagPack recent(cRecentSearchHashtags()); + for (RecentHashtagPack::iterator i = recent.begin(); i != recent.cend();) { + if (i->first == hashtag) { + i = recent.erase(i); + } else { + ++i; + } + } + cSetRecentSearchHashtags(recent); + Local::writeRecentHashtags(); + emit refreshHashtags(); + + selByMouse = true; + onUpdateSelected(true); + } else { + saveRecentHashtags('#' + hashtag); + emit completeHashtag(hashtag); + } return true; } if (filteredSel >= 0 && filteredSel < filterResults.size()) { @@ -1318,6 +1347,7 @@ DialogsWidget::DialogsWidget(MainWidget *parent) : QWidget(parent) connect(&list, SIGNAL(searchMessages()), this, SLOT(onNeedSearchMessages())); connect(&list, SIGNAL(searchResultChosen()), this, SLOT(onCancel())); connect(&list, SIGNAL(completeHashtag(QString)), this, SLOT(onCompleteHashtag(QString))); + connect(&list, SIGNAL(refreshHashtags()), this, SLOT(onFilterCursorMoved())); connect(&scroll, SIGNAL(geometryChanged()), &list, SLOT(onParentGeometryChanged())); connect(&scroll, SIGNAL(scrolled()), &list, SLOT(onUpdateSelected())); connect(&scroll, SIGNAL(scrolled()), this, SLOT(onListScroll())); @@ -1707,6 +1737,7 @@ void DialogsWidget::onFilterUpdate(bool force) { } void DialogsWidget::onFilterCursorMoved(int from, int to) { + if (to < 0) to = _filter.cursorPosition(); QString t = _filter.text(), r; for (int start = to; start > 0;) { --start; diff --git a/Telegram/SourceFiles/dialogswidget.h b/Telegram/SourceFiles/dialogswidget.h index 9dd528200f..d98ff14ae3 100644 --- a/Telegram/SourceFiles/dialogswidget.h +++ b/Telegram/SourceFiles/dialogswidget.h @@ -116,6 +116,7 @@ signals: void searchMessages(); void searchResultChosen(); void completeHashtag(QString tag); + void refreshHashtags(); private: @@ -154,6 +155,8 @@ private: LinkButton _addContactLnk; + bool _overDelete; + }; class DialogsWidget : public QWidget, public Animated, public RPCSender { @@ -217,7 +220,7 @@ public slots: void onNewGroup(); bool onCancelSearch(); - void onFilterCursorMoved(int from, int to); + void onFilterCursorMoved(int from = -1, int to = -1); void onCompleteHashtag(QString tag); void onDialogToTopFrom(int movedFrom); diff --git a/Telegram/SourceFiles/dropdown.cpp b/Telegram/SourceFiles/dropdown.cpp index e2b7f56dd4..e7236d1364 100644 --- a/Telegram/SourceFiles/dropdown.cpp +++ b/Telegram/SourceFiles/dropdown.cpp @@ -881,7 +881,7 @@ void EmojiPan::onTabChange() { } } -MentionsInner::MentionsInner(MentionsDropdown *parent, MentionRows *rows, HashtagRows *hrows) : _parent(parent), _rows(rows), _hrows(hrows), _sel(-1), _mouseSel(false) { +MentionsInner::MentionsInner(MentionsDropdown *parent, MentionRows *rows, HashtagRows *hrows) : _parent(parent), _rows(rows), _hrows(hrows), _sel(-1), _mouseSel(false), _overDelete(false) { } void MentionsInner::paintEvent(QPaintEvent *e) { @@ -895,8 +895,11 @@ void MentionsInner::paintEvent(QPaintEvent *e) { for (int32 i = from; i < to; ++i) { if (i >= last) break; - if (i == _sel) p.fillRect(0, i * st::mentionHeight, width(), st::mentionHeight, st::dlgHoverBG->b); - + if (i == _sel) { + p.fillRect(0, i * st::mentionHeight, width(), st::mentionHeight, st::dlgHoverBG->b); + int skip = (st::mentionHeight - st::notifyClose.icon.pxHeight()) / 2; + if (_rows->isEmpty()) p.drawPixmap(QPoint(width() - st::notifyClose.icon.pxWidth() - skip, i * st::mentionHeight + skip), App::sprite(), st::notifyClose.icon); + } if (_rows->isEmpty()) { QString tag = st::mentionFont->m.elidedText('#' + _hrows->at(last - i - 1), Qt::ElideRight, htagwidth); p.setFont(st::mentionFont->f); @@ -931,7 +934,7 @@ void MentionsInner::mouseMoveEvent(QMouseEvent *e) { } void MentionsInner::clearSel() { - _mouseSel = false; + _mouseSel = _overDelete = false; setSel(-1); } @@ -963,7 +966,27 @@ void MentionsInner::mousePressEvent(QMouseEvent *e) { _mouseSel = true; onUpdateSelected(true); if (e->button() == Qt::LeftButton) { - select(); + if (_overDelete && _sel >= 0 && _sel < _hrows->size()) { + _mousePos = mapToGlobal(e->pos()); + + QString toRemove = _hrows->at(_hrows->size() - _sel - 1); + RecentHashtagPack recent(cRecentWriteHashtags()); + for (RecentHashtagPack::iterator i = recent.begin(); i != recent.cend();) { + if (i->first == toRemove) { + i = recent.erase(i); + } else { + ++i; + } + } + cSetRecentWriteHashtags(recent); + Local::writeRecentHashtags(); + _parent->updateFiltered(); + + _mouseSel = true; + onUpdateSelected(true); + } else { + select(); + } } } @@ -992,6 +1015,7 @@ void MentionsInner::onUpdateSelected(bool force) { if ((!force && !rect().contains(mouse)) || !_mouseSel) return; int w = width(), mouseY = mouse.y(); + _overDelete = _rows->isEmpty() && (mouse.x() >= w - st::mentionHeight); int32 sel = mouseY / int32(st::mentionHeight), maxSel = _rows->isEmpty() ? _hrows->size() : _rows->size(); if (sel < 0 || sel >= maxSel) { sel = -1; @@ -1056,6 +1080,10 @@ void MentionsDropdown::showFiltered(ChatData *chat, QString start) { _filter = start; } + updateFiltered(toDown); +} + +void MentionsDropdown::updateFiltered(bool toDown) { int32 now = unixtime(); QMultiMap ordered; MentionRows rows; diff --git a/Telegram/SourceFiles/dropdown.h b/Telegram/SourceFiles/dropdown.h index 18fb14cbbd..cc5f2e8b5a 100644 --- a/Telegram/SourceFiles/dropdown.h +++ b/Telegram/SourceFiles/dropdown.h @@ -271,6 +271,7 @@ private: bool _mouseSel; QPoint _mousePos; + bool _overDelete; }; class MentionsDropdown : public QWidget, public Animated { @@ -285,6 +286,7 @@ public: void fastHide(); void showFiltered(ChatData *chat, QString start); + void updateFiltered(bool toDown = false); void setBoundings(QRect boundings); bool animStep(float64 ms); diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 7067ca29c8..ccd08290cd 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -1060,7 +1060,7 @@ void HistoryList::onTouchSelect() { } void HistoryList::onUpdateSelected() { - if (hist->isEmpty()) return; + if (!hist || hist->isEmpty()) return; QPoint mousePos(mapFromGlobal(_dragPos)); QPoint m(historyWidget->clampMousePosition(mousePos)); diff --git a/Telegram/SourceFiles/localstorage.cpp b/Telegram/SourceFiles/localstorage.cpp index 66c77ef503..9feffa3f19 100644 --- a/Telegram/SourceFiles/localstorage.cpp +++ b/Telegram/SourceFiles/localstorage.cpp @@ -516,6 +516,7 @@ namespace { FileKey _userSettingsKey = 0; FileKey _recentHashtagsKey = 0; + bool _recentHashtagsWereRead = false; typedef QPair FileDesc; // file, size typedef QMap StorageMap; @@ -2255,6 +2256,9 @@ namespace Local { } void readRecentHashtags() { + if (_recentHashtagsWereRead) return; + _recentHashtagsWereRead = true; + if (!_recentHashtagsKey) return; FileReadDescriptor hashtags; diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 414066bba0..7bf7a3845b 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -2103,6 +2103,7 @@ void MainWidget::showAll() { profile->show(); } else { history.show(); + history.resizeEvent(0); } if (profile || overview || history.peer()) { _topBar.show(); @@ -2129,6 +2130,7 @@ void MainWidget::showAll() { profile->show(); } else if (history.peer()) { history.show(); + history.resizeEvent(0); } else { dialogs.show(); history.hide();