From 3e8adced66879945c314af87c09037c7024b6d92 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 6 Feb 2020 20:19:02 +0530 Subject: [PATCH] Clean up the Add books menu --- manual/gui.rst | 4 +- src/calibre/gui2/actions/add.py | 62 ++++++++++++++-------- src/calibre/gui2/dialogs/add_empty_book.py | 6 +++ 3 files changed, 46 insertions(+), 26 deletions(-) diff --git a/manual/gui.rst b/manual/gui.rst index 1882d4db3d..5aee7dc4d0 100644 --- a/manual/gui.rst +++ b/manual/gui.rst @@ -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 ` 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 ` 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). - - 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. + 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 ` 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). 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. diff --git a/src/calibre/gui2/actions/add.py b/src/calibre/gui2/actions/add.py index 444e654ba9..29d938ffb0 100644 --- a/src/calibre/gui2/actions/add.py +++ b/src/calibre/gui2/actions/add.py @@ -58,21 +58,8 @@ class AddAction(InterfaceAction): self._add_filesystem_book = self.Dispatcher(self.__add_filesystem_book) self.add_menu = self.qaction.menu() ma = partial(self.create_menu_action, self.add_menu) - ma('recursive-single', _('Add books from directories, including ' - 'sub-directories (One book per directory, assumes every e-book ' - '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)) + ma('recursive-add', _('Add from directories and sub-directories')).triggered.connect(self.add_recursive_question) + ma('archive-add-book', _('Add multiple books from archive (ZIP/RAR)')).triggered.connect(self.add_from_archive) self.add_menu.addSeparator() ma('add-empty', _('Add empty book (Book entry with no formats)'), shortcut='Shift+Ctrl+E').triggered.connect(self.add_empty) @@ -82,16 +69,11 @@ class AddAction(InterfaceAction): 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')) - from calibre.ebooks.oeb.polish.create import valid_empty_formats - 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())) + ma('add-empty-format-to-books', _( + 'Add an empty file to selected book records')).triggered.connect(self.add_empty_format_choose) self.add_menu.addSeparator() ma('add-config', _('Control the adding of books'), triggered=self.add_config) - self.qaction.triggered.connect(self.add_books) def location_selected(self, loc): @@ -197,7 +179,7 @@ class AddAction(InterfaceAction): if current_idx.isValid(): 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: return view = self.gui.library_view @@ -215,7 +197,27 @@ class AddAction(InterfaceAction): ' empty file to all %d books? If the format' ' already exists for a book, it will be replaced.')%len(ids)): 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 if len(ids) == 1: formats = db.formats(ids[0], index_is_id=True) @@ -252,6 +254,15 @@ class AddAction(InterfaceAction): if paths: 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): root = choose_dir(self.gui, 'recursive book import root dir dialog', _('Select root folder')) @@ -282,6 +293,11 @@ class AddAction(InterfaceAction): ''' 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): ''' Add an empty book item to the library. This does not import any formats diff --git a/src/calibre/gui2/dialogs/add_empty_book.py b/src/calibre/gui2/dialogs/add_empty_book.py index f7a212b7e2..a58746d571 100644 --- a/src/calibre/gui2/dialogs/add_empty_book.py +++ b/src/calibre/gui2/dialogs/add_empty_book.py @@ -175,6 +175,12 @@ class AddEmptyBookDialog(QDialog): return self.title_edit.text().strip() +class AddFromArchive(QDialog): + + def __init__(self, parent=None): + QDialog.__init__(self, parent) + + if __name__ == '__main__': from calibre.library import db db = db()