Allow adding files to selected book records from the clipboard. To use copy a file from windows explorer, right click the Add books button and choose: Add files to selected books from clipboard

See #1815419 ([Enhancement] New option for calibre command)
This commit is contained in:
Kovid Goyal 2019-03-07 14:17:10 +05:30
parent b523de9813
commit 59ec0ad2a7
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C

View File

@ -9,9 +9,9 @@ import os
from functools import partial from functools import partial
from collections import defaultdict from collections import defaultdict
from PyQt5.Qt import QPixmap, QTimer from PyQt5.Qt import QPixmap, QTimer, QApplication
from calibre import as_unicode from calibre import as_unicode, guess_type
from calibre.gui2 import (error_dialog, choose_files, choose_dir, from calibre.gui2 import (error_dialog, choose_files, choose_dir,
warning_dialog, info_dialog, gprefs) warning_dialog, info_dialog, gprefs)
from calibre.gui2.dialogs.add_empty_book import AddEmptyBookDialog from calibre.gui2.dialogs.add_empty_book import AddEmptyBookDialog
@ -78,6 +78,8 @@ class AddAction(InterfaceAction):
self.add_menu.addSeparator() self.add_menu.addSeparator()
ma('add-formats', _('Add files to selected book records'), ma('add-formats', _('Add files to selected book records'),
triggered=self.add_formats, shortcut='Shift+A') triggered=self.add_formats, shortcut='Shift+A')
ma('add-formats-clipboard', _('Add files to selected book records from clipboard'),
triggered=self.add_formats_from_clipboard, shortcut='Shift+Alt+A')
arm = self.add_archive_menu = self.add_menu.addMenu(_('Add an empty file to selected book records')) arm = self.add_archive_menu = self.add_menu.addMenu(_('Add an empty file to selected book records'))
from calibre.ebooks.oeb.polish.create import valid_empty_formats from calibre.ebooks.oeb.polish.create import valid_empty_formats
for fmt in sorted(valid_empty_formats): for fmt in sorted(valid_empty_formats):
@ -100,16 +102,64 @@ class AddAction(InterfaceAction):
initial_plugin=('Import/Export', 'Adding'), initial_plugin=('Import/Export', 'Adding'),
close_after_initial=True) close_after_initial=True)
def add_formats(self, *args): def _check_add_formats_ok(self):
if self.gui.stack.currentIndex() != 0: if self.gui.current_view() is not self.gui.library_view:
return return []
view = self.gui.library_view view = self.gui.library_view
rows = view.selectionModel().selectedRows() rows = view.selectionModel().selectedRows()
if not rows: if not rows:
return error_dialog(self.gui, _('No books selected'), error_dialog(self.gui, _('No books selected'),
_('Cannot add files as no books are selected'), show=True) _('Cannot add files as no books are selected'), show=True)
ids = [view.model().id(r) for r in rows] ids = [view.model().id(r) for r in rows]
return ids
def add_formats_from_clipboard(self):
ids = self._check_add_formats_ok()
if not ids:
return
md = QApplication.instance().clipboard().mimeData()
files_to_add = []
images = []
if md.hasUrls():
for url in md.urls():
if url.isLocalFile():
path = url.toLocalFile()
if os.access(path, os.R_OK):
mt = guess_type(path)[0]
if mt.startswith('image/'):
images.append(path)
else:
files_to_add.append(path)
if not files_to_add and not images:
return error_dialog(self.gui, _('No files in clipboard'),
_('No files have been copied to the clipboard'), show=True)
if files_to_add:
self._add_formats(files_to_add, ids)
if images:
if len(ids) > 1 and not question_dialog(
self.gui,
_('Are you sure?'),
_('Are you sure you want to set the same'
' cover for all %d books?')%len(ids)):
return
with lopen(images[0], 'rb') as f:
cdata = f.read()
self.gui.current_db.new_api.set_cover({book_id: cdata for book_id in ids})
self.gui.refresh_cover_browser()
m = self.gui.library_view.model()
current = self.gui.library_view.currentIndex()
m.current_changed(current, current)
def add_formats(self, *args):
ids = self._check_add_formats_ok()
if not ids:
return
books = choose_files(self.gui, 'add formats dialog dir',
_('Select book files'), filters=get_filters())
if books:
self._add_formats(books, ids)
def _add_formats(self, paths, ids):
if len(ids) > 1 and not question_dialog( if len(ids) > 1 and not question_dialog(
self.gui, self.gui,
_('Are you sure?'), _('Are you sure?'),
@ -118,17 +168,12 @@ class AddAction(InterfaceAction):
' already exists for a book, it will be replaced.')%len(ids)): ' already exists for a book, it will be replaced.')%len(ids)):
return return
books = choose_files(self.gui, 'add formats dialog dir', db = self.gui.current_db
_('Select book files'), filters=get_filters())
if not books:
return
db = view.model().db
if len(ids) == 1: if len(ids) == 1:
formats = db.formats(ids[0], index_is_id=True) formats = db.formats(ids[0], index_is_id=True)
if formats: if formats:
formats = {x.upper() for x in formats.split(',')} formats = {x.upper() for x in formats.split(',')}
nformats = {f.rpartition('.')[-1].upper() for f in books} nformats = {f.rpartition('.')[-1].upper() for f in paths}
override = formats.intersection(nformats) override = formats.intersection(nformats)
if override: if override:
title = db.title(ids[0], index_is_id=True) title = db.title(ids[0], index_is_id=True)
@ -139,7 +184,7 @@ class AddAction(InterfaceAction):
if not confirm(msg, 'confirm_format_override_on_add', title=_('Are you sure?'), parent=self.gui): if not confirm(msg, 'confirm_format_override_on_add', title=_('Are you sure?'), parent=self.gui):
return return
fmt_map = {os.path.splitext(fpath)[1][1:].upper():fpath for fpath in books} fmt_map = {os.path.splitext(fpath)[1][1:].upper():fpath for fpath in paths}
for id_ in ids: for id_ in ids:
for fmt, fpath in fmt_map.iteritems(): for fmt, fpath in fmt_map.iteritems():
@ -148,7 +193,7 @@ class AddAction(InterfaceAction):
notify=True) notify=True)
current_idx = self.gui.library_view.currentIndex() current_idx = self.gui.library_view.currentIndex()
if current_idx.isValid(): if current_idx.isValid():
view.model().current_changed(current_idx, current_idx) self.gui.library_view.model().current_changed(current_idx, current_idx)
def add_empty_format(self, format_): def add_empty_format(self, format_):
if self.gui.stack.currentIndex() != 0: if self.gui.stack.currentIndex() != 0: