Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-138099

QTextEdit and QPlainTextEdit context menu position coordinates: poor usability and wrong behavior

    XMLWordPrintable

Details

    • Bug
    • Resolution: Unresolved
    • P2: Important
    • None
    • 6.9.1
    • None
    • Manjaro GNU/Linux x64, X11, Xfce
    • All

    Description

      The member function createStandardContextMenu(const QPoint &position) of both QTextEdit and QPlainTextEdit is documented to take "the position in document coordinates".

      The documentation is correct for QTextEdit, but translating from the viewport coordinates provided by the signal QTextEdit::customContextMenuRequested() to the document coordinates is not trivial and requires copying implementation ideas from QTextEditPrivate::horizontalOffset and QTextEditPrivate::verticalOffset (poor usability). For example:

      void MyWidget::textViewContextMenuRequested(const QPoint& viewportPosition)
      {
          const auto horizontalScrollBar = textEdit->horizontalScrollBar();
          const auto horizontalOffset = textEdit->isRightToLeft() ? horizontalScrollBar->maximum() - horizontalScrollBar->value() : horizontalScrollBar->value();
          const auto verticalOffset = textEdit->verticalScrollBar()->value();
          const auto documentPosition = viewportPosition + QPoint{horizontalOffset, verticalOffset};
          auto* popup = textEdit->createStandardContextMenu(documentPosition);

      Ideally, either createStandardContextMenu() should take the position in the viewport coordinates or QTextEdit should provide coordinate conversion API.

      As for QPlainTextEdit, due to the use of horizontalOffset() and verticalOffset() in QPlainTextEdit::anchorAt, its createStandardContextMenu() actually expects the position in the viewport coordinates. This is convenient for a user slot connected to QPlainTextEdit::customContextMenuRequested() because the already available position in the viewport coordinates just needs to be forwarded to createStandardContextMenu(). However, when createStandardContextMenu() is invoked from the standard context menu event handler of QPlainTextEdit (when user code does not override the default context menu policy and does not override QPlainTextEdit::contextMenuEvent()), its coordinates are translated to the document coordinates as well, which results in repeated/duplicate coordinate translation and incorrect end result (bug). For example, the default context menu handler of QPlainTextEdit incorrectly determines whether or not the user right-clicks a link when the scroll bars are not in their top-left-most states.

      I have tested this behavior in my application as follows:

      // configure the Q(Plain|)TextEdit instance
      textEdit->setTextInteractionFlags(textEdit->textInteractionFlags() | Qt::LinksAccessibleByMouse);
      textEdit->setWordWrapMode(QTextOption::WordWrap); // optional
      textEdit->setLayoutDirection(Qt::RightToLeft); // optional
      
      // insert several HTML links among lots of plain text
      const auto line = QStringLiteral("<a href=\"https://example.com\">loooong link</a>");
      QTextDocument *document = textEdit->document();
      QTextCursor cursor(document);
      cursor.movePosition(QTextCursor::End);
      cursor.insertHtml(line);
      

       

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            qt.team.quick.subscriptions Qt Quick and Widgets Team
            vedg Igor Kushnir
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There are no open Gerrit changes