Catalog generation: Fixed improper title display in catalog when title contains ':'. Added 'ondevice' field to CSV/XML catalog output (only with connected device|folder|iTunes). Added optional 'Series' section to generated catalogs with hyperlinks between books and series. Tweaks to catalog formatting

This commit is contained in:
Kovid Goyal 2010-09-08 09:37:42 -06:00
commit 336db024ae
10 changed files with 807 additions and 440 deletions

View File

@ -6,7 +6,7 @@ p.title {
text-align:center; text-align:center;
font-style:italic; font-style:italic;
font-size:xx-large; font-size:xx-large;
border-bottom: solid black 4px; border-bottom: solid black 2px;
} }
p.author { p.author {
@ -17,6 +17,15 @@ p.author {
font-size:large; font-size:large;
} }
p.author_index {
font-size:large;
font-weight:bold;
text-align:left;
margin-top:0px;
margin-bottom:-2px;
text-indent: 0em;
}
p.tags { p.tags {
margin-top:0em; margin-top:0em;
margin-bottom:0em; margin-bottom:0em;
@ -47,19 +56,12 @@ p.letter_index {
margin-bottom:0px; margin-bottom:0px;
} }
p.author_index {
font-size:large;
text-align:left;
margin-top:0px;
margin-bottom:0px;
text-indent: 0em;
}
p.series { p.series {
text-align: left; font-style:italic;
margin-top:0px; margin-top:2px;
margin-bottom:0px; margin-bottom:0px;
margin-left:2em; margin-left:2em;
text-align:left;
text-indent:-2em; text-indent:-2em;
} }
@ -87,11 +89,13 @@ p.date_read {
text-indent:-6em; text-indent:-6em;
} }
hr.series_divider { hr.description_divider {
width:50%; width:90%;
margin-left:1em; margin-left:5%;
margin-top:0em; border-top: solid white 0px;
margin-bottom:0em; border-right: solid white 0px;
border-bottom: solid black 1px;
border-left: solid white 0px;
} }
hr.annotations_divider { hr.annotations_divider {

View File

@ -294,7 +294,7 @@ class CatalogPlugin(Plugin): # {{{
# Return a list of requested fields, with opts.sort_by first # Return a list of requested fields, with opts.sort_by first
all_fields = set( all_fields = set(
['author_sort','authors','comments','cover','formats', ['author_sort','authors','comments','cover','formats',
'id','isbn','pubdate','publisher','rating', 'id','isbn','ondevice','pubdate','publisher','rating',
'series_index','series','size','tags','timestamp', 'series_index','series','size','tags','timestamp',
'title','uuid']) 'title','uuid'])
@ -306,6 +306,9 @@ class CatalogPlugin(Plugin): # {{{
else: else:
fields = list(all_fields) fields = list(all_fields)
if not opts.connected_device['is_device_connected'] and 'ondevice' in fields:
fields.pop(int(fields.index('ondevice')))
fields.sort() fields.sort()
if opts.sort_by and opts.sort_by in fields: if opts.sort_by and opts.sort_by in fields:
fields.insert(0,fields.pop(int(fields.index(opts.sort_by)))) fields.insert(0,fields.pop(int(fields.index(opts.sort_by))))

View File

@ -2303,9 +2303,9 @@ class ITUNES(DriverBase):
# Delete existing from Device|Books, add to self.update_list # Delete existing from Device|Books, add to self.update_list
# for deletion from booklist[0] during add_books_to_metadata # for deletion from booklist[0] during add_books_to_metadata
for book in self.cached_books: for book in self.cached_books:
if self.cached_books[book]['uuid'] == metadata.uuid and \ if self.cached_books[book]['uuid'] == metadata.uuid or \
self.cached_books[book]['title'] == metadata.title and \ (self.cached_books[book]['title'] == metadata.title and \
self.cached_books[book]['author'] == metadata.authors[0]: self.cached_books[book]['author'] == metadata.authors[0]):
self.update_list.append(self.cached_books[book]) self.update_list.append(self.cached_books[book])
self._remove_from_device(self.cached_books[book]) self._remove_from_device(self.cached_books[book])
if DEBUG: if DEBUG:
@ -2322,9 +2322,9 @@ class ITUNES(DriverBase):
# Delete existing from Library|Books, add to self.update_list # Delete existing from Library|Books, add to self.update_list
# for deletion from booklist[0] during add_books_to_metadata # for deletion from booklist[0] during add_books_to_metadata
for book in self.cached_books: for book in self.cached_books:
if self.cached_books[book]['uuid'] == metadata.uuid and \ if self.cached_books[book]['uuid'] == metadata.uuid or \
self.cached_books[book]['title'] == metadata.title and \ (self.cached_books[book]['title'] == metadata.title and \
self.cached_books[book]['author'] == metadata.authors[0]: self.cached_books[book]['author'] == metadata.authors[0]):
self.update_list.append(self.cached_books[book]) self.update_list.append(self.cached_books[book])
self._remove_from_iTunes(self.cached_books[book]) self._remove_from_iTunes(self.cached_books[book])
if DEBUG: if DEBUG:
@ -2488,7 +2488,7 @@ class ITUNES(DriverBase):
zf_opf.close() zf_opf.close()
# If 'News' in tags, tweak the title/author for friendlier display in iBooks # If 'News' in tags, tweak the title/author for friendlier display in iBooks
if _('News') in metadata.tags: if _('News') or _('Catalog') in metadata.tags:
if metadata.title.find('[') > 0: if metadata.title.find('[') > 0:
metadata.title = metadata.title[:metadata.title.find('[')-1] metadata.title = metadata.title[:metadata.title.find('[')-1]
date_as_author = '%s, %s %s, %s' % (strftime('%A'), strftime('%B'), strftime('%d').lstrip('0'), strftime('%Y')) date_as_author = '%s, %s %s, %s' % (strftime('%A'), strftime('%B'), strftime('%d').lstrip('0'), strftime('%Y'))

View File

@ -26,14 +26,18 @@ class GenerateCatalogAction(InterfaceAction):
rows = xrange(self.gui.library_view.model().rowCount(QModelIndex())) rows = xrange(self.gui.library_view.model().rowCount(QModelIndex()))
ids = map(self.gui.library_view.model().id, rows) ids = map(self.gui.library_view.model().id, rows)
dbspec = None
if not ids: if not ids:
return error_dialog(self.gui, _('No books selected'), return error_dialog(self.gui, _('No books selected'),
_('No books selected to generate catalog for'), _('No books selected to generate catalog for'),
show=True) show=True)
db = self.gui.library_view.model().db
dbspec = {}
for id in ids:
dbspec[id] = {'ondevice': db.ondevice(id, index_is_id=True)}
# Calling gui2.tools:generate_catalog() # Calling gui2.tools:generate_catalog()
ret = generate_catalog(self.gui, dbspec, ids, self.gui.device_manager.device) ret = generate_catalog(self.gui, dbspec, ids, self.gui.device_manager)
if ret is None: if ret is None:
return return

View File

@ -19,6 +19,7 @@ class PluginWidget(QWidget,Ui_Form):
OPTION_FIELDS = [('exclude_genre','\[.+\]'), OPTION_FIELDS = [('exclude_genre','\[.+\]'),
('exclude_tags','~,'+_('Catalog')), ('exclude_tags','~,'+_('Catalog')),
('generate_titles', True), ('generate_titles', True),
('generate_series', True),
('generate_recently_added', True), ('generate_recently_added', True),
('note_tag','*'), ('note_tag','*'),
('numbers_as_text', False), ('numbers_as_text', False),
@ -40,7 +41,7 @@ class PluginWidget(QWidget,Ui_Form):
# Update dialog fields from stored options # Update dialog fields from stored options
for opt in self.OPTION_FIELDS: for opt in self.OPTION_FIELDS:
opt_value = gprefs.get(self.name + '_' + opt[0], opt[1]) opt_value = gprefs.get(self.name + '_' + opt[0], opt[1])
if opt[0] in ['numbers_as_text','generate_titles','generate_recently_added']: if opt[0] in ['numbers_as_text','generate_titles','generate_series','generate_recently_added']:
getattr(self, opt[0]).setChecked(opt_value) getattr(self, opt[0]).setChecked(opt_value)
else: else:
getattr(self, opt[0]).setText(opt_value) getattr(self, opt[0]).setText(opt_value)
@ -52,13 +53,13 @@ class PluginWidget(QWidget,Ui_Form):
# others store as lists # others store as lists
opts_dict = {} opts_dict = {}
for opt in self.OPTION_FIELDS: for opt in self.OPTION_FIELDS:
if opt[0] in ['numbers_as_text','generate_titles','generate_recently_added']: if opt[0] in ['numbers_as_text','generate_titles','generate_series','generate_recently_added']:
opt_value = getattr(self,opt[0]).isChecked() opt_value = getattr(self,opt[0]).isChecked()
else: else:
opt_value = unicode(getattr(self, opt[0]).text()) opt_value = unicode(getattr(self, opt[0]).text())
gprefs.set(self.name + '_' + opt[0], opt_value) gprefs.set(self.name + '_' + opt[0], opt_value)
if opt[0] in ['exclude_genre','numbers_as_text','generate_titles','generate_recently_added']: if opt[0] in ['exclude_genre','numbers_as_text','generate_titles','generate_series','generate_recently_added']:
opts_dict[opt[0]] = opt_value opts_dict[opt[0]] = opt_value
else: else:
opts_dict[opt[0]] = opt_value.split(',') opts_dict[opt[0]] = opt_value.split(',')

View File

@ -108,20 +108,27 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="9" column="0"> <item row="10" column="0">
<widget class="QCheckBox" name="generate_recently_added"> <widget class="QCheckBox" name="generate_recently_added">
<property name="text"> <property name="text">
<string>Include 'Recently Added' Section</string> <string>Include 'Recently Added' Section</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="10" column="0"> <item row="11" column="0">
<widget class="QCheckBox" name="numbers_as_text"> <widget class="QCheckBox" name="numbers_as_text">
<property name="text"> <property name="text">
<string>Sort numbers as text</string> <string>Sort numbers as text</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="9" column="0">
<widget class="QCheckBox" name="generate_series">
<property name="text">
<string>Include 'Series' Section</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<resources/> <resources/>

View File

@ -29,6 +29,7 @@ def gui_catalog(fmt, title, dbspec, ids, out_file_name, sync, fmt_options, conne
log = Log() log = Log()
from calibre.library import db from calibre.library import db
db = db() db = db()
db.catalog_plugin_on_device_temp_mapping = dbspec
# Create a minimal OptionParser that we can append to # Create a minimal OptionParser that we can append to
parser = OptionParser() parser = OptionParser()

View File

@ -238,7 +238,7 @@ def fetch_scheduled_recipe(arg):
return 'gui_convert', args, _('Fetch news from ')+arg['title'], fmt.upper(), [pt] return 'gui_convert', args, _('Fetch news from ')+arg['title'], fmt.upper(), [pt]
def generate_catalog(parent, dbspec, ids, device): def generate_catalog(parent, dbspec, ids, device_manager):
from calibre.gui2.dialogs.catalog import Catalog from calibre.gui2.dialogs.catalog import Catalog
# Build the Catalog dialog in gui2.dialogs.catalog # Build the Catalog dialog in gui2.dialogs.catalog
@ -252,9 +252,18 @@ def generate_catalog(parent, dbspec, ids, device):
# Profile the connected device # Profile the connected device
# Parallel initialization in calibre.library.cli:command_catalog() # Parallel initialization in calibre.library.cli:command_catalog()
connected_device = { 'storage':None,'serial':None,'save_template':None,'name':None} connected_device = {
'is_device_connected': device_manager.is_device_connected,
'kind': device_manager.connected_device_kind,
'name': None,
'save_template': None,
'serial': None,
'storage': None
}
if device: if device_manager.is_device_connected:
device = device_manager.device
connected_device['name'] = device.gui_name
try: try:
storage = [] storage = []
if device._main_prefix: if device._main_prefix:
@ -263,11 +272,10 @@ def generate_catalog(parent, dbspec, ids, device):
storage.append(os.path.join(device._card_a_prefix, device.EBOOK_DIR_CARD_A)) storage.append(os.path.join(device._card_a_prefix, device.EBOOK_DIR_CARD_A))
if device._card_b_prefix: if device._card_b_prefix:
storage.append(os.path.join(device._card_b_prefix, device.EBOOK_DIR_CARD_B)) storage.append(os.path.join(device._card_b_prefix, device.EBOOK_DIR_CARD_B))
connected_device = { 'storage': storage, connected_device['storage'] = storage
'serial': device.detected_device.serial if \ connected_device['serial'] = device.detected_device.serial if \
hasattr(device.detected_device,'serial') else None, hasattr(device.detected_device,'serial') else None
'save_template': device.save_template(), connected_device['save_template'] = device.save_template()
'name': device.gui_name}
except: except:
pass pass

File diff suppressed because it is too large Load Diff

View File

@ -674,7 +674,14 @@ def command_catalog(args, dbpath):
# No support for connected device in CLI environment # No support for connected device in CLI environment
# Parallel initialization in calibre.gui2.tools:generate_catalog() # Parallel initialization in calibre.gui2.tools:generate_catalog()
opts.connected_device = { 'storage':None,'serial':None,'save_template':None,'name':None} opts.connected_device = {
'is_device_connected': False,
'kind': None,
'name': None,
'save_template': None,
'serial': None,
'storage': None,
}
with plugin: with plugin:
plugin.run(args[1], opts, get_db(dbpath, opts)) plugin.run(args[1], opts, get_db(dbpath, opts))