Clickable hyperlink in QTextEdit
Asked Answered
A

5

14

I want to use QTextEdit (in read-only mode) to show a clickable hyperlink, I used to do

QTextEdit *textEdit = new QTextEdit;
QTextCursor cursor(textEdit->document());
textEdit->setTextCursor(cursor);
cursor->insertHtml("<a href=\"www.google.com\" >Google</a>");
textEdit->show();

this code will show Google as hyperlink but unable to click.
And if I used

QTextEdit *textEdit = new QTextEdit;
QTextCursor cursor(textEdit->document());
textEdit->setTextCursor(cursor);
QTextCharFormat linkFormat = cursor.charFormat();
linkFormat.setAnchor(true);
linkFormat.setAnchorHref("http://www.google.com");
linkFormat.setAnchorName("Google");
cursor.insertText("Google", linkFormat);

then nothing happen. "Google" is just normal text.

Please help me insert clickable hyperlink to QTextEdit.

Amanda answered 8/3, 2016 at 3:24 Comment(0)
K
14

To have clickable hyperlink in QTextEdit, you can use

  1. QTextCharFormat::setAnchorHref to set the link for some text

  2. QWidget::mousePressEvent to capture mouse press event

  3. QTextEdit::anchorAt to obtain the link

Here's the minimal working PyQt example,

import sys
from PyQt5.Qt import QDesktopServices, QUrl, QApplication, QColor, Qt
from PyQt5.QtWidgets import QTextEdit


class MyWidget(QTextEdit):

    def mousePressEvent(self, e):
        self.anchor = self.anchorAt(e.pos())
        if self.anchor:
            QApplication.setOverrideCursor(Qt.PointingHandCursor)

    def mouseReleaseEvent(self, e):
        if self.anchor:
            QDesktopServices.openUrl(QUrl(self.anchor))
            QApplication.setOverrideCursor(Qt.ArrowCursor)
            self.anchor = None


app = QApplication(sys.argv)
editor = MyWidget()
cursor = editor.textCursor()
fmt = cursor.charFormat()
fmt.setForeground(QColor('blue'))
address = 'http://example.com'
fmt.setAnchor(True)
fmt.setAnchorHref(address)
fmt.setToolTip(address)
cursor.insertText("Hello world again", fmt)
editor.show()
app.exec_()
Keffiyeh answered 11/5, 2020 at 5:14 Comment(2)
This is the base solution I ended with. I changed it to use a mouseMoveEvent() to set the anchor and change the cursor to a PointingHand when on the anchor, and reset the cursor when not on an anchor. mousePressEvent() is not needed anymore and mouseRelease is used to open the url if the anchor is set.Ebarta
Don't forget to call the super() class mousePressEvent and mouseReleaseEvent implementations from the overriden methods, or you'll lost the standard mouse interaction with the widget!Demetrius
E
13

Using QTextBrowser is simpler (as suggested by another answer). However, if for some reason you want to use QTextEdit, try to change the text interaction flags using setTextInteractionFlags(). I think you have to enable the Qt::LinksAccessibleByMouse flag.

See Qt::TextInteractionFlag and QTextEdit::textInteractionFlags

Erythromycin answered 8/3, 2016 at 7:29 Comment(1)
Note: if you use the setTextInteractionFlag() with a QTextEdit, there's no way to detect the link was clicked. If you want to manually handle the activated link/anchor, you must use a QTextBrowser.Incrocci
D
8

As far as I've tried, when using QTextEdit + Qt::LinksAccessibleByMouse I'm able to click on links, but no action is taken (i.e., link is not open). The only action possible is to right-click on the link and select Copy Link Location.

As mentioned, one option is using QTextBrowser. In this case you have to set the QTextBrowser::openExternalLinks property too, in order to open the link using the default browser, otherwise it will be open in the text-browser widget.

Another option, given you have a read-only text, is to use a QLabel with rich format, and using the QLabel::linkActivated signal to open the URL

label->setTextFormat(Qt::RichText);
QObject::connect(label, &QLabel::linkActivated, [](const QString & link) {
  QDesktopServices::openUrl(link);
});
Defazio answered 25/6, 2019 at 8:17 Comment(1)
Note: I found that if you are linking to a file to be opened in addition to using .setOpenExternalLinks I needed to add the URL scheme "file://" for the link to work on MacOSOmeara
G
4

You can use QTextBrowser instead of QTextEdit if it read only text.

Gaussmeter answered 8/3, 2016 at 3:57 Comment(0)
W
0

In order for setTextInteractionFlags() to work the openExternalLinks property needs to be set. Since this property is not available on QTextEdit, here is a little hack to enable it.

auto &clist = edit->children();
for each (QObject *pObj in clist)
{
  QString cname = pObj->metaObject()->className();
  if (cname == "QWidgetTextControl")
    pObj->setProperty("openExternalLinks", true);
}

This does not address the mouse cursor, so you will still need to override mouseMoveEvent.

Wraith answered 17/12, 2021 at 21:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.