Register Guidelines E-Books Today's Posts Search

Go Back   MobileRead Forums > E-Book Software > Calibre > Development

Notices

Reply
 
Thread Tools Search this Thread
Old 02-01-2025, 08:58 AM   #1
Angeljo
Junior Member
Angeljo began at the beginning.
 
Posts: 1
Karma: 10
Join Date: Feb 2025
Device: Kindle Color
Help on a plugin which not appears in the Menu

Good morning. I am completely new to development in python and even more so in Calibre. I wanted, for my personal use, to prepare a small plugin that would allow me to manage the biography of an author, on several books at the same time. With the help of AI I made this plugin, which apparently integrates with Calibre because we see it in the plugin folder and also in Preferences>Plugins>User Interface Action. Unfortunately, I cannot test it, because it does not appear in the menu (despite the creation request). I searched in the different toolbars (in Preferences), in the shortcuts but without success. So maybe my code doesn't work, but I don't know because I can't test it. Sorry for my bad English: I am French speaking. And also sorry if my question is really stupid in your eyes: be lenient.
Could you tell me what I'm doing wrong?

here is the code for the 2 main files (the other 2, manifest.json and __init_.py are less important I believe):

1. ui.py

Code:
from PyQt5.QtWidgets import QDialog, QVBoxLayout, QLabel, QComboBox, QTextEdit, QPushButton
from calibre.gui2 import info_dialog
from calibre.gui2.dialogs.message_box import MessageBox

class BioManagerUI(QDialog):
    """
    Fenêtre pour gérer les biographies des auteurs.
    L'utilisateur sélectionne un auteur et saisit/modifie sa biographie.
    """
    def __init__(self, gui, parent=None):
        super(BioManagerUI, self).__init__(parent)
        self.gui = gui
        self.setWindowTitle("Gérer les biographies des auteurs")
        self.resize(500, 400)
        layout = QVBoxLayout(self)
        
        # Label et menu déroulant pour sélectionner un auteur
        label = QLabel("Sélectionnez un auteur :")
        layout.addWidget(label)
        self.combo = QComboBox(self)
        self.combo.addItems(self.get_authors())
        layout.addWidget(self.combo)
        
        # Zone de saisie pour la biographie (support HTML)
        self.text_edit = QTextEdit(self)
        self.text_edit.setAcceptRichText(True)
        layout.addWidget(self.text_edit)
        
        # Bouton pour enregistrer
        self.save_button = QPushButton("Enregistrer", self)
        self.save_button.clicked.connect(self.save_bio)
        layout.addWidget(self.save_button)
    
    def get_authors(self):
        """
        Récupère la liste de tous les auteurs présents dans la bibliothèque.
        """
        db_instance = self.gui.current_db
        authors = set()
        for book_id in db_instance.all_book_ids():
            mi = db_instance.get_metadata(book_id, index_is_id=True)
            if mi.authors:
                authors.update(mi.authors)
        return sorted(authors)
    
    def save_bio(self):
        """
        Enregistre la biographie pour l'auteur sélectionné.
        Si une biographie existe déjà, demande si l'utilisateur souhaite la remplacer ou l'ajouter.
        """
        db_instance = self.gui.current_db
        author = self.combo.currentText()
        new_bio = self.text_edit.toHtml().strip()
        count = 0
        existing_bio = ""
        for book_id in db_instance.all_book_ids():
            mi = db_instance.get_metadata(book_id, index_is_id=True)
            if mi.authors == [author]:
                existing_bio = db_instance.get_custom(book_id, "#auteurbio") or ""
                break
        if existing_bio:
            choice = MessageBox.question(
                self.gui,
                "Biographie existante",
                f"Une biographie existe déjà pour {author}.\nVoulez-vous la remplacer ou l'ajouter ?",
                "Remplacer", "Ajouter", "Annuler"
            )
            if choice == 2:
                return
            elif choice == 1:
                new_bio = existing_bio + "\n\n" + new_bio
        for book_id in db_instance.all_book_ids():
            mi = db_instance.get_metadata(book_id, index_is_id=True)
            if mi.authors == [author]:
                db_instance.set_custom(book_id, "#auteurbio", new_bio)
                count += 1
        info_dialog(self.gui, "Succès", f"Biographie mise à jour pour {count} livre(s) de {author}.", show=True)
        self. Accept()
2. plugin.py

Code:
import csv
import os, sys, subprocess, zipfile
from functools import partial

from calibre.constants import DEBUG, numeric_version as calibre_version
from calibre.gui2 import info_dialog, question_dialog, error_dialog, Dispatcher
from calibre.gui2.actions import InterfaceAction
from calibre.customize import InterfaceActionBase

