diff --git a/tools/chatgui/src/messagedelegate.cpp b/tools/chatgui/src/messagedelegate.cpp index b291844db..b528a41a9 100644 --- a/tools/chatgui/src/messagedelegate.cpp +++ b/tools/chatgui/src/messagedelegate.cpp @@ -182,8 +182,10 @@ bool MessageDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, m_pollPress = onPoll ? index : QModelIndex(); m_pollPressPosition = mouse->pos(); return codeBlock >= 0 || onQuote || onAvatar || onReaction || onPoll; } + const auto* view = qobject_cast(option.widget); const bool copyCode = codeBlock >= 0 && m_codePress == index && m_codePressBlock == codeBlock - && (mouse->pos() - m_codePressPosition).manhattanLength() < 5 && m_codePressSource == index.data(MsgTextRole).toString(); + && (mouse->pos() - m_codePressPosition).manhattanLength() < 5 && m_codePressSource == index.data(MsgTextRole).toString() + && (!view || !view->textSelection().active); m_codePress = QPersistentModelIndex(); m_codePressBlock = -1; m_codePressSource.clear(); if (copyCode) { const auto& block = L.formattedText->code[codeBlock]; @@ -193,7 +195,6 @@ bool MessageDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, } const bool activateMedia = onMedia && m_mediaPress == index && (mouse->pos() - m_mediaPressPosition).manhattanLength() < 5; m_mediaPress = QPersistentModelIndex(); - const auto* view = qobject_cast(option.widget); const bool hadQuotePress = m_quotePress.isValid(); const bool activateQuote = onQuote && m_quotePress == index && (mouse->pos() - m_quotePressPosition).manhattanLength() < 5 && (!view || !view->hasSelection()); diff --git a/tools/chatgui/tests/test_invite_links.cpp b/tools/chatgui/tests/test_invite_links.cpp index bc3a7ac72..dfd9b653e 100644 --- a/tools/chatgui/tests/test_invite_links.cpp +++ b/tools/chatgui/tests/test_invite_links.cpp @@ -459,9 +459,14 @@ private slots: view.show(); QTest::qWait(30); QStyleOptionViewItem option; option.initFrom(&view); option.widget = &view; option.rect = view.visualRect(index); QMap buttons; - for (int y = 0; y < option.rect.height(); y += 4) for (int x = 0; x < view.viewport()->width(); x += 8) { - const int block = delegate.codeCopyAt(option, index, QPoint(x, y)); - if (block >= 0 && !buttons.contains(block)) buttons[block] = QPoint(x, y); + for (int y = 0; y < option.rect.height() && buttons.size() < 3; y += 4) { + // Все Copy выровнены по правому краю: после первой найденной кнопки проверяем только её колонку. + const int startX = buttons.isEmpty() ? 0 : buttons.first().x(); + const int endX = buttons.isEmpty() ? view.viewport()->width() : startX + 1; + for (int x = startX; x < endX; x += 8) { + const int block = delegate.codeCopyAt(option, index, QPoint(x, y)); + if (block >= 0 && !buttons.contains(block)) { buttons[block] = QPoint(x, y); break; } + } } QCOMPARE(buttons.size(), 3); QSignalSpy links(&view, &ChatView::linkActivated); @@ -483,6 +488,10 @@ private slots: QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, end); QCOMPARE(QApplication::clipboard()->text(), QString("unchanged")); QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::NoModifier, buttons[0]); + QApplication::sendEvent(view.viewport(), &drag); + QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, buttons[0]); + QCOMPARE(QApplication::clipboard()->text(), QString("unchanged")); + QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::NoModifier, buttons[0]); model.setData(index, source + " edited", MsgTextRole); QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, buttons[0]); QCOMPARE(QApplication::clipboard()->text(), QString("unchanged"));