View Single Post
Old 10-24-2025, 12:41 PM   #1
myway880
Junior Member
myway880 began at the beginning.
 
Posts: 8
Karma: 10
Join Date: Oct 2025
Device: i dont have one
help with developing a plugin for footnotes

hi , I'm new here and off course i need help
i do not know how to even read python but i'm using AI and off course i'm stuck with a problem...

I'm developing a large plugin for adding tool-tips, footnotes and sidebar notes and margin notes for a book i'm working on, and it is going to need a lot of notes

So the problem i had at first was that the AI couldn't get the GUI buttons added to caliber editor and even when it succeeded it would break it by accident later and would take very long trying to fix it again .

Eventually i decided to ask it to make a shim API for adding menus and buttons to the toolbar and it succeeded with the first but the second is broken and it cannot fix it

Here is the code if any one can help make it work i will be super grateful it add menus and commands under them but it keep adding a drop-down menu to the toolbar and the AI can not tell how to make it add individual commands

here is the python code for the shim
Code:
# shim.py
# Qt compatibility
try:
    from PyQt6.QtWidgets import (QMainWindow, QToolBar, QMenu, QToolButton)
    from PyQt6.QtCore import Qt
    from PyQt6.QtGui import QIcon, QAction
except ImportError:
    from PyQt5.QtWidgets import (QMainWindow, QToolBar, QMenu, QToolButton, QAction)
    from PyQt5.QtCore import Qt
    from PyQt5.QtGui import QIcon

# Mock Boss and GUI for testing
class MockGui(QMainWindow):
    def __init__(self):
        super().__init__()
        self.resize(800, 600)
        self.setWindowTitle("Shim GUI Test")
        self.menuBar() # Initialize menu bar
        self.plugins_menu = self.menuBar().addMenu('&Plugins')
        tb = self.addToolBar("Plugins toolbar")
        tb.setObjectName("plugins-toolbar")
        tb.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)

class MockBoss:
    def __init__(self):
        self.gui = MockGui()

# ShimBoss with new APIs
class ShimBoss:
    def __init__(self, gui):
        self.gui = gui

    def get_plugins_menu(self):
        mb = self.gui.menuBar()
        for a in mb.actions():
            m = a.menu()
            if m and m.title() == '&Plugins':
                return m
        return None

    def add_menu_action(self, menu_path, action_text, callback, shortcut=None, icon_path=None, tooltip=None, name=None):
        paths = menu_path.split('|')
        if paths[0] == 'Plugins':
            menu = self.get_plugins_menu()
            paths = paths[1:]
        else:
            mb = self.gui.menuBar()
            root_title = paths[0]
            menu = None
            for a in mb.actions():
                m = a.menu()
                if m and m.title() == root_title:
                    menu = m
                    break
            if not menu:
                menu = mb.addMenu(root_title)
            paths = paths[1:]
        for p in paths:
            found = False
            for a in menu.actions():
                if a.menu() and a.menu().title() == p:
                    menu = a.menu()
                    found = True
                    break
            if not found:
                menu = menu.addMenu(p)
        ac = menu.addAction(action_text)
        if icon_path:
            ac.setIcon(QIcon(icon_path))
        if tooltip:
            ac.setToolTip(tooltip)
        if shortcut:
            ac.setShortcut(shortcut)
        if name:
            ac.setObjectName(name)
        ac.triggered.connect(callback)
        return ac

    def add_toolbar_action(self, action_text, callback, toolbar_name='plugins-toolbar', icon_path=None, tooltip=None, name=None):
        tb = self.gui.findChild(QToolBar, toolbar_name)
        if not tb:
            tb = self.gui.addToolBar('Plugins')
            tb.setObjectName(toolbar_name)
        ac = QAction(action_text, self.gui)
        if icon_path:
            ac.setIcon(QIcon(icon_path))
        if tooltip:
            ac.setToolTip(tooltip)
        if name:
            ac.setObjectName(name)
        ac.triggered.connect(callback)
        tb.addAction(ac)
        widget = tb.widgetForAction(ac)
        if widget:
            widget.setPopupMode(QToolButton.NoButton)
        return ac

    def add_toolbar_dropdown(self, button_text, actions_list, toolbar_name='plugins-toolbar', icon_path=None, tooltip=None):
        """
        Add a dropdown toolbar button with sub-actions.
        actions_list: list of dicts, e.g., [{'text': 'Sub1', 'callback': fn1, 'shortcut': None, 'icon_path': None, 'tooltip': None}]
        """
        tb = self.gui.findChild(QToolBar, toolbar_name)
        if not tb:
            tb = self.gui.addToolBar('Plugins')
            tb.setObjectName(toolbar_name)
        toolbutton = QToolButton(self.gui)
        toolbutton.setText(button_text)
        if icon_path:
            toolbutton.setIcon(QIcon(icon_path))
        if tooltip:
            toolbutton.setToolTip(tooltip)
        menu = QMenu(toolbutton)
        for act_dict in actions_list:
            ac = menu.addAction(act_dict['text'])
            if act_dict.get('icon_path'):
                ac.setIcon(QIcon(act_dict['icon_path']))
            if act_dict.get('tooltip'):
                ac.setToolTip(act_dict['tooltip'])
            if act_dict.get('shortcut'):
                ac.setShortcut(act_dict['shortcut'])
            ac.triggered.connect(act_dict['callback'])
        toolbutton.setMenu(menu)
        toolbutton.setPopupMode(QToolButton.InstantPopup)
        tb.addWidget(toolbutton)
        return toolbutton

    def hide_toolbar_action(self, name, toolbar_name='plugins-toolbar'):
        tb = self.gui.findChild(QToolBar, toolbar_name)
        if tb:
            for ac in tb.actions():
                if ac.objectName() == name:
                    ac.setVisible(False)

    def show_toolbar_action(self, name, toolbar_name='plugins-toolbar'):
        tb = self.gui.findChild(QToolBar, toolbar_name)
        if tb:
            for ac in tb.actions():
                if ac.objectName() == name:
                    ac.setVisible(True)

