diff --git a/src/calibre/gui2/actions/add.py b/src/calibre/gui2/actions/add.py index 79a710d8da..28a0c17047 100644 --- a/src/calibre/gui2/actions/add.py +++ b/src/calibre/gui2/actions/add.py @@ -145,6 +145,14 @@ class AddAction(InterfaceAction): if books: self._add_formats(books, ids) + def _add_extra_files(self, book_ids, paths): + rmap = {'data/' + os.path.basename(x): x for x in paths} + db = self.gui.current_db.new_api + for book_id in book_ids: + db.add_extra_files(book_id, rmap) + self.gui.library_view.model().refresh_ids(book_ids, + current_row=self.gui.library_view.currentIndex().row()) + def add_extra_files(self): ids = self._check_add_formats_ok() if not ids: @@ -152,12 +160,7 @@ class AddAction(InterfaceAction): books = choose_files_and_remember_all_files(self.gui, 'add extra data files dialog dir', _('Select extra data files'), filters=get_filters()) if books: - rmap = {'data/' + os.path.basename(x): x for x in books} - db = self.gui.current_db.new_api - for book_id in ids: - db.add_extra_files(book_id, rmap) - self.gui.library_view.model().refresh_ids(ids, - current_row=self.gui.library_view.currentIndex().row()) + self._add_extra_files(ids, books) def _add_formats(self, paths, ids): if len(ids) > 1 and not question_dialog( @@ -507,16 +510,24 @@ class AddAction(InterfaceAction): accept = True if accept and event is not None: event.accept() - add_as_book = False + add_as_book = add_as_data_files = False if do_confirm and formats: - ok, add_as_book = confirm( + ok, add_as = confirm( _('You have dropped some files onto the book %s. This will' ' add or replace the files for this book. Do you want to proceed?') % db.title(cid, index_is_id=True), 'confirm_drop_on_book', parent=self.gui, - extra_button=ngettext('Add as new book', 'Add as new books', len(formats))) - if ok and add_as_book: - add_as_book = [path for ext, path in formats] - if not ok or add_as_book: + extra_button=_('Add as...'), extra_button_choices={ + 'book': ngettext('Add as new book', 'Add as new books', len(formats)), + 'data_files': ngettext('Add as data file', 'Add as data files', len(formats)), + }) + if ok: + if add_as == 'book': + add_as_book = [path for ext, path in formats] + formats = [] + elif add_as == 'data_files': + add_as_data_files = [path for ext, path in formats] + formats = [] + else: formats = [] for ext, path in formats: db.add_format_with_hooks(cid, ext, path, index_is_id=True) @@ -526,6 +537,8 @@ class AddAction(InterfaceAction): self.gui.refresh_cover_browser() if add_as_book: self.files_dropped(add_as_book) + if add_as_data_files: + self._add_extra_files({cid}, add_as_data_files) def __add_filesystem_book(self, paths, allow_device=True): if isinstance(paths, string_or_bytes): diff --git a/src/calibre/gui2/dialogs/confirm_delete.py b/src/calibre/gui2/dialogs/confirm_delete.py index d87fc7eb1a..ff99773429 100644 --- a/src/calibre/gui2/dialogs/confirm_delete.py +++ b/src/calibre/gui2/dialogs/confirm_delete.py @@ -5,7 +5,7 @@ __license__ = 'GPL v3' __copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net' __docformat__ = 'restructuredtext en' -from qt.core import QCheckBox, QDialog, QDialogButtonBox, QHBoxLayout, QIcon, QLabel, Qt, QVBoxLayout +from qt.core import QCheckBox, QDialog, QDialogButtonBox, QHBoxLayout, QIcon, QLabel, QMenu, Qt, QVBoxLayout from calibre import confirm_config_name from calibre.gui2 import dynamic @@ -14,8 +14,11 @@ from calibre.gui2.dialogs.message_box import Icon class Dialog(QDialog): - def __init__(self, msg, name, parent, config_set=dynamic, icon='dialog_warning.png', - title=None, confirm_msg=None, show_cancel_button=True, extra_button=None): + def __init__( + self, msg, name, parent, config_set=dynamic, icon='dialog_warning.png', + title=None, confirm_msg=None, show_cancel_button=True, extra_button=None, + extra_button_choices=None + ): QDialog.__init__(self, parent) self.setWindowTitle(title or _("Are you sure?")) self.setWindowIcon(QIcon.ic(icon)) @@ -50,9 +53,18 @@ class Dialog(QDialog): bb.setFocus(Qt.FocusReason.OtherFocusReason) bb.accepted.connect(self.accept), bb.rejected.connect(self.reject) self.extra_button_clicked = False + self.extra_button_choice = None if extra_button: b = bb.addButton(extra_button, QDialogButtonBox.ButtonRole.AcceptRole) - b.clicked.connect(self.on_extra_button_click) + if extra_button_choices: + m = QMenu() + b.setMenu(m) + for acname, text in extra_button_choices.items(): + ac = m.addAction(text) + ac.setObjectName(acname) + ac.triggered.connect(self.on_extra_choice_click) + else: + b.clicked.connect(self.on_extra_button_click) l.addWidget(bb) self.name = name @@ -64,20 +76,32 @@ class Dialog(QDialog): def on_extra_button_click(self): self.extra_button_clicked = True + def on_extra_choice_click(self): + ac = self.sender() + self.extra_button_choice = ac.objectName() + self.accept() + def toggle(self, *args): self.config_set[confirm_config_name(self.name)] = self.again.isChecked() -def confirm(msg, name, parent=None, pixmap='dialog_warning.png', title=None, - show_cancel_button=True, confirm_msg=None, config_set=None, extra_button=None): +def confirm( + msg, name, parent=None, pixmap='dialog_warning.png', title=None, + show_cancel_button=True, confirm_msg=None, config_set=None, extra_button=None, extra_button_choices=None +): config_set = config_set or dynamic if not config_set.get(confirm_config_name(name), True): if extra_button: + if extra_button_choices: + return True, None return True, False return True d = Dialog(msg, name, parent, config_set=config_set, icon=pixmap, extra_button=extra_button, - title=title, confirm_msg=confirm_msg, show_cancel_button=show_cancel_button) + title=title, confirm_msg=confirm_msg, show_cancel_button=show_cancel_button, extra_button_choices=extra_button_choices) ret = d.exec() == QDialog.DialogCode.Accepted if extra_button: - ret = ret, d.extra_button_clicked + if extra_button_choices: + ret = ret, d.extra_button_choice + else: + ret = ret, d.extra_button_clicked return ret