View Single Post
Old 05-13-2022, 01:05 AM   #854
capink
Wizard
capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.
 
Posts: 1,203
Karma: 1995558
Join Date: Aug 2015
Device: Kindle
Quote:
Originally Posted by un_pogaz View Post
Hey, a make a module.
The purpose of this module is to update the title and/or author sorting key, like the options in the Bulk Metadata dialog, options that are unavailable via Action Chains (I won't open the huge Bulk Metadata dialog just to check the same 2 options everytime => go on to make a non-interactive module).

I remember you had created a thread to reference different user modules (and other event managers), but I couldn't find it.
If it exists, it would be nice to have an explicit link in the description (so that we can look for it before breaking our heads to do things ourselves, especially if we don't understand anything in code)

Here is the code of the module:
EDIT: code moved into the dedicated thread
Thanks for your contribution. I added a link to your module in the first post of the Action Chains Scripts thread.

One suggestion I have is to make the action support the scopes feature as illustrated in the code below (modifications highlighted in blue)

Code:
import os, copy

try:
    from qt.core import (QApplication, Qt, QWidget, QGridLayout, QHBoxLayout, QVBoxLayout,
                            QGroupBox, QCheckBox)
except ImportError:
    from PyQt5.Qt import (QApplication, Qt, QWidget, QGridLayout, QHBoxLayout, QVBoxLayout,
                            QGroupBox, QCheckBox)

from calibre import prints
from calibre.constants import DEBUG

from calibre_plugins.action_chains.actions.base import ChainAction

class BulkSortKeyAction(ChainAction):
    
    # the name of your action
    name = 'Bulk Sort Key'
    
    support_scopes = True
    
    def run(self, gui, settings, chain):
        
        cache = gui.current_db.new_api
        self.ids = chain.scope().get_book_ids()
        #self.ids = gui.current_view().selectionModel().selectedRows()
        if not self.ids or len(self.ids) == 0:
            return
        #self.ids = gui.library_view.get_selected_ids()
        
        if settings.get(KEY.SORT_TITLE, DEFAULT[KEY.SORT_TITLE]):
            from calibre.ebooks.metadata import title_sort
            
            lang_map = cache.all_field_for('languages', self.ids)
            title_map = cache.all_field_for('title', self.ids)
            
            def get_sort(book_id):
                try:
                    lang = lang_map[book_id][0]
                except (KeyError, IndexError, TypeError, AttributeError):
                    lang = DEFAULT_LANG
                return title_sort(title_map[book_id], lang=lang)
            
            cache.set_field('sort', {bid:get_sort(bid) for bid in self.ids})
        
        if settings.get(KEY.SORT_AUTHOR, DEFAULT[KEY.SORT_AUTHOR]):
            author_sort_map = cache.author_sort_strings_for_books(self.ids)
            cache.set_field('author_sort', {book_id: ' & '.join(author_sort_map[book_id]) for book_id in author_sort_map})


    def config_widget(self):
        return ConfigWidget

class KEY:
    SORT_AUTHOR = 'sort_author'
    SORT_TITLE = 'sort_title'

DEFAULT = {}
DEFAULT[KEY.SORT_AUTHOR] = True
DEFAULT[KEY.SORT_TITLE] = True

#set DEFAULT_LANG title sort to the user interface
def get_iso_language():
    from calibre.utils.localization import set_translators, _load_iso639
    iso639 = _load_iso639()
    rslt = 'eng'
    lang = set_translators.lang.split('_')[0].lower()
    if len(lang) == 3:
        if lang in iso639['codes3']:
            rslt = lang
    elif len(lang) == 2:
        rslt = iso639['2to3'].get(lang, rslt)
    elif len(lang) > 3:
        rslt = iso639['name_map'].get(lang, rslt)
    return rslt
DEFAULT_LANG = get_iso_language()

class ConfigWidget(QWidget):
    def __init__(self, plugin_action):
        QWidget.__init__(self)
        self.plugin_action = plugin_action
        self.gui = plugin_action.gui
        self.db = self.gui.current_db
        self._init_controls()

    def _init_controls(self):
        l = self.l = QVBoxLayout()
        self.setLayout(l)
        
        gb_opts = QGroupBox(_("Options"), self)
        l.addWidget(gb_opts)
        l_opts = QVBoxLayout()
        gb_opts.setLayout(l_opts)
        
        self.chk_sort_author = QCheckBox(_("A&utomatically set author sort"))
        self.chk_sort_author.setChecked(DEFAULT[KEY.SORT_AUTHOR])
        self.chk_sort_author.setToolTip(_("This will cause the author sort field to be automatically updated\n"
                                            " based on the authors field for each selected book. Note that if\n"
                                            " you use the control above to set authors in bulk, the author sort\n"
                                            " field is updated anyway, regardless of the value of this checkbox."))
        l_opts.addWidget(self.chk_sort_author)
        
        self.chk_sort_title = QCheckBox(_("Update &title sort"))
        self.chk_sort_title.setChecked(DEFAULT[KEY.SORT_TITLE])
        self.chk_sort_title.setToolTip(_("Update title sort based on the current title. This will be applied only after other changes to title."))
        l_opts.addWidget(self.chk_sort_title)
        
        l.addStretch(1)
        
        self.setMinimumSize(300,100)

    def load_settings(self, settings):
        if not settings:
            settings = copy.deepcopy(DEFAULT)
        
        self.chk_sort_author.setChecked(settings.get(KEY.SORT_AUTHOR, DEFAULT[KEY.SORT_AUTHOR]))
        self.chk_sort_title.setChecked(settings.get(KEY.SORT_TITLE, DEFAULT[KEY.SORT_TITLE]))

    def save_settings(self):
        settings = {}
        settings[KEY.SORT_AUTHOR] = self.chk_sort_author.isChecked()
        settings[KEY.SORT_TITLE] = self.chk_sort_title.isChecked()
        return settings
capink is offline   Reply With Quote