From 4c4d1d2042809ba3b39d6de63a192bf855269070 Mon Sep 17 00:00:00 2001 From: Cranken Date: Sat, 6 Oct 2018 13:43:21 +0200 Subject: [PATCH] Fixed double click selection. --- src/messages/Selection.hpp | 10 ++ .../layouts/MessageLayoutContainer.cpp | 2 +- src/widgets/helper/ChannelView.cpp | 126 ++++++++++++++++-- src/widgets/helper/ChannelView.hpp | 5 + 4 files changed, 131 insertions(+), 12 deletions(-) diff --git a/src/messages/Selection.hpp b/src/messages/Selection.hpp index 7cffebbec..435ce6f26 100644 --- a/src/messages/Selection.hpp +++ b/src/messages/Selection.hpp @@ -76,4 +76,14 @@ struct Selection { } }; +struct DoubleClickSelection { + int originalStart = 0; + int originalEnd = 0; + int origMessageIndex; + bool selectingLeft = false; + bool selectingRight = false; + SelectionItem origStartItem; + SelectionItem origEndItem; +}; + } // namespace chatterino diff --git a/src/messages/layouts/MessageLayoutContainer.cpp b/src/messages/layouts/MessageLayoutContainer.cpp index 31bb8577f..a9dedf949 100644 --- a/src/messages/layouts/MessageLayoutContainer.cpp +++ b/src/messages/layouts/MessageLayoutContainer.cpp @@ -485,7 +485,7 @@ int MessageLayoutContainer::getSelectionIndex(QPoint point) } // this is the word - if (point.x() < this->elements_[i]->getRect().right()) { + if (point.x() <= this->elements_[i]->getRect().right()) { index += this->elements_[i]->getMouseOverIndex(point); break; } diff --git a/src/widgets/helper/ChannelView.cpp b/src/widgets/helper/ChannelView.cpp index 0cb7f0bfe..700b90b8f 100644 --- a/src/widgets/helper/ChannelView.cpp +++ b/src/widgets/helper/ChannelView.cpp @@ -884,6 +884,94 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event) tooltipWidget->hide(); return; } + + if (this->isDoubleClick_) { + int wordStart; + int wordEnd; + this->getWordBounds(layout.get(), hoverLayoutElement, relativePos, + wordStart, wordEnd); + SelectionItem newStart(messageIndex, wordStart); + SelectionItem newEnd(messageIndex, wordEnd); + + // Selection changed in same message + if (messageIndex == this->dCSelection_.origMessageIndex) { + // Selecting to the left + if (wordStart < this->selection_.start.charIndex && + !this->dCSelection_.selectingRight) { + this->dCSelection_.selectingLeft = true; + this->setSelection(newStart, this->selection_.end); + // Selecting to the right + } else if (wordEnd > this->selection_.end.charIndex && + !this->dCSelection_.selectingLeft) { + this->dCSelection_.selectingRight = true; + this->setSelection(this->selection_.start, newEnd); + } + // Swapping from selecting left to selecting right + if (wordStart > this->selection_.start.charIndex && + !this->dCSelection_.selectingRight) { + if (wordStart > this->dCSelection_.originalEnd) { + this->dCSelection_.selectingLeft = false; + this->dCSelection_.selectingRight = true; + this->setSelection(this->dCSelection_.origStartItem, + newEnd); + } else { + this->setSelection(newStart, this->selection_.end); + } + // Swapping from selecting right to selecting left + } else if (wordEnd < this->selection_.end.charIndex && + !this->dCSelection_.selectingLeft) { + if (wordEnd < this->dCSelection_.originalStart) { + this->dCSelection_.selectingLeft = true; + this->dCSelection_.selectingRight = false; + this->setSelection(newStart, + this->dCSelection_.origEndItem); + } else { + this->setSelection(this->selection_.start, newEnd); + } + } + // Selection changed in a different message + } else { + // Message over the original + if (messageIndex < this->selection_.start.messageIndex) { + // Swapping from left to right selecting + if (!this->dCSelection_.selectingLeft) { + this->dCSelection_.selectingLeft = true; + this->dCSelection_.selectingRight = false; + } + if (wordStart < this->selection_.start.charIndex && + !this->dCSelection_.selectingRight) { + this->dCSelection_.selectingLeft = true; + } + this->setSelection(newStart, this->dCSelection_.origEndItem); + // Message under the original + } else if (messageIndex > this->selection_.end.messageIndex) { + // Swapping from right to left selecting + if (!this->dCSelection_.selectingRight) { + this->dCSelection_.selectingLeft = false; + this->dCSelection_.selectingRight = true; + } + if (wordEnd > this->selection_.end.charIndex && + !this->dCSelection_.selectingLeft) { + this->dCSelection_.selectingRight = true; + } + this->setSelection(this->dCSelection_.origStartItem, newEnd); + // Selection changed in non original message + } else { + if (this->dCSelection_.selectingLeft) { + this->setSelection(newStart, this->selection_.end); + } else { + this->setSelection(this->selection_.start, newEnd); + } + } + } + // Reset direction of selection + if (wordStart == this->dCSelection_.originalStart && + wordEnd == this->dCSelection_.originalEnd) { + this->dCSelection_.selectingLeft = + this->dCSelection_.selectingRight = false; + } + } + const auto &tooltip = hoverLayoutElement->getCreator().getTooltip(); bool isLinkValid = hoverLayoutElement->getLink().isValid(); @@ -970,6 +1058,8 @@ void ChannelView::mouseReleaseEvent(QMouseEvent *event) { // check if mouse was pressed if (event->button() == Qt::LeftButton) { + this->isDoubleClick_ = this->dCSelection_.selectingLeft = + this->dCSelection_.selectingRight = false; if (this->isMouseDown_) { this->isMouseDown_ = false; @@ -1194,23 +1284,24 @@ void ChannelView::mouseDoubleClickEvent(QMouseEvent *event) return; } if (!this->isMouseDown_) { - this->isMouseDown_ = true; + this->isDoubleClick_ = true; - const int mouseInWordIndex = - hoverLayoutElement->getMouseOverIndex(relativePos); - const int wordStart = - layout->getSelectionIndex(relativePos) - mouseInWordIndex; - const int selectionLength = - hoverLayoutElement->getSelectionIndexCount(); - const int length = hoverLayoutElement->hasTrailingSpace() - ? selectionLength - 1 - : selectionLength; - const int wordEnd = wordStart + length; + int wordStart; + int wordEnd; + this->getWordBounds(layout.get(), hoverLayoutElement, relativePos, + wordStart, wordEnd); this->clickTimer_->start(); SelectionItem wordMin(messageIndex, wordStart); SelectionItem wordMax(messageIndex, wordEnd); + + this->dCSelection_.originalStart = wordStart; + this->dCSelection_.originalEnd = wordEnd; + this->dCSelection_.origMessageIndex = messageIndex; + this->dCSelection_.origStartItem = wordMin; + this->dCSelection_.origEndItem = wordMax; + this->setSelection(wordMin, wordMax); } @@ -1316,4 +1407,17 @@ void ChannelView::selectWholeMessage(MessageLayout *layout, int &messageIndex) this->setSelection(msgStart, msgEnd); } +void ChannelView::getWordBounds(MessageLayout *layout, + const MessageLayoutElement *element, + const QPoint &relativePos, int &wordStart, + int &wordEnd) +{ + const int mouseInWordIndex = element->getMouseOverIndex(relativePos); + wordStart = layout->getSelectionIndex(relativePos) - mouseInWordIndex; + const int selectionLength = element->getSelectionIndexCount(); + const int length = + element->hasTrailingSpace() ? selectionLength - 1 : selectionLength; + wordEnd = wordStart + length; +} + } // namespace chatterino diff --git a/src/widgets/helper/ChannelView.hpp b/src/widgets/helper/ChannelView.hpp index bc27345bb..f68835b09 100644 --- a/src/widgets/helper/ChannelView.hpp +++ b/src/widgets/helper/ChannelView.hpp @@ -106,6 +106,9 @@ private: MessageElementFlags getFlags() const; bool isPaused(); void selectWholeMessage(MessageLayout *layout, int &messageIndex); + void getWordBounds(MessageLayout *layout, + const MessageLayoutElement *element, + const QPoint &relativePos, int &wordStart, int &wordEnd); void handleMouseClick(QMouseEvent *event, const MessageLayoutElement *hoverLayoutElement, @@ -148,6 +151,8 @@ private: // Mouse event variables bool isMouseDown_ = false; bool isRightMouseDown_ = false; + bool isDoubleClick_ = false; + DoubleClickSelection dCSelection_; QPointF lastPressPosition_; QPointF lastRightPressPosition_; QTimer *clickTimer_;