Code:
#!/usr/bin/env python
# ~*~ coding: utf-8 ~*~
__license__ = 'GPL v3'
__copyright__ = '2021, Ahmed Zaki <azaki00.dev@gmail.com>'
__docformat__ = 'restructuredtext en'
from functools import partial
from qt.core import (QApplication, Qt, QTimer, QWidget, QVBoxLayout, QCheckBox, pyqtSignal)
from calibre import prints
from calibre.constants import DEBUG
from calibre.db.listeners import EventType
from calibre.utils.date import now
from calibre_plugins.action_chains.events.base import ChainEvent
import calibre_plugins.action_chains.config as cfg
try:
load_translations()
except NameError:
prints("ActionChains::events/books_added.py - exception when loading translations")
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)
self.select_chk = QCheckBox(_('Select newly added books'))
self.select_chk.setChecked(True)
l.addWidget(self.select_chk)
l.addStretch(1)
self.setMinimumSize(300,300)
def load_settings(self, settings):
if settings:
self.select_chk.setChecked(settings.get('select_books', False))
def save_settings(self):
settings = {}
settings['select_books'] = self.select_chk.isChecked()
return settings
class BooksAddedEvent(ChainEvent):
name = 'Books Added'
books_added = pyqtSignal(object)
timer_interval = 30
def __init__(self, plugin_action):
ChainEvent.__init__(self, plugin_action)
self.db = plugin_action.gui.current_db
self.gui.add_db_listener(self.process_event_in_db)
self.book_created_cache = set()
self.book_created_cache_last_updated = None
QTimer.singleShot(self.timer_interval * 1000, self._on_timeout)
def process_event_in_db(self, db, event_type, event_data):
if not db.library_id == self.gui.current_db.library_id:
return
if event_type == EventType.book_created:
book_id = event_data[0]
self.add_to_book_created_cache(book_id, now())
elif event_type == EventType.books_removed:
removed_book_ids = event_data[0]
self.book_created_cache = self.book_created_cache.difference(set(removed_book_ids))
def _on_timeout(self):
# Make sure no modal widget dialog is present (e.g. add books duplicate dialog). Otherwise, postpone
if QApplication.instance().activeModalWidget():
pass
# postpone event if another action chains is running
elif self.plugin_action.chainStack:
pass
else:
utime = self.book_created_cache_last_updated
if utime:
elapsed = now() - utime
# Wait for some seconds to make sure all books are added. If books are added by calibre
# auto-add, there will not be a modal dialog, so we have to wait a little to make sure
# auto-add finished adding all the books
wait_time = 20
if elapsed.total_seconds() > wait_time:
QTimer.singleShot(0, partial(self.books_added.emit, self.book_created_cache))
QTimer.singleShot(0, self.clean_book_created_cache)
# keep the timer runnig
QTimer.singleShot(self.timer_interval * 1000, self._on_timeout)
def add_to_book_created_cache(self, book_id, timestamp):
self.book_created_cache.add(book_id)
self.book_created_cache_last_updated = timestamp
def clean_book_created_cache(self):
self.book_created_cache = set()
self.book_created_cache_last_updated = None
def get_event_signal(self):
return self.books_added
def config_widget(self):
return ConfigWidget
def pre_chains_event_actions(self, event_args, event_opts):
if event_opts.get('select_books', False):
book_ids = event_args[0]
self.gui.library_view.select_rows(book_ids)
if DEBUG:
prints('Action Chains: Books Added Event: Selecting newly added book_ids: {}')
After adding this you should have an event called "Books Added" in the dropdown list of the Event Manager. You can attach whatever chains you want to that event.
Notes:- The event will automatically select all added books, so that any chains attached to the event can act on them. If whatever reason you don't want this, you can turn it off (Event Manager > Books Added > Event options)
- There is a lag of several seconds before the event is activated. This is done to ensure calibre's adder (and auto-adder) has added all the books.
- You can attach one or more chain(s) to the event: Event Manager > Add Event > Books Added > click settings button next to the event.
- Whenever you change the name of a chain attached to an event, you will need to open the Event Manager to re-attach it.