Add action to save only specified format when saving to disk

This commit is contained in:
Kovid Goyal 2008-06-25 19:38:57 -07:00
parent 476e9371bb
commit 7b498bf908
7 changed files with 161 additions and 127 deletions

View File

@ -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']

View File

@ -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)

View File

@ -3,12 +3,13 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
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+_('<br>Must be a directory.'))
d.exec_()

View File

@ -1,4 +1,5 @@
<ui version="4.0" >
<author>Kovid Goyal</author>
<class>Dialog</class>
<widget class="QDialog" name="Dialog" >
<property name="geometry" >
@ -76,18 +77,10 @@
<property name="currentIndex" >
<number>0</number>
</property>
<widget class="QWidget" name="page" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>583</width>
<height>625</height>
</rect>
</property>
<layout class="QGridLayout" >
<item row="0" column="0" >
<layout class="QVBoxLayout" >
<widget class="QWidget" name="page_3" >
<layout class="QVBoxLayout" name="verticalLayout" >
<item>
<layout class="QVBoxLayout" name="_2" >
<item>
<widget class="QLabel" name="label" >
<property name="text" >
@ -99,7 +92,7 @@
</widget>
</item>
<item>
<layout class="QHBoxLayout" >
<layout class="QHBoxLayout" name="_3" >
<item>
<widget class="QLineEdit" name="location" />
</item>
@ -121,7 +114,7 @@
</item>
</layout>
</item>
<item row="1" column="0" >
<item>
<widget class="QCheckBox" name="roman_numerals" >
<property name="text" >
<string>Use &amp;Roman numerals for series number</string>
@ -131,9 +124,35 @@
</property>
</widget>
</item>
<item row="2" column="0" >
<layout class="QHBoxLayout" >
<item>
<item>
<layout class="QGridLayout" name="gridLayout_2" >
<item row="0" column="0" >
<widget class="QLabel" name="label_5" >
<property name="text" >
<string>Format for &amp;single file save:</string>
</property>
<property name="buddy" >
<cstring>single_format</cstring>
</property>
</widget>
</item>
<item row="0" column="1" >
<widget class="QComboBox" name="single_format" />
</item>
<item row="1" column="0" >
<widget class="QLabel" name="label_3" >
<property name="text" >
<string>&amp;Priority for conversion jobs:</string>
</property>
<property name="buddy" >
<cstring>priority</cstring>
</property>
</widget>
</item>
<item row="1" column="1" >
<widget class="QComboBox" name="priority" />
</item>
<item row="2" column="0" >
<widget class="QLabel" name="label_2" >
<property name="text" >
<string>Default network &amp;timeout:</string>
@ -143,7 +162,7 @@
</property>
</widget>
</item>
<item>
<item row="2" column="1" >
<widget class="QSpinBox" name="timeout" >
<property name="toolTip" >
<string>Set the default timeout for network fetches (i.e. anytime we go out to the internet to get information)</string>
@ -164,31 +183,78 @@
</item>
</layout>
</item>
<item row="3" column="0" >
<layout class="QHBoxLayout" >
<item>
<widget class="QLabel" name="label_3" >
<property name="text" >
<string>&amp;Priority for conversion jobs:</string>
</property>
<property name="buddy" >
<cstring>priority</cstring>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="priority" />
</item>
</layout>
<item>
<widget class="QGroupBox" name="groupBox_2" >
<property name="title" >
<string>Toolbar</string>
</property>
<layout class="QGridLayout" name="gridLayout" >
<item row="0" column="1" >
<widget class="QComboBox" name="toolbar_button_size" >
<item>
<property name="text" >
<string>Large</string>
</property>
</item>
<item>
<property name="text" >
<string>Medium</string>
</property>
</item>
<item>
<property name="text" >
<string>Small</string>
</property>
</item>
</widget>
</item>
<item row="0" column="0" >
<widget class="QLabel" name="label_4" >
<property name="text" >
<string>&amp;Button size in toolbar</string>
</property>
<property name="buddy" >
<cstring>toolbar_button_size</cstring>
</property>
</widget>
</item>
<item row="1" column="0" >
<widget class="QCheckBox" name="show_toolbar_text" >
<property name="text" >
<string>Show &amp;text in toolbar buttons</string>
</property>
<property name="checked" >
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="6" column="0" >
<item>
<widget class="QGroupBox" name="groupBox" >
<property name="title" >
<string>Select visible &amp;columns in library view</string>
</property>
<layout class="QGridLayout" name="_4" >
<item row="0" column="0" >
<widget class="QListWidget" name="columns" >
<property name="selectionMode" >
<enum>QAbstractItemView::NoSelection</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="dirs_box" >
<property name="title" >
<string>Frequently used directories</string>
</property>
<layout class="QGridLayout" >
<layout class="QGridLayout" name="_5" >
<item row="0" column="0" >
<layout class="QHBoxLayout" >
<layout class="QHBoxLayout" name="_6" >
<item>
<widget class="QListWidget" name="directory_list" >
<property name="alternatingRowColors" >
@ -203,7 +269,7 @@
</widget>
</item>
<item>
<layout class="QVBoxLayout" >
<layout class="QVBoxLayout" name="_7" >
<item>
<spacer>
<property name="orientation" >
@ -278,83 +344,6 @@
</layout>
</widget>
</item>
<item row="7" column="0" >
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0" >
<size>
<width>392</width>
<height>16</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="0" >
<widget class="QGroupBox" name="groupBox" >
<property name="title" >
<string>Select visible &amp;columns in library view</string>
</property>
<layout class="QGridLayout" >
<item row="0" column="0" >
<widget class="QListWidget" name="columns" >
<property name="selectionMode" >
<enum>QAbstractItemView::NoSelection</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="4" column="0" >
<widget class="QGroupBox" name="groupBox_2" >
<property name="title" >
<string>Toolbar</string>
</property>
<layout class="QGridLayout" name="gridLayout" >
<item row="0" column="1" >
<widget class="QComboBox" name="toolbar_button_size" >
<item>
<property name="text" >
<string>Large</string>
</property>
</item>
<item>
<property name="text" >
<string>Medium</string>
</property>
</item>
<item>
<property name="text" >
<string>Small</string>
</property>
</item>
</widget>
</item>
<item row="0" column="0" >
<widget class="QLabel" name="label_4" >
<property name="text" >
<string>&amp;Button size in toolbar</string>
</property>
<property name="buddy" >
<cstring>toolbar_button_size</cstring>
</property>
</widget>
</item>
<item row="1" column="0" >
<widget class="QCheckBox" name="show_toolbar_text" >
<property name="text" >
<string>Show &amp;text in toolbar buttons</string>
</property>
<property name="checked" >
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_2" >
@ -362,8 +351,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>583</width>
<height>625</height>
<width>595</width>
<height>638</height>
</rect>
</property>
<layout class="QVBoxLayout" >

View File

@ -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 ]

View File

@ -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 = _('<p>Could not save the following books to disk, because the %s format is not available for them:<ul>')%single_format.upper()
for f in failures:
msg += '<li>%s</li>'%f[1]
msg += '</ul>'
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,

View File

@ -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):