Clean up the Add books menu

This commit is contained in:
Kovid Goyal 2020-02-06 20:19:02 +05:30
parent 4dc41f8929
commit 3e8adced66
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 46 additions and 26 deletions

View File

@ -47,9 +47,7 @@ Add books
1. **Add books from a single directory**: Opens a file chooser dialog and allows you to specify which books in a directory should be added. This action is *context sensitive*, i.e. it depends on which :ref:`catalog <catalogs>` you have selected. If you have selected the :guilabel:`Library`, books will be added to the library. If you have selected the e-book reader device, the books will be uploaded to the device, and so on. 1. **Add books from a single directory**: Opens a file chooser dialog and allows you to specify which books in a directory should be added. This action is *context sensitive*, i.e. it depends on which :ref:`catalog <catalogs>` you have selected. If you have selected the :guilabel:`Library`, books will be added to the library. If you have selected the e-book reader device, the books will be uploaded to the device, and so on.
2. **Add books from directories, including sub-directories (One book per directory, assumes every e-book file is the same book in a different format)**: Allows you to choose a directory. The directory and all its sub-directories are scanned recursively, and any e-books found are added to the library. calibre assumes that each directory contains a single book. All e-book files in a directory are assumed to be the same book in different formats. This action is the inverse of the :ref:`Save to disk <save_to_disk_multiple>` action, i.e. you can :guilabel:`Save to disk`, delete the books and re-add them with no lost information except for the date (this assumes you have not changed any of the setting for the Save to disk action). 2. **Add books from directories and sub-directories**: Allows you to choose a directory. The directory and all its sub-directories are scanned recursively, and any e-books found are added to the library. You can choose whether to have calibre add all files present in a single directory to a single book record or multiple book records. calibre assumes that each directory contains a single book. All e-book files in a directory are assumed to be the same book in different formats. This action is the inverse of the :ref:`Save to disk <save_to_disk_multiple>` action, i.e. you can :guilabel:`Save to disk`, delete the books and re-add them in single book per directory mode, with no lost information except for the date (this assumes you have not changed any of the setting for the Save to disk action).
3. **Add books from directories, including sub-directories (Multiple books per directory, assumes every e-book file is a different book)**: Allows you to choose a directory. The directory and all its sub-directories are scanned recursively and any e-books found are added to the library. calibre assumes that each directory contains many books. All e-book files with the same name in a directory are assumed to be the same book in different formats. E-books with different names are added as different books.
4. **Add multiple books from archive (ZIP/RAR)**: Allows you to add multiple e-books that are stored inside the selected ZIP or RAR files. It is a convenient shortcut that avoids having to first unzip the archive and then add the books via one of the above two options. 4. **Add multiple books from archive (ZIP/RAR)**: Allows you to add multiple e-books that are stored inside the selected ZIP or RAR files. It is a convenient shortcut that avoids having to first unzip the archive and then add the books via one of the above two options.

View File

