Register Guidelines E-Books Today's Posts Search

Go Back   MobileRead Forums > E-Book Software > Sigil > Plugins

Notices

Reply
 
Thread Tools Search this Thread
Old 10-19-2025, 06:03 AM   #601
Doitsu
Grand Sorcerer
Doitsu ought to be getting tired of karma fortunes by now.Doitsu ought to be getting tired of karma fortunes by now.Doitsu ought to be getting tired of karma fortunes by now.Doitsu ought to be getting tired of karma fortunes by now.Doitsu ought to be getting tired of karma fortunes by now.Doitsu ought to be getting tired of karma fortunes by now.Doitsu ought to be getting tired of karma fortunes by now.Doitsu ought to be getting tired of karma fortunes by now.Doitsu ought to be getting tired of karma fortunes by now.Doitsu ought to be getting tired of karma fortunes by now.Doitsu ought to be getting tired of karma fortunes by now.
 
Doitsu's Avatar
 
Posts: 5,763
Karma: 24088559
Join Date: Dec 2010
Device: Kindle PW2
Quote:
Originally Posted by Capricorn View Post
What tools and websites are good to learn python?
I'd strongly recommend Automate the Boring Stuff with Python by Al Sweigart, which is available for free online.
You'll also need to download the Sigil Framework Guide.
You also might find the Sigil test plugin helpful because it demonstrates most Sigil-specific Python functions.

Here's a minimal proof-of-concept edit plugin that will wrap "the" in all html files in <b> tags:

Code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys, os

# main routine    
def run(bk):
    # iterate over all html files
    for html_id, href in bk.text_iter():
        # read orignal html code from file
        original_html = bk.readfile(html_id)
        # modify html code
        modified_html = original_html.replace('the', '<b>the</b>') 
        if modified_html != original_html:
            # write modified html code to file
            bk.writefile(html_id, modified_html)
            print(os.path.basename(href) + ' updated')
    return 0

def main():
    print('I reached main when I should not have\n')
    return -1

if __name__ == "__main__":
    sys.exit(main())
As you can see it doesn't really require much code. BTW, Sigil comes with a fork of the BeautifulSoup library that makes it really easy to manipulate HTML content. To import it you must use:

Code:
from sigil_bs4 import BeautifulSoup
Doitsu is offline   Reply With Quote
Old 10-19-2025, 09:04 AM   #602
KevinH
Sigil Developer
KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.
 
Posts: 9,089
Karma: 6379704
Join Date: Nov 2009
Device: many
Just to be clear ...

Sigil plugins only allow batch processing of files inside a single loaded epub. If you want to batch process a number of epubs without having to load them in Sigil, python is the way to go but not Sigil Plugins.

That said the python modules in Sigil could be extracted and used in a standalone python program with only low to moderate effort.

Last edited by KevinH; 10-19-2025 at 09:06 AM.
KevinH is offline   Reply With Quote
Old 10-19-2025, 02:37 PM   #603
theducks
Well trained by Cats
theducks ought to be getting tired of karma fortunes by now.theducks ought to be getting tired of karma fortunes by now.theducks ought to be getting tired of karma fortunes by now.theducks ought to be getting tired of karma fortunes by now.theducks ought to be getting tired of karma fortunes by now.theducks ought to be getting tired of karma fortunes by now.theducks ought to be getting tired of karma fortunes by now.theducks ought to be getting tired of karma fortunes by now.theducks ought to be getting tired of karma fortunes by now.theducks ought to be getting tired of karma fortunes by now.theducks ought to be getting tired of karma fortunes by now.
 
theducks's Avatar
 
Posts: 31,299
Karma: 62000000
Join Date: Aug 2009
Location: The Central Coast of California
Device: Kobo Libra2,Kobo Aura2v1, K4NT(Fixed: New Bat.), Galaxy Tab A
Quote:
Originally Posted by DiapDealer View Post
The markup in mobi files was full of small, medium, large, x-small, xx-large, and normal font sizes.

The mobi2xhtml script in the kindleinport plugin has a routine that tried to make some sort of sense out of it:

https://github.com/dougmassay/kindle...2xhtml.py#L358
I made a Sigil Saved Grouped Search that changes those name into ##em (except Normal is just deleted) (I used to have to do a lot of 'cleanup' on older files from the Baen CD's or Free Library.
This is one of the reasons I use Sigil for some tasks and Calibre Editor for others. They fit MY workflow (please keep doing Sigil things, the Sigil way), and Calibre does others.
All we need to do is learn to use the tools we have without making those other folk that want the other way (either editor) use OUR way.
Only if it is broken, does it need fixin'
theducks is offline   Reply With Quote
Old 10-20-2025, 03:05 AM   #604
Capricorn
Belgian Pommes Frites
Capricorn turned on, tuned in, and dropped out.Capricorn turned on, tuned in, and dropped out.Capricorn turned on, tuned in, and dropped out.Capricorn turned on, tuned in, and dropped out.Capricorn turned on, tuned in, and dropped out.Capricorn turned on, tuned in, and dropped out.Capricorn turned on, tuned in, and dropped out.Capricorn turned on, tuned in, and dropped out.Capricorn turned on, tuned in, and dropped out.Capricorn turned on, tuned in, and dropped out.Capricorn turned on, tuned in, and dropped out.
 
