mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
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:
commit
336db024ae
@ -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 {
|
||||||
|
@ -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))))
|
||||||
|
@ -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'))
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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(',')
|
||||||
|
@ -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/>
|
||||||
|
@ -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()
|
||||||
|
@ -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
@ -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))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user