diff --git a/src/chatlog/chatlinecontent.cpp b/src/chatlog/chatlinecontent.cpp index 5b3b555e4..109230fb3 100644 --- a/src/chatlog/chatlinecontent.cpp +++ b/src/chatlog/chatlinecontent.cpp @@ -56,6 +56,10 @@ void ChatLineContent::selectionDoubleClick(QPointF) { } +void ChatLineContent::selectionTripleClick(QPointF) +{ +} + void ChatLineContent::selectionFocusChanged(bool) { } diff --git a/src/chatlog/chatlinecontent.h b/src/chatlog/chatlinecontent.h index 8c402f56c..d6309c38a 100644 --- a/src/chatlog/chatlinecontent.h +++ b/src/chatlog/chatlinecontent.h @@ -45,6 +45,7 @@ public: virtual void selectionStarted(QPointF scenePos); virtual void selectionCleared(); virtual void selectionDoubleClick(QPointF scenePos); + virtual void selectionTripleClick(QPointF scenePos); virtual void selectionFocusChanged(bool focusIn); virtual bool isOverSelection(QPointF scenePos) const; virtual QString getSelectedText() const; diff --git a/src/chatlog/chatlog.cpp b/src/chatlog/chatlog.cpp index b264c8a6b..087beab79 100644 --- a/src/chatlog/chatlog.cpp +++ b/src/chatlog/chatlog.cpp @@ -105,6 +105,12 @@ ChatLog::ChatLog(QWidget* parent) workerTimer->setInterval(5); connect(workerTimer, &QTimer::timeout, this, &ChatLog::onWorkerTimeout); + // This timer is used to detect multiple clicks + multiClickTimer = new QTimer(this); + multiClickTimer->setSingleShot(true); + multiClickTimer->setInterval(QApplication::doubleClickInterval()); + connect(multiClickTimer, &QTimer::timeout, this, &ChatLog::onMultiClickTimeout); + // selection connect(this, &ChatLog::selectionChanged, this, [this]() { copyAction->setEnabled(hasTextToBeCopied()); @@ -190,6 +196,13 @@ void ChatLog::mousePressEvent(QMouseEvent* ev) clickPos = ev->pos(); clearSelection(); } + + // Counts only single clicks and first click of doule click + clickCount++; + lastClickPos = ev->pos(); + + // Triggers on odd click counts + handleMultiClickEvent(); } void ChatLog::mouseReleaseEvent(QMouseEvent* ev) @@ -197,6 +210,8 @@ void ChatLog::mouseReleaseEvent(QMouseEvent* ev) QGraphicsView::mouseReleaseEvent(ev); selectionScrollDir = NoDirection; + + multiClickTimer->start(); } void ChatLog::mouseMoveEvent(QMouseEvent* ev) @@ -461,6 +476,13 @@ void ChatLog::mouseDoubleClickEvent(QMouseEvent* ev) emit selectionChanged(); } + + // Counts the second click of double click + clickCount++; + lastClickPos = ev->pos(); + + // Triggers on even click counts + handleMultiClickEvent(); } QString ChatLog::getSelectedText() const @@ -796,6 +818,36 @@ void ChatLog::onWorkerTimeout() } } +void ChatLog::onMultiClickTimeout() +{ + clickCount = 0; +} + +void ChatLog::handleMultiClickEvent() +{ + // Ignore single or double clicks + if (clickCount < 2) + return; + + switch (clickCount) { + case 3: + QPointF scenePos = mapToScene(lastClickPos); + ChatLineContent* content = getContentFromPos(scenePos); + + if (content) { + content->selectionTripleClick(scenePos); + selClickedCol = content->getColumn(); + selClickedRow = content->getRow(); + selFirstRow = content->getRow(); + selLastRow = content->getRow(); + selectionMode = Precise; + + emit selectionChanged(); + } + break; + } +} + void ChatLog::showEvent(QShowEvent*) { // Empty. diff --git a/src/chatlog/chatlog.h b/src/chatlog/chatlog.h index af3b7cf1a..c6d7fdb6a 100644 --- a/src/chatlog/chatlog.h +++ b/src/chatlog/chatlog.h @@ -74,6 +74,7 @@ public slots: private slots: void onSelectionTimerTimeout(); void onWorkerTimeout(); + void onMultiClickTimeout(); protected: QRectF calculateSceneRect() const; @@ -111,6 +112,7 @@ protected: private: void retranslateUi(); bool isActiveFileTransfer(ChatLine::Ptr l); + void handleMultiClickEvent(); private: enum SelectionMode @@ -147,7 +149,10 @@ private: QGraphicsRectItem* selGraphItem = nullptr; QTimer* selectionTimer = nullptr; QTimer* workerTimer = nullptr; + QTimer* multiClickTimer = nullptr; AutoScrollDirection selectionScrollDir = NoDirection; + int clickCount = 0; + QPoint lastClickPos; // worker vars int workerLastIndex = 0; diff --git a/src/chatlog/content/text.cpp b/src/chatlog/content/text.cpp index 3a6557771..1dd1b1189 100644 --- a/src/chatlog/content/text.cpp +++ b/src/chatlog/content/text.cpp @@ -121,6 +121,30 @@ void Text::selectionDoubleClick(QPointF scenePos) update(); } +void Text::selectionTripleClick(QPointF scenePos) +{ + if (!doc) + return; + + int cur = cursorFromPos(scenePos); + + if (cur >= 0) { + QTextCursor cursor(doc); + cursor.setPosition(cur); + cursor.select(QTextCursor::BlockUnderCursor); + + selectionAnchor = cursor.selectionStart(); + selectionEnd = cursor.selectionEnd(); + + if (cursor.block().isValid() && cursor.block().blockNumber() != 0) + selectionAnchor++; + + selectedText = extractSanitizedText(getSelectionStart(), getSelectionEnd()); + } + + update(); +} + void Text::selectionFocusChanged(bool focusIn) { selectionHasFocus = focusIn; diff --git a/src/chatlog/content/text.h b/src/chatlog/content/text.h index fdfc7618d..d4e18f7aa 100644 --- a/src/chatlog/content/text.h +++ b/src/chatlog/content/text.h @@ -43,6 +43,7 @@ public: virtual void selectionStarted(QPointF scenePos) final; virtual void selectionCleared() final; virtual void selectionDoubleClick(QPointF scenePos) final; + virtual void selectionTripleClick(QPointF scenePos) final; virtual void selectionFocusChanged(bool focusIn) final; virtual bool isOverSelection(QPointF scenePos) const final; virtual QString getSelectedText() const final;