From 7b498bf908ec48c33bdb0e2990c65e63dfb7ae72 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 25 Jun 2008 19:38:57 -0700 Subject: [PATCH] Add action to save only specified format when saving to disk --- src/calibre/ebooks/__init__.py | 4 +- src/calibre/ebooks/mobi/reader.py | 2 +- src/calibre/gui2/dialogs/config.py | 14 +- src/calibre/gui2/dialogs/config.ui | 223 ++++++++++++++--------------- src/calibre/gui2/library.py | 8 +- src/calibre/gui2/main.py | 18 ++- src/calibre/library/database.py | 19 +++ 7 files changed, 161 insertions(+), 127 deletions(-) diff --git a/src/calibre/ebooks/__init__.py b/src/calibre/ebooks/__init__.py index 61153bdc8d..dd7e8fc96a 100644 --- a/src/calibre/ebooks/__init__.py +++ b/src/calibre/ebooks/__init__.py @@ -15,6 +15,6 @@ class ConversionError(Exception): class UnknownFormatError(Exception): pass -BOOK_EXTENSIONS = ['lrf', 'lrx', 'rar', 'zip', 'rtf', 'lit', 'txt', 'htm', 'xhtm', +BOOK_EXTENSIONS = ['lrf', 'rar', 'zip', 'rtf', 'lit', 'txt', 'htm', 'xhtm', 'html', 'xhtml', 'epub', 'pdf', 'prc', 'mobi', 'azw', - 'epub', 'fb2', 'djvu'] + 'epub', 'fb2', 'djvu', 'lrx'] diff --git a/src/calibre/ebooks/mobi/reader.py b/src/calibre/ebooks/mobi/reader.py index 22aa95b1e4..87e312ec23 100644 --- a/src/calibre/ebooks/mobi/reader.py +++ b/src/calibre/ebooks/mobi/reader.py @@ -222,7 +222,7 @@ class MobiReader(object): tocobj = TOC() for a in soup.findAll('a', href=True): try: - text = ''.join(a.findAll(text=True)) + text = ''.join(a.findAll(text=True)).strip() except: text = '' tocobj.add_item(toc.partition('#')[0], a['href'][1:], text) diff --git a/src/calibre/gui2/dialogs/config.py b/src/calibre/gui2/dialogs/config.py index 8c1c7fe23d..0b32ab66cd 100644 --- a/src/calibre/gui2/dialogs/config.py +++ b/src/calibre/gui2/dialogs/config.py @@ -3,12 +3,13 @@ __copyright__ = '2008, Kovid Goyal ' import os from PyQt4.QtGui import QDialog, QMessageBox, QListWidgetItem, QIcon -from PyQt4.QtCore import SIGNAL, QTimer, Qt, QSize +from PyQt4.QtCore import SIGNAL, QTimer, Qt, QSize, QVariant from calibre import islinux, Settings from calibre.gui2.dialogs.config_ui import Ui_Dialog from calibre.gui2 import qstring_to_unicode, choose_dir, error_dialog from calibre.gui2.widgets import FilenamePattern +from calibre.ebooks import BOOK_EXTENSIONS @@ -58,7 +59,12 @@ class ConfigDialog(QDialog, Ui_Dialog): icons = settings.get('toolbar icon size', self.ICON_SIZES[0]) self.toolbar_button_size.setCurrentIndex(0 if icons == self.ICON_SIZES[0] else 1 if icons == self.ICON_SIZES[1] else 2) self.show_toolbar_text.setChecked(settings.get('show text in toolbar', True)) - + + for ext in BOOK_EXTENSIONS: + self.single_format.addItem(ext.upper(), QVariant(ext)) + + single_format = settings.get('save to disk single format', 'lrf') + self.single_format.setCurrentIndex(BOOK_EXTENSIONS.index(single_format)) def compact(self, toggled): d = Vacuum(self, self.db) @@ -89,7 +95,9 @@ class ConfigDialog(QDialog, Ui_Dialog): settings.set('show text in toolbar', bool(self.show_toolbar_text.isChecked())) pattern = self.filename_pattern.commit() settings.set('filename pattern', pattern) - + settings.set('save to disk single format', BOOK_EXTENSIONS[self.single_format.currentIndex()]) + + if not path or not os.path.exists(path) or not os.path.isdir(path): d = error_dialog(self, _('Invalid database location'), _('Invalid database location ')+path+_('
Must be a directory.')) d.exec_() diff --git a/src/calibre/gui2/dialogs/config.ui b/src/calibre/gui2/dialogs/config.ui index f6b3957f34..5d00292794 100644 --- a/src/calibre/gui2/dialogs/config.ui +++ b/src/calibre/gui2/dialogs/config.ui @@ -1,4 +1,5 @@ + Kovid Goyal Dialog @@ -76,18 +77,10 @@ 0 - - - - 0 - 0 - 583 - 625 - - - - - + + + + @@ -99,7 +92,7 @@ - + @@ -121,7 +114,7 @@ - + Use &Roman numerals for series number @@ -131,9 +124,35 @@ - - - + + + + + + Format for &single file save: + + + single_format + + + + + + + + + + &Priority for conversion jobs: + + + priority + + + + + + + Default network &timeout: @@ -143,7 +162,7 @@ - + Set the default timeout for network fetches (i.e. anytime we go out to the internet to get information) @@ -164,31 +183,78 @@ - - - - - - &Priority for conversion jobs: - - - priority - - - - - - - + + + + Toolbar + + + + + + + Large + + + + + Medium + + + + + Small + + + + + + + + &Button size in toolbar + + + toolbar_button_size + + + + + + + Show &text in toolbar buttons + + + true + + + + + - + + + + Select visible &columns in library view + + + + + + QAbstractItemView::NoSelection + + + + + + + Frequently used directories - + - + @@ -203,7 +269,7 @@ - + @@ -278,83 +344,6 @@ - - - - Qt::Vertical - - - - 392 - 16 - - - - - - - - Select visible &columns in library view - - - - - - QAbstractItemView::NoSelection - - - - - - - - - - Toolbar - - - - - - - Large - - - - - Medium - - - - - Small - - - - - - - - &Button size in toolbar - - - toolbar_button_size - - - - - - - Show &text in toolbar buttons - - - true - - - - - - @@ -362,8 +351,8 @@ 0 0 - 583 - 625 + 595 + 638 diff --git a/src/calibre/gui2/library.py b/src/calibre/gui2/library.py index ce9db76eed..d03716b54c 100644 --- a/src/calibre/gui2/library.py +++ b/src/calibre/gui2/library.py @@ -150,9 +150,13 @@ class BooksModel(QAbstractTableModel): ''' Return list indices of all cells in index.row()''' return [ self.index(index.row(), c) for c in range(self.columnCount(None))] - def save_to_disk(self, rows, path, single_dir=False): + def save_to_disk(self, rows, path, single_dir=False, single_format=None): rows = [row.row() for row in rows] - self.db.export_to_dir(path, rows, self.sorted_on[0] == 1, single_dir=single_dir) + if single_format is None: + return self.db.export_to_dir(path, rows, self.sorted_on[0] == 1, single_dir=single_dir) + else: + return self.db.export_single_format_to_dir(path, rows, single_format) + def delete_books(self, indices): ids = [ self.id(i) for i in indices ] diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py index d640a75733..636f0a888f 100644 --- a/src/calibre/gui2/main.py +++ b/src/calibre/gui2/main.py @@ -136,6 +136,7 @@ class Main(MainWindow, Ui_MainWindow): self.save_menu = QMenu() self.save_menu.addAction(_('Save to disk')) self.save_menu.addAction(_('Save to disk in a single directory')) + self.save_menu.addAction(_('Save only %s format to disk')%Settings().get('save to disk single format', 'lrf').upper()) self.view_menu = QMenu() self.view_menu.addAction(_('View')) @@ -144,6 +145,7 @@ class Main(MainWindow, Ui_MainWindow): QObject.connect(self.action_save, SIGNAL("triggered(bool)"), self.save_to_disk) QObject.connect(self.save_menu.actions()[0], SIGNAL("triggered(bool)"), self.save_to_disk) QObject.connect(self.save_menu.actions()[1], SIGNAL("triggered(bool)"), self.save_to_single_dir) + QObject.connect(self.save_menu.actions()[2], SIGNAL("triggered(bool)"), self.save_single_format_to_disk) QObject.connect(self.action_view, SIGNAL("triggered(bool)"), self.view_book) QObject.connect(self.view_menu.actions()[0], SIGNAL("triggered(bool)"), self.view_book) QObject.connect(self.view_menu.actions()[1], SIGNAL("triggered(bool)"), self.view_specific_format) @@ -662,20 +664,32 @@ class Main(MainWindow, Ui_MainWindow): ############################################################################ ############################## Save to disk ################################ + def save_single_format_to_disk(self, checked): + self.save_to_disk(checked, True, Settings().get('save to disk single format', 'lrf')) + def save_to_single_dir(self, checked): self.save_to_disk(checked, True) - def save_to_disk(self, checked, single_dir=False): + def save_to_disk(self, checked, single_dir=False, single_format=None): rows = self.current_view().selectionModel().selectedRows() if not rows or len(rows) == 0: d = error_dialog(self, _('Cannot save to disk'), _('No books selected')) d.exec_() return + dir = choose_dir(self, 'save to disk dialog', ('Choose destination directory')) if not dir: return if self.current_view() == self.library_view: - self.current_view().model().save_to_disk(rows, dir, single_dir=single_dir) + failures = self.current_view().model().save_to_disk(rows, dir, + single_dir=single_dir, single_format=single_format) + if failures and single_format is not None: + msg = _('

Could not save the following books to disk, because the %s format is not available for them:

    ')%single_format.upper() + for f in failures: + msg += '
  • %s
  • '%f[1] + msg += '
' + warning_dialog(self, _('Could not save some ebooks'), msg).exec_() + QDesktopServices.openUrl(QUrl('file:'+dir)) else: paths = self.current_view().model().paths(rows) self.job_manager.run_device_job(self.books_saved, diff --git a/src/calibre/library/database.py b/src/calibre/library/database.py index ceff444186..d80917108e 100644 --- a/src/calibre/library/database.py +++ b/src/calibre/library/database.py @@ -1548,6 +1548,25 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE; if res is not None: duplicates.extend(res) return duplicates + + def export_single_format_to_dir(self, dir, indices, format, index_is_id=False): + if not index_is_id: + indices = map(self.id, indices) + failures = [] + for id in indices: + try: + data = self.format(id, format, index_is_id=True) + except: + failures.append((id, self.title(id, index_is_id=True))) + title = self.title(id, index_is_id=True) + au = self.authors(id, index_is_id=True) + if not au: + au = _('Unknown') + fname = '%s - %s.%s'%(title, au, format.lower()) + fname = sanitize_file_name(fname) + open(os.path.join(dir, fname), 'wb').write(data) + return failures + class SearchToken(object):