Posts: 131
Karma: 35038
Join Date: Jan 2012
Device: Pocketbook Touch HD
Tools

Quote:
Originally Posted by Doitsu View Post
I'd strongly recommend Automate the Boring Stuff with Python by Al Sweigart, which is available for free online.
You'll also need to download the Sigil Framework Guide.
You also might find the Sigil test plugin helpful because it demonstrates most Sigil-specific Python functions.
Thanks. I will get this book and see where it leads.
Capricorn is offline   Reply With Quote
Old 10-24-2025, 08:39 AM   #605
myway880
Junior Member
myway880 began at the beginning.
 
Posts: 8
Karma: 10
Join Date: Oct 2025
Device: i dont have one
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
thank you very much in advance
myway880 is offline   Reply With Quote
Old 10-24-2025, 10:24 AM   #606
DiapDealer
Grand Sorcerer
DiapDealer ought to be getting tired of karma fortunes by now.DiapDealer ought to be getting tired of karma fortunes by now.DiapDealer ought to be getting tired of karma fortunes by now.DiapDealer ought to be getting tired of karma fortunes by now.DiapDealer ought to be getting tired of karma fortunes by now.DiapDealer ought to be getting tired of karma fortunes by now.DiapDealer ought to be getting tired of karma fortunes by now.DiapDealer ought to be getting tired of karma fortunes by now.DiapDealer ought to be getting tired of karma fortunes by now.DiapDealer ought to be getting tired of karma fortunes by now.DiapDealer ought to be getting tired of karma fortunes by now.
 
DiapDealer's Avatar
 
Posts: 28,914
Karma: 207182180
Join Date: Jan 2010
Device: Nexus 7, Kindle Fire HD
Quote:
Originally Posted by myway880 View Post
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 .
This is not the Calibre plugin development section of the forum. This area is for Sigil plugin development.
DiapDealer is offline   Reply With Quote
Old 10-24-2025, 11:18 AM   #607
KevinH
Sigil Developer
KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.
 
Posts: 9,089
Karma: 6379704
Join Date: Nov 2009
Device: many
I am beginning to think that use of AI to "code" by non-developers is akin to giving a loaded handgun with the safety off to a complete firearms novice with no instructions on safety, or on use, or even common sense.

The only thing both will generate is a big mess.

Let's hope after 25,000 lines of code, I'm wrong, but ...

Last edited by KevinH; 10-24-2025 at 12:19 PM.
KevinH is offline   Reply With Quote
Old 10-24-2025, 11:27 AM   #608
DiapDealer
Grand Sorcerer
DiapDealer ought to be getting tired of karma fortunes by now.DiapDealer ought to be getting tired of karma fortunes by now.DiapDealer ought to be getting tired of karma fortunes by now.DiapDealer ought to be getting tired of karma fortunes by now.DiapDealer ought to be getting tired of karma fortunes by now.DiapDealer ought to be getting tired of karma fortunes by now.DiapDealer ought to be getting tired of karma fortunes by now.DiapDealer ought to be getting tired of karma fortunes by now.DiapDealer ought to be getting tired of karma fortunes by now.DiapDealer ought to be getting tired of karma fortunes by now.DiapDealer ought to be getting tired of karma fortunes by now.
 
DiapDealer's Avatar
 
Posts: 28,914
Karma: 207182180
Join Date: Jan 2010
Device: Nexus 7, Kindle Fire HD
I don't mind if people want to use AI for creating code for themselves. I just have a hard time understanding how I can assist someone with a coding issue who has no grasp of the language being used (or the algorithms being created). Other than to gift them with fully working code. I don't have the kind of free time to devote myself that completely to others' projects. Happy to provide my own code as an example, but...
DiapDealer is offline   Reply With Quote
Old 10-24-2025, 12:01 PM   #609
myway880
Junior Member
myway880 began at the beginning.
 
Posts: 8
Karma: 10
Join Date: Oct 2025
Device: i dont have one
Sorry about the misunderstanding. I have not used a forum with software this ancient or with bright white theme since the 90's. So when i searched for old thread for help with development. I did not see the sigil part of the title.

In any case i actually know how to program in java script (embarrassing I know lol) and i'm a technical person i just do not have the time to learn python just to build this..

- it was a test anyway to see if it will work and so far it is kind of working ...
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>
So the AI kind of make me run around in circles but eventually it gets there
i was not interested in giving me full code just a hint about what is wrong or a code snippet but thanks anyway i will re post in the calibre section
myway880 is offline   Reply With Quote
Reply


Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Loading Plugin in development Sladd Development 6 06-17-2014 07:57 PM
Question for plugin development gurus DiapDealer Plugins 2 02-05-2012 12:33 AM
DR800 Plugin development for DR800/DR1000 yuri_b iRex Developer's Corner 0 09-18-2010 10:46 AM
Device plugin development reader42 Plugins 10 03-29-2010 01:39 PM
Calibre plugin development - Newbie problems minstrel Plugins 5 04-12-2009 01:44 PM


All times are GMT -4. The time now is 04:53 AM.


MobileRead.com is a privately owned, operated and funded community.