Add action to context menu to copy selected books to another library

This commit is contained in:
Kovid Goyal 2010-08-19 19:57:04 -06:00
parent 88618d085c
commit f61c197194
3 changed files with 116 additions and 5 deletions

View File

@ -5,9 +5,57 @@ __license__ = 'GPL v3'
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
from functools import partial
from threading import Thread
from PyQt4.Qt import QMenu, QToolButton
from calibre.gui2.actions import InterfaceAction
from calibre.gui2 import error_dialog, Dispatcher
from calibre.gui2.dialogs.progress import ProgressDialog
class Worker(Thread):
def __init__(self, ids, db, loc, progress, done):
Thread.__init__(self)
self.ids = ids
self.db = db
self.loc = loc
self.error = None
self.progress = progress
self.done = done
def run(self):
try:
self.doit()
except Exception, err:
import traceback
try:
err = unicode(err)
except:
err = repr(err)
self.error = (err, traceback.format_exc())
self.done()
def doit(self):
from calibre.library.database2 import LibraryDatabase2
newdb = LibraryDatabase2(self.loc)
for i, x in enumerate(self.ids):
mi = self.db.get_metadata(x, index_is_id=True, get_cover=True)
self.progress(i, mi.title)
fmts = self.db.formats(x, index_is_id=True)
if not fmts: fmts = []
else: fmts = fmts.split(',')
paths = [self.db.format_abspath(x, fmt, index_is_id=True) for fmt in
fmts]
newdb.import_book(mi, paths, notify=False, import_hooks=False)
co = self.db.conversion_options(x, 'PIPE')
if co is not None:
newdb.set_conversion_options(x, 'PIPE', co)
class CopyToLibraryAction(InterfaceAction):
@ -18,5 +66,63 @@ class CopyToLibraryAction(InterfaceAction):
def genesis(self):
self.menu = QMenu(self.gui)
self.qaction.setMenu(self.menu)
@property
def stats(self):
return self.gui.iactions['Choose Library'].stats
def library_changed(self, db):
self.build_menus()
def initialization_complete(self):
self.library_changed(self.gui.library_view.model().db)
def location_selected(self, loc):
enabled = loc == 'library'
self.qaction.setEnabled(enabled)
def build_menus(self):
self.menu.clear()
db = self.gui.library_view.model().db
locations = list(self.stats.locations(db))
for name, loc in locations:
self.menu.addAction(name, partial(self.copy_to_library,
loc))
self.qaction.setVisible(bool(locations))
def copy_to_library(self, loc):
rows = self.gui.library_view.selectionModel().selectedRows()
if not rows or len(rows) == 0:
return error_dialog(self.gui, _('Cannot copy'),
_('No books selected'), show=True)
ids = list(map(self.gui.library_view.model().id, rows))
db = self.gui.library_view.model().db
if not db.exists_at(loc):
return error_dialog(self.gui, _('No library'),
_('No library found at %s')%loc, show=True)
self.pd = ProgressDialog(_('Copying'), min=0, max=len(ids)-1,
parent=self.gui, cancelable=False)
def progress(idx, title):
self.pd.set_msg(_('Copying') + ' ' + title)
self.pd.set_value(idx)
self.worker = Worker(ids, db, loc, Dispatcher(progress), Dispatcher(self.pd.accept))
self.worker.start()
self.pd.exec_()
if self.worker.error is not None:
e, tb = self.worker.error
error_dialog(self.gui, _('Failed'), _('Could not copy books: ') + e,
det_msg=tb, show=True)
else:
self.gui.status_bar.show_message(_('Copied %d books to %s') %
(len(ids), loc), 2000)

View File

@ -28,9 +28,10 @@ def partial(*args, **kwargs):
return ans
LIBRARY_CONTEXT_MENU = (
'Edit Metadata', 'Send To Device', 'Save To Disk', 'Connect Share', None,
'Convert Books', 'View', 'Open Folder', 'Show Book Details', None,
'Remove Books',
'Edit Metadata', 'Send To Device', 'Save To Disk',
'Connect Share', 'Copy To Library', None,
'Convert Books', 'View', 'Open Folder', 'Show Book Details',
'Similar Books', None, 'Remove Books',
)
DEVICE_CONTEXT_MENU = ('View', 'Save To Disk', None, 'Remove Books', None,

View File

@ -1754,7 +1754,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
return (paths, formats, metadata), len(ids)
return None, len(ids)
def import_book(self, mi, formats, notify=True):
def import_book(self, mi, formats, notify=True, import_hooks=True):
series_index = 1.0 if mi.series_index is None else mi.series_index
if not mi.title:
mi.title = _('Unknown')
@ -1779,7 +1779,11 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
ext = os.path.splitext(path)[1][1:].lower()
if ext == 'opf':
continue
self.add_format_with_hooks(id, ext, path, index_is_id=True)
if import_hooks:
self.add_format_with_hooks(id, ext, path, index_is_id=True)
else:
with open(path, 'rb') as f:
self.add_format(id, ext, f, index_is_id=True)
self.conn.commit()
self.data.refresh_ids(self, [id]) # Needed to update format list and size
if notify: