mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Migrated Add Books action
This commit is contained in:
parent
5d96982933
commit
82dc900a11
@ -5,8 +5,12 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
from functools import partial
|
||||
|
||||
from PyQt4.Qt import QToolButton, QAction, QIcon
|
||||
|
||||
from calibre.customize import InterfaceActionBase
|
||||
from calibre.gui2 import Dispatcher
|
||||
|
||||
class InterfaceAction(InterfaceActionBase):
|
||||
|
||||
@ -17,12 +21,31 @@ class InterfaceAction(InterfaceActionBase):
|
||||
positions = frozenset([])
|
||||
separators = frozenset([])
|
||||
|
||||
popup_type = QToolButton.MenuPopup
|
||||
|
||||
#: Of the form: (text, icon_path, tooltip, keyboard shortcut)
|
||||
#: tooltip and keybard shortcut can be None
|
||||
#: shortcut must be a translated string if not None
|
||||
action_spec = ('text', 'icon', None, None)
|
||||
|
||||
def do_genesis(self, gui):
|
||||
self.gui = gui
|
||||
self.Dispatcher = partial(Dispatcher, parent=gui)
|
||||
self.create_action()
|
||||
self.genesis()
|
||||
|
||||
# Subclassable methods {{{
|
||||
def genesis(self):
|
||||
raise NotImplementedError()
|
||||
# }}}
|
||||
def create_action(self):
|
||||
text, icon, tooltip, shortcut = self.action_spec
|
||||
action = QAction(QIcon(I(icon)), text, self)
|
||||
text = tooltip if tooltip else text
|
||||
action.setToolTip(text)
|
||||
action.setStatusTip(text)
|
||||
action.setWhatsThis(text)
|
||||
action.setAutoRepeat(False)
|
||||
if shortcut:
|
||||
action.setShortcut(shortcut)
|
||||
self.qaction = action
|
||||
|
||||
def genesis(self):
|
||||
pass
|
||||
|
||||
|
@ -8,10 +8,10 @@ __docformat__ = 'restructuredtext en'
|
||||
import os
|
||||
from functools import partial
|
||||
|
||||
from PyQt4.Qt import QInputDialog, QPixmap
|
||||
from PyQt4.Qt import QInputDialog, QPixmap, QMenu
|
||||
|
||||
|
||||
from calibre.gui2 import error_dialog, Dispatcher, choose_files, \
|
||||
from calibre.gui2 import error_dialog, choose_files, \
|
||||
choose_dir, warning_dialog, info_dialog
|
||||
from calibre.gui2.widgets import IMAGE_EXTENSIONS
|
||||
from calibre.ebooks import BOOK_EXTENSIONS
|
||||
@ -21,20 +21,41 @@ from calibre.gui2.actions import InterfaceAction
|
||||
|
||||
class AddAction(InterfaceAction):
|
||||
|
||||
name = 'Add Books'
|
||||
action_spec = (_('Add books'), 'add_book.svg', None, _('A'))
|
||||
positions = frozenset([
|
||||
('toolbar', 'all', 0),
|
||||
])
|
||||
|
||||
def genesis(self):
|
||||
self._add_filesystem_book = Dispatcher(self.__add_filesystem_book,
|
||||
parent=self.gui)
|
||||
self._add_filesystem_book = self.Dispatcher(self.__add_filesystem_book)
|
||||
self.add_menu = QMenu()
|
||||
self.add_menu.addAction(_('Add books from a single directory'),
|
||||
self.add_books)
|
||||
self.add_menu.addAction(_('Add books from directories, including '
|
||||
'sub-directories (One book per directory, assumes every ebook '
|
||||
'file is the same book in a different format)'),
|
||||
self.add_recursive_single)
|
||||
self.add_menu.addAction(_('Add books from directories, including '
|
||||
'sub directories (Multiple books per directory, assumes every '
|
||||
'ebook file is a different book)'), self.add_recursive_multiple)
|
||||
self.add_menu.addSeparator()
|
||||
self.add_menu.addAction(_('Add Empty book. (Book entry with no '
|
||||
'formats)'), self.add_empty)
|
||||
self.add_menu.addAction(_('Add from ISBN'), self.add_from_isbn)
|
||||
self.qaction.setMenu(self.add_menu)
|
||||
self.qaction.triggered.connect(self.add_books)
|
||||
|
||||
|
||||
def add_recursive(self, single):
|
||||
root = choose_dir(self, 'recursive book import root dir dialog',
|
||||
root = choose_dir(self.gui, 'recursive book import root dir dialog',
|
||||
'Select root folder')
|
||||
if not root:
|
||||
return
|
||||
from calibre.gui2.add import Adder
|
||||
self._adder = Adder(self,
|
||||
self.library_view.model().db,
|
||||
Dispatcher(self._files_added), spare_server=self.spare_server)
|
||||
self._adder = Adder(self.gui,
|
||||
self.gui.library_view.model().db,
|
||||
self.Dispatcher(self._files_added), spare_server=self.gui.spare_server)
|
||||
self._adder.add_recursive(root, single)
|
||||
|
||||
def add_recursive_single(self, *args):
|
||||
@ -56,13 +77,13 @@ class AddAction(InterfaceAction):
|
||||
Add an empty book item to the library. This does not import any formats
|
||||
from a book file.
|
||||
'''
|
||||
num, ok = QInputDialog.getInt(self, _('How many empty books?'),
|
||||
num, ok = QInputDialog.getInt(self.gui, _('How many empty books?'),
|
||||
_('How many empty books should be added?'), 1, 1, 100)
|
||||
if ok:
|
||||
from calibre.ebooks.metadata import MetaInformation
|
||||
for x in xrange(num):
|
||||
self.library_view.model().db.import_book(MetaInformation(None), [])
|
||||
self.library_view.model().books_added(num)
|
||||
self.gui.library_view.model().db.import_book(MetaInformation(None), [])
|
||||
self.gui.library_view.model().books_added(num)
|
||||
|
||||
def add_isbns(self, isbns):
|
||||
from calibre.ebooks.metadata import MetaInformation
|
||||
@ -70,21 +91,21 @@ class AddAction(InterfaceAction):
|
||||
for x in isbns:
|
||||
mi = MetaInformation(None)
|
||||
mi.isbn = x
|
||||
ids.add(self.library_view.model().db.import_book(mi, []))
|
||||
self.library_view.model().books_added(len(isbns))
|
||||
self.do_download_metadata(ids)
|
||||
ids.add(self.gui.library_view.model().db.import_book(mi, []))
|
||||
self.gui.library_view.model().books_added(len(isbns))
|
||||
self.gui.do_download_metadata(ids)
|
||||
|
||||
|
||||
def files_dropped(self, paths):
|
||||
to_device = self.stack.currentIndex() != 0
|
||||
to_device = self.gui.stack.currentIndex() != 0
|
||||
self._add_books(paths, to_device)
|
||||
|
||||
def files_dropped_on_book(self, event, paths):
|
||||
accept = False
|
||||
if self.current_view() is not self.library_view:
|
||||
if self.gui.current_view() is not self.gui.library_view:
|
||||
return
|
||||
db = self.library_view.model().db
|
||||
current_idx = self.library_view.currentIndex()
|
||||
db = self.gui.library_view.model().db
|
||||
current_idx = self.gui.library_view.currentIndex()
|
||||
if not current_idx.isValid(): return
|
||||
cid = db.id(current_idx.row())
|
||||
for path in paths:
|
||||
@ -102,7 +123,7 @@ class AddAction(InterfaceAction):
|
||||
accept = True
|
||||
if accept:
|
||||
event.accept()
|
||||
self.library_view.model().current_changed(current_idx, current_idx)
|
||||
self.gui.library_view.model().current_changed(current_idx, current_idx)
|
||||
|
||||
def __add_filesystem_book(self, paths, allow_device=True):
|
||||
if isinstance(paths, basestring):
|
||||
@ -111,10 +132,10 @@ class AddAction(InterfaceAction):
|
||||
os.R_OK)]
|
||||
|
||||
if books:
|
||||
to_device = allow_device and self.stack.currentIndex() != 0
|
||||
to_device = allow_device and self.gui.stack.currentIndex() != 0
|
||||
self._add_books(books, to_device)
|
||||
if to_device:
|
||||
self.status_bar.show_message(\
|
||||
self.gui.status_bar.show_message(\
|
||||
_('Uploading books to device.'), 2000)
|
||||
|
||||
|
||||
@ -123,7 +144,7 @@ class AddAction(InterfaceAction):
|
||||
|
||||
def add_from_isbn(self, *args):
|
||||
from calibre.gui2.dialogs.add_from_isbn import AddFromISBN
|
||||
d = AddFromISBN(self)
|
||||
d = AddFromISBN(self.gui)
|
||||
if d.exec_() == d.Accepted:
|
||||
self.add_isbns(d.isbns)
|
||||
|
||||
@ -144,11 +165,11 @@ class AddAction(InterfaceAction):
|
||||
(_('Comics'), ['cbz', 'cbr', 'cbc']),
|
||||
(_('Archives'), ['zip', 'rar']),
|
||||
]
|
||||
to_device = self.stack.currentIndex() != 0
|
||||
to_device = self.gui.stack.currentIndex() != 0
|
||||
if to_device:
|
||||
filters = [(_('Supported books'), self.device_manager.device.FORMATS)]
|
||||
filters = [(_('Supported books'), self.gui.device_manager.device.FORMATS)]
|
||||
|
||||
books = choose_files(self, 'add books dialog dir', 'Select books',
|
||||
books = choose_files(self.gui, 'add books dialog dir', 'Select books',
|
||||
filters=filters)
|
||||
if not books:
|
||||
return
|
||||
@ -156,32 +177,33 @@ class AddAction(InterfaceAction):
|
||||
|
||||
def _add_books(self, paths, to_device, on_card=None):
|
||||
if on_card is None:
|
||||
on_card = 'carda' if self.stack.currentIndex() == 2 else 'cardb' if self.stack.currentIndex() == 3 else None
|
||||
on_card = 'carda' if self.gui.stack.currentIndex() == 2 else \
|
||||
'cardb' if self.gui.stack.currentIndex() == 3 else None
|
||||
if not paths:
|
||||
return
|
||||
from calibre.gui2.add import Adder
|
||||
self.__adder_func = partial(self._files_added, on_card=on_card)
|
||||
self._adder = Adder(self,
|
||||
None if to_device else self.library_view.model().db,
|
||||
Dispatcher(self.__adder_func), spare_server=self.spare_server)
|
||||
self._adder = Adder(self.gui,
|
||||
None if to_device else self.gui.library_view.model().db,
|
||||
self.Dispatcher(self.__adder_func), spare_server=self.gui.spare_server)
|
||||
self._adder.add(paths)
|
||||
|
||||
def _files_added(self, paths=[], names=[], infos=[], on_card=None):
|
||||
if paths:
|
||||
self.upload_books(paths,
|
||||
self.gui.upload_books(paths,
|
||||
list(map(ascii_filename, names)),
|
||||
infos, on_card=on_card)
|
||||
self.status_bar.show_message(
|
||||
self.gui.status_bar.show_message(
|
||||
_('Uploading books to device.'), 2000)
|
||||
if getattr(self._adder, 'number_of_books_added', 0) > 0:
|
||||
self.library_view.model().books_added(self._adder.number_of_books_added)
|
||||
if hasattr(self, 'db_images'):
|
||||
self.db_images.reset()
|
||||
self.gui.library_view.model().books_added(self._adder.number_of_books_added)
|
||||
if hasattr(self.gui, 'db_images'):
|
||||
self.gui.db_images.reset()
|
||||
if getattr(self._adder, 'merged_books', False):
|
||||
books = u'\n'.join([x if isinstance(x, unicode) else
|
||||
x.decode(preferred_encoding, 'replace') for x in
|
||||
self._adder.merged_books])
|
||||
info_dialog(self, _('Merged some books'),
|
||||
info_dialog(self.gui, _('Merged some books'),
|
||||
_('Some duplicates were found and merged into the '
|
||||
'following existing books:'), det_msg=books, show=True)
|
||||
if getattr(self._adder, 'critical', None):
|
||||
@ -191,7 +213,7 @@ class AddAction(InterfaceAction):
|
||||
name = name.decode(filesystem_encoding, 'replace')
|
||||
det_msg.append(name+'\n'+log)
|
||||
|
||||
warning_dialog(self, _('Failed to read metadata'),
|
||||
warning_dialog(self.gui, _('Failed to read metadata'),
|
||||
_('Failed to read metadata from the following')+':',
|
||||
det_msg='\n\n'.join(det_msg), show=True)
|
||||
|
||||
@ -205,17 +227,17 @@ class AddAction(InterfaceAction):
|
||||
# set the in-library flags, and as a consequence send the library's
|
||||
# metadata for this book to the device. This sets the uuid to the
|
||||
# correct value.
|
||||
self.set_books_in_library(booklists=[model.db], reset=True)
|
||||
self.gui.set_books_in_library(booklists=[model.db], reset=True)
|
||||
model.reset()
|
||||
|
||||
def add_books_from_device(self, view):
|
||||
rows = view.selectionModel().selectedRows()
|
||||
if not rows or len(rows) == 0:
|
||||
d = error_dialog(self, _('Add to library'), _('No book selected'))
|
||||
d = error_dialog(self.gui, _('Add to library'), _('No book selected'))
|
||||
d.exec_()
|
||||
return
|
||||
paths = [p for p in view._model.paths(rows) if p is not None]
|
||||
ve = self.device_manager.device.VIRTUAL_BOOK_EXTENSIONS
|
||||
ve = self.gui.device_manager.device.VIRTUAL_BOOK_EXTENSIONS
|
||||
def ext(x):
|
||||
ans = os.path.splitext(x)[1]
|
||||
ans = ans[1:] if len(ans) > 1 else ans
|
||||
@ -223,21 +245,21 @@ class AddAction(InterfaceAction):
|
||||
remove = set([p for p in paths if ext(p) in ve])
|
||||
if remove:
|
||||
paths = [p for p in paths if p not in remove]
|
||||
info_dialog(self, _('Not Implemented'),
|
||||
info_dialog(self.gui, _('Not Implemented'),
|
||||
_('The following books are virtual and cannot be added'
|
||||
' to the calibre library:'), '\n'.join(remove),
|
||||
show=True)
|
||||
if not paths:
|
||||
return
|
||||
if not paths or len(paths) == 0:
|
||||
d = error_dialog(self, _('Add to library'), _('No book files found'))
|
||||
d = error_dialog(self.gui, _('Add to library'), _('No book files found'))
|
||||
d.exec_()
|
||||
return
|
||||
from calibre.gui2.add import Adder
|
||||
self.__adder_func = partial(self._add_from_device_adder, on_card=None,
|
||||
model=view._model)
|
||||
self._adder = Adder(self, self.library_view.model().db,
|
||||
Dispatcher(self.__adder_func), spare_server=self.spare_server)
|
||||
self._adder = Adder(self.gui, self.gui.library_view.model().db,
|
||||
self.Dispatcher(self.__adder_func), spare_server=self.gui.spare_server)
|
||||
self._adder.add(paths)
|
||||
|
||||
|
||||
|
@ -63,7 +63,8 @@ class LibraryViewMixin(object): # {{{
|
||||
add_to_library = None,
|
||||
edit_device_collections=None,
|
||||
similar_menu=similar_menu)
|
||||
add_to_library = (_('Add books to library'), self.add_books_from_device)
|
||||
add_to_library = (_('Add books to library'),
|
||||
self.iactions['Add Books'].add_books_from_device)
|
||||
|
||||
edit_device_collections = (_('Manage collections'),
|
||||
partial(self.edit_device_collections, oncard=None))
|
||||
@ -89,7 +90,7 @@ class LibraryViewMixin(object): # {{{
|
||||
add_to_library=add_to_library,
|
||||
edit_device_collections=edit_device_collections)
|
||||
|
||||
self.library_view.files_dropped.connect(self.files_dropped, type=Qt.QueuedConnection)
|
||||
self.library_view.files_dropped.connect(self.iactions['Add Books'].files_dropped, type=Qt.QueuedConnection)
|
||||
for func, args in [
|
||||
('connect_to_search_box', (self.search,
|
||||
self.search_done)),
|
||||
@ -305,7 +306,7 @@ class LayoutMixin(object): # {{{
|
||||
def finalize_layout(self):
|
||||
self.status_bar.initialize(self.system_tray_icon)
|
||||
self.book_details.show_book_info.connect(self.show_book_info)
|
||||
self.book_details.files_dropped.connect(self.files_dropped_on_book)
|
||||
self.book_details.files_dropped.connect(self.iactions['Add Books'].files_dropped_on_book)
|
||||
self.book_details.open_containing_folder.connect(self.view_folder_for_id)
|
||||
self.book_details.view_specific_format.connect(self.view_format_by_id)
|
||||
|
||||
|
@ -528,22 +528,6 @@ class MainWindowMixin(object):
|
||||
md.addSeparator()
|
||||
md.addAction(self.action_merge)
|
||||
|
||||
self.add_menu = QMenu()
|
||||
self.add_menu.addAction(_('Add books from a single directory'),
|
||||
self.add_books)
|
||||
self.add_menu.addAction(_('Add books from directories, including '
|
||||
'sub-directories (One book per directory, assumes every ebook '
|
||||
'file is the same book in a different format)'),
|
||||
self.add_recursive_single)
|
||||
self.add_menu.addAction(_('Add books from directories, including '
|
||||
'sub directories (Multiple books per directory, assumes every '
|
||||
'ebook file is a different book)'), self.add_recursive_multiple)
|
||||
self.add_menu.addSeparator()
|
||||
self.add_menu.addAction(_('Add Empty book. (Book entry with no '
|
||||
'formats)'), self.add_empty)
|
||||
self.add_menu.addAction(_('Add from ISBN'), self.add_from_isbn)
|
||||
self.action_add.setMenu(self.add_menu)
|
||||
self.action_add.triggered.connect(self.add_books)
|
||||
self.action_del.triggered.connect(self.delete_books)
|
||||
self.action_edit.triggered.connect(self.edit_metadata)
|
||||
self.action_merge.triggered.connect(self.merge_books)
|
||||
|
@ -155,7 +155,7 @@ class GuiRunner(QObject):
|
||||
main.initialize(self.library_path, self.db, self.listener, self.actions)
|
||||
if DEBUG:
|
||||
prints('Started up in', time.time() - self.startup_time)
|
||||
add_filesystem_book = partial(main.add_filesystem_book, allow_device=False)
|
||||
add_filesystem_book = partial(main.iactions['Add Books'].add_filesystem_book, allow_device=False)
|
||||
sys.excepthook = main.unhandled_exception
|
||||
if len(self.args) > 1:
|
||||
p = os.path.abspath(self.args[1])
|
||||
|
@ -329,7 +329,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{
|
||||
if len(argv) > 1:
|
||||
path = os.path.abspath(argv[1])
|
||||
if os.access(path, os.R_OK):
|
||||
self.add_filesystem_book(path)
|
||||
self.iactions['Add Books'].add_filesystem_book(path)
|
||||
self.setWindowState(self.windowState() & \
|
||||
~Qt.WindowMinimized|Qt.WindowActive)
|
||||
self.show_windows()
|
||||
|
Loading…
x
Reference in New Issue
Block a user