#-----------------------------------------------
class BioManagerUpdate(InterfaceAction):
    name = 'bio_manager_action'
    action_spec = ('Gérer Biographies', None, 'Gérer les biographies des auteurs', None)
    action_type = 'global'
    accepts_drops = False
    auto_repeat = False
    priority = 9
    popup_type = 1

    def genesis(self):
        # On récupère la fenêtre principale
        self.maingui = self.gui
        # Créer un sous-menu "Biographies" dans le menu "Outils"
        self.menu = self.gui.main_window.menu.addMenu("Biographies")
        # Ajout de l'action au sous-menu avec un identifiant unique (ici, "_v2" pour forcer le changement)
        self.qaction.setText("Gérer Biographies")
        self.qaction.triggered.connect(self.open_ui)
        self.menu.addAction(self.qaction)
        # Ajout de l'action dans le menu "Outils" (si disponible)
        if hasattr(self.gui.main_window, 'menu_actions') and 'tools' in self.gui.main_window.menu_actions:
            self.gui.main_window.menu_actions['tools'].addAction(self.qaction)
        print("Plugin 'Gérer Biographies' chargé (v2).")

    def apply_settings(self):
        self.gui.add_action(self)

    def open_ui(self):
        try:
            from calibre_plugins.bio_manager.ui import BioManagerUI
        except ImportError:
            from ui import BioManagerUI
        ui = BioManagerUI(self.gui)
        ui.exec_()

#-----------------------------------------------
class BioManagerPlugin(InterfaceActionBase):
    name = "BioManager"
    description = "Un plugin pour gérer les biographies des auteurs dans Calibre"
    supported_platforms = ["windows", "osx", "linux"]
    author = "ChatGPT & Joëlle"
    version = (1, 0, 0)
    minimum_calibre_version = (5, 0)

    def load_actual_plugin(self, gui):
        self.actual_plugin = BioManagerUpdate(gui)
        gui.add_action(self.actual_plugin)

    def unload_actual_plugin(self):
        self.actual_plugin = None
Angeljo is offline   Reply With Quote
Old 02-01-2025, 09:42 AM   #2
kovidgoyal
creator of calibre
kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.
 
kovidgoyal's Avatar
 
Posts: 45,337
Karma: 27182818
Join Date: Oct 2006
Location: Mumbai, India
Device: Various
Run calibre as

calibre-debug -g

and if there are any errors they will be printed out to the console.
kovidgoyal is offline   Reply With Quote
Advert
Old 02-02-2025, 08:57 AM   #3
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,559
Karma: 204127028
Join Date: Jan 2010
Device: Nexus 7, Kindle Fire HD
If you're running any relatively recent version of Calibre, your problem is the first line of ui.py:

from PyQt5.QtWidgets import ...

Calibre moved to PyQt6 quite a while ago. There's ways to support both old and new, but your method of directly importing PyQt5 modules will not work.
DiapDealer is online now   Reply With Quote
Old 02-02-2025, 03:56 PM   #4
dunhill
Guru
dunhill ought to be getting tired of karma fortunes by now.dunhill ought to be getting tired of karma fortunes by now.dunhill ought to be getting tired of karma fortunes by now.dunhill ought to be getting tired of karma fortunes by now.dunhill ought to be getting tired of karma fortunes by now.dunhill ought to be getting tired of karma fortunes by now.dunhill ought to be getting tired of karma fortunes by now.dunhill ought to be getting tired of karma fortunes by now.dunhill ought to be getting tired of karma fortunes by now.dunhill ought to be getting tired of karma fortunes by now.dunhill ought to be getting tired of karma fortunes by now.
 
dunhill's Avatar
 
Posts: 892
Karma: 810834
Join Date: Sep 2017
Location: Buenos Aires, Argentina
Device: moon+ reader, kindle paperwhite
There are two of us investigating this new world. The script I sent was written in python but I added a tkinter interface. Now I modified it to qt6 but I can't put it together in a plugin. There should be a novice-proof thread for plugin creation.
dunhill is offline   Reply With Quote
Old 02-02-2025, 04:22 PM   #5
Terisa de morgan
Grand Sorcerer
Terisa de morgan ought to be getting tired of karma fortunes by now.Terisa de morgan ought to be getting tired of karma fortunes by now.Terisa de morgan ought to be getting tired of karma fortunes by now.Terisa de morgan ought to be getting tired of karma fortunes by now.Terisa de morgan ought to be getting tired of karma fortunes by now.Terisa de morgan ought to be getting tired of karma fortunes by now.Terisa de morgan ought to be getting tired of karma fortunes by now.Terisa de morgan ought to be getting tired of karma fortunes by now.Terisa de morgan ought to be getting tired of karma fortunes by now.Terisa de morgan ought to be getting tired of karma fortunes by now.Terisa de morgan ought to be getting tired of karma fortunes by now.
 
Terisa de morgan's Avatar
 
Posts: 6,627
Karma: 12595249
Join Date: Jun 2009
Location: Madrid, Spain
Device: Kobo Clara/Aura One/Forma,XiaoMI 5, iPad, Huawei MediaPad, YotaPhone 2
I'm betting that the problem is there is an error in initialization of the plugin (by any method) and because of that it doesn't appear in the menu as it's not healthy. The best option is to debug it.
Terisa de morgan is offline   Reply With Quote
Advert
Reply


Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
[GUI Plugin] Favourites Menu kiwidude Plugins 119 03-30-2024 07:10 PM
plugin menu case AlanHK Sigil 21 09-19-2019 12:18 AM
Plugin icon appears 3X in toolbar eggheadbooks1 Sigil 6 11-17-2016 07:04 PM
Docx plugin appears, but never installed. Section8 Plugins 4 06-19-2013 12:42 AM
Plugin Menu Layout DoctorOhh Plugins 6 03-30-2011 03:51 AM


All times are GMT -4. The time now is 08:52 AM.


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