@ -58,21 +58,8 @@ class AddAction(InterfaceAction):
self._add_filesystem_book = self.Dispatcher(self.__add_filesystem_book) self._add_filesystem_book = self.Dispatcher(self.__add_filesystem_book)
self.add_menu = self.qaction.menu() self.add_menu = self.qaction.menu()
ma = partial(self.create_menu_action, self.add_menu) ma = partial(self.create_menu_action, self.add_menu)
ma('recursive-single', _('Add books from directories, including ' ma('recursive-add', _('Add from directories and sub-directories')).triggered.connect(self.add_recursive_question)
'sub-directories (One book per directory, assumes every e-book ' ma('archive-add-book', _('Add multiple books from archive (ZIP/RAR)')).triggered.connect(self.add_from_archive)
'file is the same book in a different format)')).triggered.connect(
self.add_recursive_single)
ma('recursive-multiple', _('Add books from directories, including '
'sub-directories (Multiple books per directory, assumes every '
'e-book file is a different book)')).triggered.connect(
self.add_recursive_multiple)
arm = self.add_archive_menu = self.add_menu.addMenu(_('Add multiple books from archive (ZIP/RAR)'))
connect_lambda(self.create_menu_action(
arm, 'recursive-single-archive', _('One book per directory in the archive')).triggered,
self, lambda self: self.add_archive(True))
connect_lambda(self.create_menu_action(
arm, 'recursive-multiple-archive', _('Multiple books per directory in the archive')).triggered,
self, lambda self: self.add_archive(False))
self.add_menu.addSeparator() self.add_menu.addSeparator()
ma('add-empty', _('Add empty book (Book entry with no formats)'), ma('add-empty', _('Add empty book (Book entry with no formats)'),
shortcut='Shift+Ctrl+E').triggered.connect(self.add_empty) shortcut='Shift+Ctrl+E').triggered.connect(self.add_empty)
@ -82,16 +69,11 @@ class AddAction(InterfaceAction):
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'), ma('add-formats-clipboard', _('Add files to selected book records from clipboard'),
triggered=self.add_formats_from_clipboard, shortcut='Shift+Alt+A') 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')) ma('add-empty-format-to-books', _(
from calibre.ebooks.oeb.polish.create import valid_empty_formats 'Add an empty file to selected book records')).triggered.connect(self.add_empty_format_choose)
for fmt in sorted(valid_empty_formats):
ac = self.create_menu_action(arm, 'add-empty-' + fmt, _('Add empty {}').format(fmt.upper()))
ac.setObjectName(fmt)
connect_lambda(ac.triggered, self, lambda self: self.add_empty_format(self.gui.sender().objectName()))
self.add_menu.addSeparator() self.add_menu.addSeparator()
ma('add-config', _('Control the adding of books'), ma('add-config', _('Control the adding of books'),
triggered=self.add_config) triggered=self.add_config)
self.qaction.triggered.connect(self.add_books) self.qaction.triggered.connect(self.add_books)
def location_selected(self, loc): def location_selected(self, loc):
@ -197,7 +179,7 @@ class AddAction(InterfaceAction):
if current_idx.isValid(): if current_idx.isValid():
self.gui.library_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 is_ok_to_add_empty_formats(self):
if self.gui.stack.currentIndex() != 0: if self.gui.stack.currentIndex() != 0:
return return
view = self.gui.library_view view = self.gui.library_view
@ -215,7 +197,27 @@ class AddAction(InterfaceAction):
' empty file to all %d books? If the format' ' empty file to all %d books? If the format'
' already exists for a book, it will be replaced.')%len(ids)): ' already exists for a book, it will be replaced.')%len(ids)):
return return
return True
def add_empty_format_choose(self):
if not self.is_ok_to_add_empty_formats():
return
from calibre.ebooks.oeb.polish.create import valid_empty_formats
from calibre.gui2.dialogs.choose_format import ChooseFormatDialog
d = ChooseFormatDialog(self.gui, _('Choose format of empty file'), sorted(valid_empty_formats))
if d.exec_() != d.Accepted or not d.format():
return
self._add_empty_format(d.format())
def add_empty_format(self, format_):
if not self.is_ok_to_add_empty_formats():
return
self._add_empty_format(format_)
def _add_empty_format(self, format_):
view = self.gui.library_view
rows = view.selectionModel().selectedRows()
ids = [view.model().id(r) for r in rows]
db = self.gui.library_view.model().db db = self.gui.library_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)
@ -252,6 +254,15 @@ class AddAction(InterfaceAction):
if paths: if paths:
self.do_add_recursive(paths, single, list_of_archives=True) self.do_add_recursive(paths, single, list_of_archives=True)
def add_from_archive(self):
single = question_dialog(self.gui, _('Type of archive'), _(
'Will the archive have a single book per internal directory?'))
paths = choose_files(
self.gui, 'recursive-archive-add', _('Choose archive file'),
filters=[(_('Archives'), ('zip', 'rar'))], all_files=False, select_only_single_file=False)
if paths:
self.do_add_recursive(paths, single, list_of_archives=True)
def add_recursive(self, single): def add_recursive(self, single):
root = choose_dir(self.gui, 'recursive book import root dir dialog', root = choose_dir(self.gui, 'recursive book import root dir dialog',
_('Select root folder')) _('Select root folder'))
@ -282,6 +293,11 @@ class AddAction(InterfaceAction):
''' '''
self.add_recursive(False) self.add_recursive(False)
def add_recursive_question(self):
single = question_dialog(self.gui, _('Multi-file books?'), _(
'Assume all e-book files in a directory are the same book in different formats?'))
self.add_recursive(single)
def add_empty(self, *args): def add_empty(self, *args):
''' '''
Add an empty book item to the library. This does not import any formats Add an empty book item to the library. This does not import any formats

View File

@ -175,6 +175,12 @@ class AddEmptyBookDialog(QDialog):
return self.title_edit.text().strip() return self.title_edit.text().strip()
class AddFromArchive(QDialog):
def __init__(self, parent=None):
QDialog.__init__(self, parent)
if __name__ == '__main__': if __name__ == '__main__':
from calibre.library import db from calibre.library import db
db = db() db = db()