after looking over VR3's ViewRenderedProvider3 class, and the 
TestPaneProvider class in Terry Brown's example of putting up an additional 
pane (see 
https://leoeditor.com/FAQ.html#how-can-i-create-a-pane-for-matplotlib-charts), 
it seems to me that Leo should be providing a basic or generic class that 
provides enough basic splitter methods that many people will be able to use 
it as is.  Of course, it could be subclassed to add functionality.

This would let Leo script writers avoid  indulging in cargo cult 
programming, since most of us don't understand how the nested splitter 
machinery works.  I have taken a shot at this, and even though I know that 
it needs at least a few more methods.  Maybe there already is such a class, 
but at least this one is simpler.

Here is the code for this experimental class, followed by a little example 
code that shows how it can be used to install a QWebView widget -

# Adapted from Terry Brown's example in the FAQ at
# 
https://leoeditor.com/FAQ.html#how-can-i-create-a-pane-for-matplotlib-charts
'''
A script that adds a QT Widget pane to Leo.

After running this script, right click on one of the pane dividers and
select Insert. A new pane with a button 'Action' appears. Click it, and
select "Add test panel" from the context menu.

Alternatively, right click on a pane divider and click on
"Open Window/Add Test Pane". This will open a free-floating window 
with this test panel.
'''

class Generic_Ns_Provider:
    def __init__(self, c, widget_type, ns_name, ns_id, menu_label):
        """Create a Generic Namespace Provider object.
        
        PARAMETERS
        c -- the commander for a Leo outline.
        widget_type -- the type of widget to be installed (e.g.,
                       QtWebKitWidgets.QWebView).
        ns_name -- used by the nested splitter mechanism to identify
                   this panel.
        ns_id -- used by register_provider() to unregister previously 
registered
                 providers of the same service.  Also used to compute the
                 object name of the widget instance.
        menu_label -- a string used by the splitter context menu to display
                      the menu entry for this panel.
                      
        RETURNS
        nothing
        """

        self.c = c
        self.widget_type = widget_type
        self.id = ns_id
        self.ns_name = ns_name
        self.menu_label = menu_label
        if hasattr(c, 'free_layout'):
            splitter = c.free_layout.get_top_splitter()
            if splitter:
                splitter.register_provider(self)
    def ns_provides(self):
        return[(self.menu_label, self.ns_name)]
    def ns_provide(self, id_):
        if id_ == self.ns_name:
            c = self.c
            widget = self.widget_type()
            setattr(c, Generic_Ns_Provider.get_widget_name(self.id), widget)
            return widget
    def ns_provider_id(self):
        """used by register_provider() to unregister previously registered
           providers of the same service
           (provider ID is not the same as the service id_ above)
        """
        return self.id

    @staticmethod
    def get_widget_name(id):
        return f'{id}_widget'

# Example: connect to splitter apparatus
from leo.core.leoQt import QtWebKitWidgets
QWebView = QtWebKitWidgets.QWebView

NS_ID = '_generic_pane'
NS_NAME = '_add_generic_pane'
MENU_LABEL = 'Add generic panel'
HTML = '''<body><h2>This is a test</h2></body>'''

wn = Generic_Ns_Provider.get_widget_name(NS_ID)
if not hasattr(c, wn):
    Generic_Ns_Provider(c, QWebView, NS_NAME, NS_ID, MENU_LABEL)

if hasattr(c, wn):
    w = getattr(c, wn)
    w.setHtml(HTML)

Paste this into a node, then <CNTRL-b>.  Nothing will seem to happen, but 
the widget will be registered with the nested splitter machinery.  Until 
you activate this machinery, the widget won't actually be instantiated. Now 
right-click on a divider bar and select Insert. A new pane will open with a 
button Action. Click Action and click on 
Add Generic Panel.  The panel will turn blank - The QWebView object has 
been instantiated but has nothing to display yet.  Now click back in the 
node with the code and do <CTRL-b> again.  This will run the code at the 
bottom, which will discover that the widget exists and write a bit of HTML 
to it.

If you do a similar procedure but select Open Window/add generic panel, A 
blank free-floating window will open.  Again do <CNTRL-b> in the code, and 
the HTML will show up in this new free-floating window.

(It is left as an exercise to get rid of these panes!).

The main things demonstrated here are how easy it can be to get a new pane 
installed and opened, and how this approach avoids the cargo-cult 
programming of the past.  You can focus on the things that count, such as 
the type of widget, the menu label by which it will be activated, and a 
simple way to get the name by which it can be addressed.

SInce my own knowledge is not far removed from the cargo-cult stage, other 
people's input would be very helpful!

-- 
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 [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/leo-editor/6bee38c3-b5cf-4d64-a6e4-f05fbecad501n%40googlegroups.com.

Reply via email to