4

If I create a link using appendHtml in QPlainTextEdit, how can I figure out if user click on it, and do something with the URL? There is no signal for clicking on URL, like in QTextBrowser.

Is there any way to accomplish this, other than creating a completely new Qt control that does this?

NOTE: I am not interested in different components like QTextEdit or QTextBrowser as these are incredibly slow. I specifically want to catch link clicks within either QPlainTextEdit or any customization of it, which has the same performance.

Petr
  • 13,747
  • 20
  • 89
  • 144

2 Answers2

9

There is the function QPlainTextEdit::anchorAt:

Returns the reference of the anchor at position pos, or an empty string if no anchor exists at that point.

To activate some link the user should press left mouse button on this object and release the button also on this link. That can be tracked by mousePressEvent and mouseReleaseEvent.

Unfortunately there is no simple mechanism to check on release that the button is released on the same link object. It is possible to compare only anchor text. So, the false positive detection can happen if there are several anchors with the same link. If it is a problem, it possible to do the similar trick with checking text selection state as in QTextBrowser if the widget text is selectable.

The simplest implementation:

#ifndef PLAINTEXTEDIT_H
#define PLAINTEXTEDIT_H

#include <QPlainTextEdit>
#include <QMouseEvent>

class PlainTextEdit : public QPlainTextEdit
{
    Q_OBJECT

private:
    QString clickedAnchor;

public:
    explicit PlainTextEdit(QWidget *parent = 0) : QPlainTextEdit(parent)
    {
    }

    void mousePressEvent(QMouseEvent *e)
    {
        clickedAnchor = (e->button() & Qt::LeftButton) ? anchorAt(e->pos()) :
                                                         QString();
        QPlainTextEdit::mousePressEvent(e);
    }

    void mouseReleaseEvent(QMouseEvent *e)
    {
        if (e->button() & Qt::LeftButton && !clickedAnchor.isEmpty() &&
            anchorAt(e->pos()) == clickedAnchor)
        {
            emit linkActivated(clickedAnchor);
        }

        QPlainTextEdit::mouseReleaseEvent(e);
    }

signals:
    void linkActivated(QString);
};

#endif // PLAINTEXTEDIT_H

The signal linkActivated is emitted with href anchor text. For example the signal will be emitted with the string "http://example.com" when the following anchor is activated:

QString html = "<a href='http://example.com'>Click me!</a>";
text->appendHtml(html);
Orest Hera
  • 6,706
  • 2
  • 21
  • 35
  • Is there a way to make the mouse cursor change when you hover over the hyperlink? I tried setting the `LinksAccessibleByMouse` flag in the `textInteractionFlags` property of the `QPlainTextEdit` widget, but that had no effect. – Mike Finch Apr 24 '19 at 19:55
1

Seems QPlainTextEdit doesn't support links at all. As the docu states it is for plain text with bit formatting only.

But it seems you can use a QTextBrowser as text editor if you set the readOnly property to false. Something like setProperty("readOnly", false) should work.

Aaron
  • 1,181
  • 7
  • 15
  • I specifically don't want to use it because it's incredibly slow (see http://stackoverflow.com/questions/33504015/how-to-fast-append-to-qtextedit) it does support links at least partially because when I append html which contains them, they look different than rest of text. – Petr Nov 05 '15 at 16:20
  • Well, I fear it really only highlights the links but provides no functionality beyond. – Aaron Nov 05 '15 at 16:46
  • You might get a less seriously blocking QTextBrowser if you buffer the log messages in chunks of 10 or 100 depending on their frequency and add those chunks to the QTextBrowser. No neat scrolling but your App. should stay responsive. – Aaron Nov 06 '15 at 17:40
  • `QTextBrowser` is inherited from `QTextEdit` and is just as slow as that one. I tried it in past, I've been playing with it for weeks. That thing is inherently slow. Its performance is nowhere near `QPlainTextEdit` and is basically unusable for anything what requires decent performance. – Petr Nov 07 '15 at 13:03