if __name__ == "__main__":
    try:
        from PyQt6.QtWidgets import QApplication
    except ImportError:
        from PyQt5.QtWidgets import QApplication
    import sys
    app = QApplication(sys.argv)
    boss = MockBoss()
    shim = ShimBoss(boss.gui)
    # Test additions
    def quick_fn():
        print("Quick action triggered")
    shim.add_menu_action('Plugins|Footnotes', 'Test Action', quick_fn, shortcut='Ctrl+T', tooltip='Test')
    shim.add_toolbar_action('Quick Action', quick_fn, tooltip='Quick fn', name='quick_action')
    # Example hide/show
    shim.hide_toolbar_action('quick_action')
    shim.show_toolbar_action('quick_action')
    boss.gui.show()
    sys.exit(app.exec_())
I will off course be releasing the plugin if i ever mange to make it work i already have a 25000 line of code however i don't know yet how much of it work , lol
even though this whole project was a test anyway to see if it will work and so far it is kind of is ...
I have this output from the plugin and a semi working GUI


Code:
<span xml:lang="en" title="hello">hi4</span>

<span xml:lang="en" title="hello" class="acronym">hi3</span>

<span xml:lang="en" title="hello" class="glossary">hi2</span>

<span xml:lang="en" title="hello" class="definition">hi</span>

<sup><a href="balm.html#ftn3" id="bodyftn3" xml:lang="en" class="noteanchor">[3]</a></sup>

<sup><a href="balm.html#ftn1" id="bodyftn1" xml:lang="en" class="noteanchor">[1]</a></sup>

<sup><a href="balm.html#ftn2" id="bodyftn2" xml:lang="en" class="noteanchor">[2]</a></sup>

<p class="footer">Footnotes</p><div id="ftn1" tabindex="0" xml:lang="en" class="note"><a href="balm.html#bodyftn1" class="noteSymbol">(1)</a> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">hello</p></div>

<div id="ftn2" tabindex="0" xml:lang="en" class="sidebar"><a href="balm.html#bodyftn2" class="noteSymbol">(2)</a> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">hello</p></div>

<aside id="ftn3" tabindex="0" xml:lang="en" class="marginnote"><a href="balm.html#bodyftn3" class="noteSymbol">(3)</a> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">hello</p></aside>
i kind of need some second opinion from experience book editors about the output above as this is the recommendation of the AI.
frankly i have no real experience with digital book editing either and whither the compatibility of the output above with e-reader is any good.

If anyone with experience is willing to advice with any improvement that will be wonderful.

So anyway the AI kind of make me run around in circles but eventually it gets there.

i'm not interested in someone giving me the full code although that would be welcome. just a hint about what is wrong or a code snippet.

thank you in advance for your time and assistance
myway880 is offline   Reply With Quote