How To Intercept Clicks On Links in a QT5 Browser Widget

74 views
Skip to first unread message

Thomas Passin

unread,
Feb 26, 2020, 12:45:30 PM2/26/20
to leo-editor
If I create a QT5 browser widget, and (within Leo) want to intercept and act on clicks on hyperlinks, is that feasible?  Would I just look up the event for a hyperlink click and connect it to my own handler?

What I'm interested in specifically is the case where I have a mind map in the browser, and I want the links to go to corresponding nodes in a Leo outline.  It would seem that handling the click would be easier than trying to use the Leo Bridge (which I'm totally ignorant of).

Edward K. Ream

unread,
Feb 26, 2020, 1:14:53 PM2/26/20
to leo-editor
On Wed, Feb 26, 2020 at 11:45 AM Thomas Passin <tbp1...@gmail.com> wrote:
If I create a QT5 browser widget, and (within Leo) want to intercept and act on clicks on hyperlinks, is that feasible?  Would I just look up the event for a hyperlink click and connect it to my own handler?

Yes.

What I'm interested in specifically is the case where I have a mind map in the browser, and I want the links to go to corresponding nodes in a Leo outline.  It would seem that handling the click would be easier than trying to use the Leo Bridge (which I'm totally ignorant of).

Don't use the bridge within Leo. It wasn't designed for that.

Edward

Thomas Passin

unread,
Feb 26, 2020, 6:37:36 PM2/26/20
to leo-editor
Thank you, Edward .

Brian Theado

unread,
Feb 26, 2020, 10:15:46 PM2/26/20
to leo-editor
Thomas,

Below I've pasted a leo subtree containing a demo @button which will display html hyperlinks to nodes inside a QTextBrowser.

To use it copy the xml and in a leo outline, "paste as node". Create a script button from it and after clicking the button, a new pane should appear containing hyperlinks to the selected node and each of its subtree nodes. Clicking on those hyperlinks will move the selection to the node corresponding to the clicked link.

QT dock-based display only.

I thought I'd share in case it helps you along with what you are doing. The code is a little rough around the edges, but since it is a complete working example, it might be useful to you.

<?xml version="1.0" encoding="utf-8"?>
<!-- Created by Leo: http://leoeditor.com/leo_toc.html -->
<leo_file xmlns:leo="http://leoeditor.com/namespaces/leo-python-editor/1.1" >
<leo_header file_format="2"/>
<vnodes>
<v t="btheado.20200226212619.1"><vh>@button node linked html</vh>
<v t="btheado.20200226212619.10"><vh>display_widget_in_leo_pane()</vh></v>
<v t="btheado.20200226212619.11"><vh>display_html</vh></v>
<v t="btheado.20200226214559.1"><vh>node_link</vh></v>
<v t="btheado.20200226212619.12"><vh>display_node_linked_html</vh></v>
</v>
</vnodes>
<tnodes>
<t tx="btheado.20200226212619.1">@language python
from PyQt5 import QtCore, QtWidgets
@others

# Just some sample node links, one on each line
html = "\n".join([
    node_link(p) + "&lt;br/&gt;"
    for p in p.self_and_subtree()
])

# Display the html in a docked widget
display_node_linked_html(c, html)
</t>
<t tx="btheado.20200226212619.10">def display_widget_in_leo_pane(g, c, w, name):
    """
        w is the widget to display
        name is the name the widget should appear in pane menu
    """
    dw = c.frame.top
    c.user_dict.setdefault('btheado_docks', {})
    dock_dict = c.user_dict['btheado_docks']
    dock = dock_dict.get(name)
    if not dock:
        dock = g.app.gui.create_dock_widget(
                 closeable=True, moveable=True, height=50, name=name)
        dock_dict[name] = dock
        dw.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock)
    dock.setWidget(w)
    dock.show()
    #g.es(dock.widget())
</t>
<t tx="btheado.20200226212619.11">def display_html(html, name = 'test html'):
    w = QtWidgets.QTextBrowser()
    w.setHtml(html)
    display_widget_in_leo_pane(g, c, w, name)
    return w</t>
