def __exit__(self, *args): remove_dir(self._tdir) for x in self.delete_on_exit: try: os.remove(x) except: pass
def _start_splitmerge(self,book_list, tdir=None, db=None): # logger.debug(book_list) em = self.get_epubmerge_plugin() es = self.get_epubsplit_plugin() good_list = [ b for b in book_list if b['good'] ] tmp = PersistentTemporaryFile(prefix='merge-', suffix='.epub', dir=tdir) if len(good_list) == 1: deftitle = "New "+good_list[0]['title'] defauthors = good_list[0]['authors'] else: deftitle = "New Chapters Anthology" defauthors = ["Various Authors"] mi = MetaInformation(deftitle,defauthors) tagslists = [ x['tags'] for x in good_list ] mi.tags = [item for sublist in tagslists for item in sublist] mi.comments = "<p>New Chapters from:</p>" mi.comments += '<br/>'.join( [ "%s by %s"%(x['title'],", ".join(x['authors'])) for x in good_list ] ) em.do_merge(tmp, [b['splittmp'] for b in good_list], authoropts=mi.authors, titleopt=mi.title, descopt=mi.comments, tags=mi.tags, keepmetadatafiles=False, ) book_id = db.create_book_entry(mi, add_duplicates=True) db.add_format_with_hooks(book_id, 'EPUB', tmp, index_is_id=True) self.gui.library_view.model().books_added(1) self.gui.library_view.model().refresh_ids([book_id]) # self.gui.iactions['Edit Metadata'].edit_metadata(False) self.gui.tags_view.recount() ## run word counts cp_plugin = self.gui.iactions['Count Pages'] cp_plugin.count_statistics([book_id],['WordCount']) ## run auto convert self.gui.iactions['Convert Books'].auto_convert_auto_add([book_id]) ## add to FFF update lists self.gui.library_view.select_rows([book_id]) fff_plugin = self.gui.iactions['FanFicFare'] fff_plugin.update_lists() remove_dir(tdir)
def merge_done(self,job): db=self.gui.current_db logger.info("merge_done(%s,%s)"%(job.failed,job.args)) args = job.args[2][0] if job.failed: # self.gui.job_exception(job, dialog_title=_('EpubMerge Failed')) if question_dialog(self.gui, _('Remove Failed Anthology Book?'),''' <h3>%s</h3> <p>%s</p> <p><b>%s</b></p> <p>%s</p> <p>%s</p>'''%( _("Remove Failed Anthology Book?"), _("EpubMerge failed, no new EPUB was created; see the background job details for any error messages."), _("Do you want to delete the empty book EpubMerge created?"), _("Click '<b>Yes</b>' to remove empty book from Libary,"), _("Click '<b>No</b>' to leave it in Library.")), show_copy_button=False): self.gui.iactions['Remove Books'].do_library_delete([args['book_id']]) return outputepubfn = args['outputepubfn'] book_id = args['book_id'] book_count = args['book_count'] logger.debug("6:%s"%(time.time()-self.t)) logger.debug(_("Merge finished, output in:\n%s")%outputepubfn) self.t = time.time() db.add_format_with_hooks(book_id, 'EPUB', outputepubfn, index_is_id=True) logger.debug("7:%s"%(time.time()-self.t)) self.t = time.time() # clean up temp files. remove_dir(args['tdir']) self.gui.status_bar.show_message(_('Finished merging %s EPUBs.')%book_count, 3000) self.gui.library_view.model().refresh_ids([book_id]) self.gui.tags_view.recount() current = self.gui.library_view.currentIndex() self.gui.library_view.model().current_changed(current, self.previous) #self.gui.iactions['View'].view_book(False) if self.gui.cover_flow: self.gui.cover_flow.dataChanged() confirm('\n'+_('''EpubMerge has finished. The new EPUB has been added to the book previously created.'''), 'epubmerge_finished_again', self.gui, title=_("EpubMerge"), show_cancel_button=False)
def _queue_job(self, tdir, books_to_scan, statistics_cols_map, pages_algorithm, use_goodreads): if not books_to_scan: if tdir: # All failed so cleanup our temp directory remove_dir(tdir) return func = 'arbitrary_n' cpus = self.gui.job_manager.server.pool_size args = ['calibre_plugins.count_pages.jobs', 'do_count_statistics', (books_to_scan, pages_algorithm, use_goodreads, self.nltk_pickle, cpus)] desc = 'Count Page/Word Statistics' job = self.gui.job_manager.run_job( self.Dispatcher(self._get_statistics_completed), func, args=args, description=desc) job.tdir = tdir job.statistics_cols_map = statistics_cols_map job.use_goodreads = use_goodreads self.gui.status_bar.show_message('Counting statistics in %d books'%len(books_to_scan))
def _get_statistics_completed(self, job): if job.tdir: remove_dir(job.tdir) if job.failed: return self.gui.job_exception(job, dialog_title='Failed to count statistics') self.gui.status_bar.show_message('Counting statistics completed', 3000) book_statistics_map = job.result if len(book_statistics_map) == 0: # Must have been some sort of error in processing this book msg = 'Failed to generate any statistics. <b>View Log</b> for details' p = ErrorNotification(job.details, 'Count log', 'Count Pages failed', msg, show_copy_button=False, parent=self.gui) p.show() else: payload = (job.statistics_cols_map, book_statistics_map) all_ids = set(book_statistics_map.keys()) msg = '<p>Count Pages plugin found <b>%d statistics(s)</b>. ' % len(all_ids) + \ 'Proceed with updating columns in your library?' self.gui.proceed_question(self._update_database_columns, payload, job.details, 'Count log', 'Count complete', msg, show_copy_button=False)
def launchObok(self): ''' Main processing/distribution method ''' self.count = 0 self.books_to_add = [] self.formats_to_add = [] self.add_books_cancelled = False self.decryption_errors = [] self.userkeys = [] self.duplicate_book_list = [] self.no_home_for_book = [] self.ids_of_new_books = [] self.successful_format_adds =[] self.add_formats_cancelled = False self.tdir = PersistentTemporaryDirectory('_obok', prefix='') self.db = self.gui.current_db.new_api self.current_idx = self.gui.library_view.currentIndex() print ('Running {}'.format(PLUGIN_NAME + ' v' + PLUGIN_VERSION)) # # search for connected device in case serials are saved tmpserials = cfg['kobo_serials'] device_path = None try: device = self.parent().device_manager.connected_device if (device): device_path = device._main_prefix debug_print("get_device_settings - device_path=", device_path) else: debug_print("didn't find device") except: debug_print("Exception getting device path. Probably not an E-Ink Kobo device") # Get the Kobo Library object (obok v3.01) self.library = KoboLibrary(tmpserials, device_path, cfg['kobo_directory']) debug_print ("got kobodir %s" % self.library.kobodir) if (self.library.kobodir == ''): # linux and no device connected, but could be extended # to the case where on Windows/Mac the prog is not installed msg = _('<p>Could not find Kobo Library\n<p>Windows/Mac: do you have Kobo Desktop installed?\n<p>Windows/Mac/Linux: In case you have an Kobo eInk device, connect the device.') showErrorDlg(msg, None) return # Get a list of Kobo titles books = self.build_book_list() if len(books) < 1: msg = _('<p>No books found in Kobo Library\nAre you sure it\'s installed\configured\synchronized?') showErrorDlg(msg, None) return # Check to see if a key can be retrieved using the legacy obok method. legacy_key = legacy_obok().get_legacy_cookie_id if legacy_key is not None: print (_('Legacy key found: '), legacy_key.encode('hex_codec')) self.userkeys.append(legacy_key) # Add userkeys found through the normal obok method to the list to try. try: candidate_keys = self.library.userkeys except: print (_('Trouble retrieving keys with newer obok method.')) traceback.print_exc() else: if len(candidate_keys): self.userkeys.extend(candidate_keys) print (_('Found {0} possible keys to try.').format(len(self.userkeys))) if not len(self.userkeys): msg = _('<p>No userkeys found to decrypt books with. No point in proceeding.') showErrorDlg(msg, None) return # Launch the Dialog so the user can select titles. dlg = SelectionDialog(self.gui, self, books) if dlg.exec_(): books_to_import = dlg.getBooks() self.count = len(books_to_import) debug_print("InterfacePluginAction::launchObok - number of books to decrypt: %d" % self.count) # Feed the titles, the callback function (self.get_decrypted_kobo_books) # and the Kobo library object to the ProgressDialog dispatcher. d = DecryptAddProgressDialog(self.gui, books_to_import, self.get_decrypted_kobo_books, self.library, 'kobo', status_msg_type='Kobo books', action_type=('Decrypting', 'Decryption')) # Canceled the decryption process; clean up and exit. if d.wasCanceled(): print (_('{} - Decryption canceled by user.').format(PLUGIN_NAME + ' v' + PLUGIN_VERSION)) self.library.close() remove_dir(self.tdir) return else: # Canceled the selection process; clean up and exit. self.library.close() remove_dir(self.tdir) return # Close Kobo Library object self.library.close() # If we have decrypted books to work with, feed the list of decrypted books details # and the callback function (self.add_new_books) to the ProgressDialog dispatcher. if len(self.books_to_add): d = DecryptAddProgressDialog(self.gui, self.books_to_add, self.add_new_books, self.db, 'calibre', status_msg_type='new calibre books', action_type=('Adding','Addition')) # Canceled the "add new books to calibre" process; # show the results of what got added before cancellation. if d.wasCanceled(): print (_('{} - "Add books" canceled by user.').format(PLUGIN_NAME + ' v' + PLUGIN_VERSION)) self.add_books_cancelled = True print (_('{} - wrapping up results.').format(PLUGIN_NAME + ' v' + PLUGIN_VERSION)) self.wrap_up_results() remove_dir(self.tdir) return # If books couldn't be added because of duplicate entries in calibre, ask # if we should try to add the decrypted epubs to existing calibre library entries. if len(self.duplicate_book_list): if cfg['finding_homes_for_formats'] == 'Always': self.process_epub_formats() elif cfg['finding_homes_for_formats'] == 'Never': self.no_home_for_book.extend([entry[0] for entry in self.duplicate_book_list]) else: if self.ask_about_inserting_epubs(): # Find homes for the epub decrypted formats in existing calibre library entries. self.process_epub_formats() else: print (_('{} - User opted not to try to insert EPUB formats').format(PLUGIN_NAME + ' v' + PLUGIN_VERSION)) self.no_home_for_book.extend([entry[0] for entry in self.duplicate_book_list]) print (_('{} - wrapping up results.').format(PLUGIN_NAME + ' v' + PLUGIN_VERSION)) self.wrap_up_results() remove_dir(self.tdir) return
def unmerge(self): db = self.gui.current_db applyall = False state = 'add' for book_id in self.gui.library_view.get_selected_ids(): unmerge_mi = db.get_metadata(book_id, index_is_id=True) # if len(self.gui.library_view.get_selected_ids()) != 1: # d = error_dialog(self.gui, # _('Select One Book'), # _('Please select exactly one book to UnMerge.'), # show_copy_button=False) # d.exec_() # else: # book_id=[0] if db.has_format(book_id, 'EPUB', index_is_id=True): epub = StringIO(db.format(book_id, 'EPUB', index_is_id=True)) else: d = error_dialog( self.gui, _('Cannot UnMerge Non-Epubs'), unmerge_mi.title + '<br>' + _('To UnMerge the source must be Epub(s) created by EpubMerge with Keep UnMerge Metadata enabled.' ), show_copy_button=False) d.exec_() continue tdir = PersistentTemporaryDirectory(prefix='epubmerge_') logger.debug("tdir:%s" % tdir) outfilenames = self.do_unmerge(epub, tdir) if not outfilenames: d = error_dialog( self.gui, _('No UnMerge data found'), unmerge_mi.title + '<br>' + _('To UnMerge the source must be Epub(s) created by EpubMerge with Keep UnMerge Metadata enabled.' ), show_copy_button=False) d.exec_() remove_dir(tdir) continue #db.import_book_directory_multiple(tdir) XXX #self.gui.library_view.model().books_added(len(outfilenames)) added_list = [] updated_list = [] for formats in db.find_books_in_directory(tdir, False): #logger.debug("formats:%s"%formats) mi = metadata_from_formats(formats) #logger.debug("mi:%s"%mi) identicalbooks = db.find_identical_books(mi) if identicalbooks: if len(identicalbooks) == 1: text = unmerge_mi.title + '<br>' + _( "You already have a book <i>%s</i> by <i>%s</i>. You may Add a new book of the same title, Overwrite the Epub in the existing book, or Discard this Epub." ) % (mi.title, ", ".join(mi.authors)) over = True else: text = unmerge_mi.title + '<br>' + _( "You already have more than one book <i>%s</i> by <i>%s</i>. You may Add a new book of the same title, or Discard this Epub." ) % (mi.title, ", ".join(mi.authors)) over = False #logger.debug("applyall:%s over:%s state:%s"%(applyall,over, state)) if applyall and (over or state in ('add', 'discard')): # use previous state. pass else: d = AddOverDiscardDialog(self.gui, self.qaction.icon(), text, over=over) d.exec_() state = d.state applyall = d.get_applyall() if state == 'add' or len(identicalbooks) == 0: book_id = db.create_book_entry(mi, add_duplicates=True) added_list.append(book_id) elif state == 'discard': continue elif state == 'over': book_id = identicalbooks.pop() db.add_format_with_hooks(book_id, 'EPUB', formats[0], index_is_id=True) updated_list.append(book_id) if len(added_list): self.gui.library_view.model().books_added(len(added_list)) if len(updated_list): self.gui.library_view.model().refresh_ids(updated_list) remove_dir(tdir)
def launchObok(self): ''' Main processing/distribution method ''' self.count = 0 self.books_to_add = [] self.formats_to_add = [] self.add_books_cancelled = False self.decryption_errors = [] self.userkeys = [] self.duplicate_book_list = [] self.no_home_for_book = [] self.ids_of_new_books = [] self.successful_format_adds =[] self.add_formats_cancelled = False self.tdir = PersistentTemporaryDirectory('_obok', prefix='') self.db = self.gui.current_db.new_api self.current_idx = self.gui.library_view.currentIndex() print ('Running {}'.format(PLUGIN_NAME + ' v' + PLUGIN_VERSION)) # # search for connected device in case serials are saved tmpserials = cfg['kobo_serials'] device = self.parent().device_manager.connected_device device_path = None if (device): device_path = device._main_prefix debug_print("get_device_settings - device_path=", device_path) # get serial from device_path/.adobe-digital-editions/device.xml if can_parse_xml: devicexml = os.path.join(device_path, '.adobe-digital-editions', 'device.xml') debug_print("trying to load %s" % devicexml) if (os.path.exists(devicexml)): debug_print("trying to parse %s" % devicexml) xmltree = ET.parse(devicexml) for node in xmltree.iter(): if "deviceSerial" in node.tag: serial = node.text debug_print ("found serial %s" % serial) tmpserials.append(serial) break else: debug_print("didn't find device") # Get the Kobo Library object (obok v3.01) self.library = KoboLibrary(tmpserials, device_path) debug_print ("got kobodir %s" % self.library.kobodir) if (self.library.kobodir == ''): # linux and no device connected, but could be extended # to the case where on Windows/Mac the prog is not installed msg = _('<p>Could not find Kobo Library\n<p>Windows/Mac: do you have Kobo Desktop installed?\n<p>Windows/Mac/Linux: In case you have an Kobo eInk device, connect the device.') showErrorDlg(msg, None) return # Get a list of Kobo titles books = self.build_book_list() if len(books) < 1: msg = _('<p>No books found in Kobo Library\nAre you sure it\'s installed\configured\synchronized?') showErrorDlg(msg, None) return # Check to see if a key can be retrieved using the legacy obok method. legacy_key = legacy_obok().get_legacy_cookie_id if legacy_key is not None: print (_('Legacy key found: '), legacy_key.encode('hex_codec')) self.userkeys.append(legacy_key) # Add userkeys found through the normal obok method to the list to try. try: candidate_keys = self.library.userkeys except: print (_('Trouble retrieving keys with newer obok method.')) traceback.print_exc() else: if len(candidate_keys): self.userkeys.extend(candidate_keys) print (_('Found {0} possible keys to try.').format(len(self.userkeys))) if not len(self.userkeys): msg = _('<p>No userkeys found to decrypt books with. No point in proceeding.') showErrorDlg(msg, None) return # Launch the Dialog so the user can select titles. dlg = SelectionDialog(self.gui, self, books) if dlg.exec_(): books_to_import = dlg.getBooks() self.count = len(books_to_import) debug_print("InterfacePluginAction::launchObok - number of books to decrypt: %d" % self.count) # Feed the titles, the callback function (self.get_decrypted_kobo_books) # and the Kobo library object to the ProgressDialog dispatcher. d = DecryptAddProgressDialog(self.gui, books_to_import, self.get_decrypted_kobo_books, self.library, 'kobo', status_msg_type='Kobo books', action_type=('Decrypting', 'Decryption')) # Canceled the decryption process; clean up and exit. if d.wasCanceled(): print (_('{} - Decryption canceled by user.').format(PLUGIN_NAME + ' v' + PLUGIN_VERSION)) self.library.close() remove_dir(self.tdir) return else: # Canceled the selection process; clean up and exit. self.library.close() remove_dir(self.tdir) return # Close Kobo Library object self.library.close() # If we have decrypted books to work with, feed the list of decrypted books details # and the callback function (self.add_new_books) to the ProgressDialog dispatcher. if len(self.books_to_add): d = DecryptAddProgressDialog(self.gui, self.books_to_add, self.add_new_books, self.db, 'calibre', status_msg_type='new calibre books', action_type=('Adding','Addition')) # Canceled the "add new books to calibre" process; # show the results of what got added before cancellation. if d.wasCanceled(): print (_('{} - "Add books" canceled by user.').format(PLUGIN_NAME + ' v' + PLUGIN_VERSION)) self.add_books_cancelled = True print (_('{} - wrapping up results.').format(PLUGIN_NAME + ' v' + PLUGIN_VERSION)) self.wrap_up_results() remove_dir(self.tdir) return # If books couldn't be added because of duplicate entries in calibre, ask # if we should try to add the decrypted epubs to existing calibre library entries. if len(self.duplicate_book_list): if cfg['finding_homes_for_formats'] == 'Always': self.process_epub_formats() elif cfg['finding_homes_for_formats'] == 'Never': self.no_home_for_book.extend([entry[0] for entry in self.duplicate_book_list]) else: if self.ask_about_inserting_epubs(): # Find homes for the epub decrypted formats in existing calibre library entries. self.process_epub_formats() else: print (_('{} - User opted not to try to insert EPUB formats').format(PLUGIN_NAME + ' v' + PLUGIN_VERSION)) self.no_home_for_book.extend([entry[0] for entry in self.duplicate_book_list]) print (_('{} - wrapping up results.').format(PLUGIN_NAME + ' v' + PLUGIN_VERSION)) self.wrap_up_results() remove_dir(self.tdir) return
def launchObok(self): ''' Main processing/distribution method ''' self.count = 0 self.books_to_add = [] self.formats_to_add = [] self.add_books_cancelled = False self.decryption_errors = [] self.userkeys = [] self.duplicate_book_list = [] self.no_home_for_book = [] self.ids_of_new_books = [] self.successful_format_adds =[] self.add_formats_cancelled = False self.tdir = PersistentTemporaryDirectory('_obok', prefix='') self.db = self.gui.current_db.new_api self.current_idx = self.gui.library_view.currentIndex() print ('Running {}'.format(PLUGIN_NAME + ' v' + PLUGIN_VERSION)) # Get the Kobo Library object (obok v3.01) self.library = KoboLibrary() # Get a list of Kobo titles books = self.build_book_list() if len(books) < 1: msg = _('<p>No books found in Kobo Library\nAre you sure it\'s installed\configured\synchronized?') showErrorDlg(msg, None) return # Check to see if a key can be retrieved using the legacy obok method. legacy_key = legacy_obok().get_legacy_cookie_id if legacy_key is not None: print (_('Legacy key found: '), legacy_key.encode('hex_codec')) self.userkeys.append(legacy_key) # Add userkeys found through the normal obok method to the list to try. try: candidate_keys = self.library.userkeys except: print (_('Trouble retrieving keys with newer obok method.')) traceback.print_exc() else: if len(candidate_keys): self.userkeys.extend(candidate_keys) print (_('Found {0} possible keys to try.').format(len(self.userkeys))) if not len(self.userkeys): msg = _('<p>No userkeys found to decrypt books with. No point in proceeding.') showErrorDlg(msg, None) return # Launch the Dialog so the user can select titles. dlg = SelectionDialog(self.gui, self, books) if dlg.exec_(): books_to_import = dlg.getBooks() self.count = len(books_to_import) debug_print("InterfacePluginAction::launchObok - number of books to decrypt: %d" % self.count) # Feed the titles, the callback function (self.get_decrypted_kobo_books) # and the Kobo library object to the ProgressDialog dispatcher. d = DecryptAddProgressDialog(self.gui, books_to_import, self.get_decrypted_kobo_books, self.library, 'kobo', status_msg_type='Kobo books', action_type=('Decrypting', 'Decryption')) # Canceled the decryption process; clean up and exit. if d.wasCanceled(): print (_('{} - Decryption canceled by user.').format(PLUGIN_NAME + ' v' + PLUGIN_VERSION)) self.library.close() remove_dir(self.tdir) return else: # Canceled the selection process; clean up and exit. self.library.close() remove_dir(self.tdir) return # Close Kobo Library object self.library.close() # If we have decrypted books to work with, feed the list of decrypted books details # and the callback function (self.add_new_books) to the ProgressDialog dispatcher. if len(self.books_to_add): d = DecryptAddProgressDialog(self.gui, self.books_to_add, self.add_new_books, self.db, 'calibre', status_msg_type='new calibre books', action_type=('Adding','Addition')) # Canceled the "add new books to calibre" process; # show the results of what got added before cancellation. if d.wasCanceled(): print (_('{} - "Add books" canceled by user.').format(PLUGIN_NAME + ' v' + PLUGIN_VERSION)) self.add_books_cancelled = True print (_('{} - wrapping up results.').format(PLUGIN_NAME + ' v' + PLUGIN_VERSION)) self.wrap_up_results() remove_dir(self.tdir) return # If books couldn't be added because of duplicate entries in calibre, ask # if we should try to add the decrypted epubs to existing calibre library entries. if len(self.duplicate_book_list): if cfg['finding_homes_for_formats'] == 'Always': self.process_epub_formats() elif cfg['finding_homes_for_formats'] == 'Never': self.no_home_for_book.extend([entry[0] for entry in self.duplicate_book_list]) else: if self.ask_about_inserting_epubs(): # Find homes for the epub decrypted formats in existing calibre library entries. self.process_epub_formats() else: print (_('{} - User opted not to try to insert EPUB formats').format(PLUGIN_NAME + ' v' + PLUGIN_VERSION)) self.no_home_for_book.extend([entry[0] for entry in self.duplicate_book_list]) print (_('{} - wrapping up results.').format(PLUGIN_NAME + ' v' + PLUGIN_VERSION)) self.wrap_up_results() remove_dir(self.tdir) return
def clean_tdirs_in(b): # Remove any stale tdirs left by previous program crashes for q in tdirs_in(b): if not is_tdir_locked(q): remove_dir(q)
def remove_tdir(path, lock_file): lock_file.close() remove_dir(path)
def unmerge(self): if len(self.gui.library_view.get_selected_ids()) != 1: d = error_dialog(self.gui, _('Select One Book'), _('Please select exactly one book to UnMerge.'), show_copy_button=False) d.exec_() else: db=self.gui.current_db book_id=self.gui.library_view.get_selected_ids()[0] if db.has_format(book_id,'EPUB',index_is_id=True): epub = StringIO(db.format(book_id,'EPUB',index_is_id=True)) else: d = error_dialog(self.gui, _('Cannot UnMerge Non-Epubs'), _('To UnMerge the source must be Epub(s) created by EpubMerge with Keep UnMerge Metadata enabled.'), show_copy_button=False) d.exec_() remove_dir(tdir) return tdir = PersistentTemporaryDirectory(prefix='epubmerge_') print("tdir:%s"%tdir) outfilenames = self.do_unmerge(epub,tdir) if not outfilenames: d = error_dialog(self.gui, _('No UnMerge data found'), _('To UnMerge the source must be Epub(s) created by EpubMerge with Keep UnMerge Metadata enabled.'), show_copy_button=False) d.exec_() return #db.import_book_directory_multiple(tdir) XXX #self.gui.library_view.model().books_added(len(outfilenames)) added_list=[] updated_list=[] for formats in db.find_books_in_directory(tdir, False): #print("formats:%s"%formats) mi = metadata_from_formats(formats) #print("mi:%s"%mi) state = 'add' identicalbooks = db.find_identical_books(mi) if identicalbooks: if len(identicalbooks) == 1: text = _("You already have a book <i>%s</i> by <i>%s</i>. You may Add a new book of the same title, Overwrite the Epub in the existing book, or Discard this Epub.")%(mi.title,", ".join(mi.authors)) over=True else: text = _("You already have more than one book <i>%s</i> by <i>%s</i>. You may Add a new book of the same title, or Discard this Epub.")%(mi.title,", ".join(mi.authors)) over=False d = AddOverDiscardDialog(self.gui,self.qaction.icon(),text,over=over) d.exec_() state=d.state if not state or state == 'discard': continue elif state == 'add': book_id = db.create_book_entry(mi, add_duplicates=True) added_list.append(book_id) else: book_id = identicalbooks.pop() db.add_format_with_hooks(book_id, 'EPUB', formats[0], index_is_id=True) updated_list.append(book_id) if len(added_list): self.gui.library_view.model().books_added(len(added_list)) if len(updated_list): self.gui.library_view.model().refresh_ids(updated_list) remove_dir(tdir)