<t tx="btheado.20200226212619.12">def display_node_linked_html(c, html):
    def link_clicked(url):
        if url.isRelative():
            if url.path().startswith('node/'):
                gnx = url.path().split("/")[-1]
                target = next((
                    p
                    for p in c.all_unique_positions()
                    if p.v.gnx == gnx
                ), None)
                if target:
                    w.setSource(QtCore.QUrl())
                    c.selectPosition(target)
                    # Without this, there is possibility of the
                    # position not being displayed and subsequent
                    # expand of the node not showing all descendants
                    c.redraw()
                else:
                    g.es(f"Could not find node with gnx: {gnx}")
            else:
                g.es(f"Don't know how to handle url: {url.toString()}")
        else:
            g.es(f"Don't know how to handle url: {url.toString()}")

    w = display_html(html)
    w.anchorClicked.connect(link_clicked)</t>
<t tx="btheado.20200226214559.1">def node_link(p):
    return f"""
        &lt;a style="color: violet; text-decoration: none;"
        href="node/{p.v.gnx}"&gt;{p.h}&lt;/a&gt;
    """</t>
</tnodes>
</leo_file>


On Wed, Feb 26, 2020 at 12:45 PM Thomas Passin <tbp1...@gmail.com> wrote:
If I create a QT5 browser widget, and (within Leo) want to intercept and act on clicks on hyperlinks, is that feasible?  Would I just look up the event for a hyperlink click and connect it to my own handler?

What I'm interested in specifically is the case where I have a mind map in the browser, and I want the links to go to corresponding nodes in a Leo outline.  It would seem that handling the click would be easier than trying to use the Leo Bridge (which I'm totally ignorant of).

--
You received this message because you are subscribed to the Google Groups "leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email to leo-editor+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/leo-editor/500414ec-9e4b-4bfa-bb62-f763de2be5d6%40googlegroups.com.

Thomas Passin

unread,
Feb 26, 2020, 11:05:47 PM2/26/20
to leo-e...@googlegroups.com
Thanks!  Wow, that will save me lots of time.  Ummmm, I don't see how to "paste as node".  My version of Leo has no menu item or leo command that seems to be that.  Of course I can just paste it into the body of a node, but that won't give the same result.

So I opened a new text file, pasted your content in, and named the file something-or-other.leo   I loaded it into Leo, and it works just as advertised, button and all.  Thanks!

And right there is the connection I thought had to be possible:

w.anchorClicked.connect(link_clicked)

Perfect.

To unsubscribe from this group and stop receiving emails from it, send an email to leo-e...@googlegroups.com.

Edward K. Ream

unread,
Feb 27, 2020, 6:39:53 AM2/27/20
to leo-editor
On Wed, Feb 26, 2020 at 5:37 PM Thomas Passin <tbp1...@gmail.com> wrote:

If I create a QT5 browser widget, and (within Leo) want to intercept and act on clicks on hyperlinks, is that feasible?  Would I just look up the event for a hyperlink click and connect it to my own handler?

Yes.

What I'm interested in specifically is the case where I have a mind map in the browser, and I want the links to go to corresponding nodes in a Leo outline.  It would seem that handling the click would be easier than trying to use the Leo Bridge (which I'm totally ignorant of).

Don't use the bridge within Leo. It wasn't designed for that.

Thank you, Edward .

You're welcome.

Edward

Edward K. Ream

unread,
Feb 27, 2020, 6:41:11 AM2/27/20
to leo-editor
On Wed, Feb 26, 2020 at 9:15 PM Brian Theado <brian....@gmail.com> wrote:

Below I've pasted a leo subtree containing a demo @button which will display html hyperlinks to nodes inside a QTextBrowser.

Thanks for this helpful example.

Edward

Brian Theado

unread,
Feb 27, 2020, 7:11:27 AM2/27/20
to leo-editor
On Wed, Feb 26, 2020 at 11:05 PM Thomas Passin <tbp1...@gmail.com> wrote:
Thanks!  Wow, that will save me lots of time.  Ummmm, I don't see how to "paste as node".  My version of Leo has no menu item or leo command that seems to be that.  Of course I can just paste it into the body of a node, but that won't give the same result.

Looks like you already got it working, but the menu pick is at Outline->Paste-Node. Ctrl-Shift-v is the default keybinding.

Thomas Passin

unread,
Feb 27, 2020, 8:00:51 AM2/27/20
to leo-editor
Oh, I thought that only applied if you had directly copied a node using "Copy-Node".  I had no idea it would understand if you had xml that looked like a node in the body.

Matt Wilkie

unread,
Feb 27, 2020, 4:56:26 PM2/27/20
to leo-editor
Below I've pasted a leo subtree containing a demo @button which will display html hyperlinks to nodes inside a QTextBrowser.

Oh this is very neat, thank you. I've imagined something like this for Leo Docs.

Reply all
Reply to author
Forward
0 new messages