GwR Series Section revisions

This commit is contained in:
GRiker 2010-09-07 11:56:16 -07:00
commit a98531a204
8 changed files with 386 additions and 90 deletions

View File

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

View File

@ -34,11 +34,10 @@ class GenerateCatalogAction(InterfaceAction):
db = self.gui.library_view.model().db
dbspec = {}
for id in ids:
dbspec[id] = {'ondevice':db.ondevice(id, index_is_id=True)}
db.catalog_plugin_on_device_temp_mapping = dbspec
dbspec[id] = {'ondevice': db.ondevice(id, index_is_id=True)}
# Calling gui2.tools:generate_catalog()
ret = generate_catalog(self.gui, db, ids, self.gui.device_manager)
ret = generate_catalog(self.gui, dbspec, ids, self.gui.device_manager)
if ret is None:
return

View File

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

View File

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

View File

@ -27,13 +27,9 @@ def gui_catalog(fmt, title, dbspec, ids, out_file_name, sync, fmt_options, conne
notification=DummyReporter(), log=None):
if log is None:
log = Log()
if dbspec is None:
from calibre.utils.config import prefs
from calibre.library.database2 import LibraryDatabase2
dbpath = prefs['library_path']
db = LibraryDatabase2(dbpath)
else: # To be implemented in the future
pass
from calibre.library import db
db = db()
db.catalog_plugin_on_device_temp_mapping = dbspec
# Create a minimal OptionParser that we can append to
parser = OptionParser()

View File

@ -10,8 +10,8 @@ from functools import partial
from PyQt4.Qt import QMainWindow, Qt, QIcon, QStatusBar, QFont, QWidget, \
QScrollArea, QStackedWidget, QVBoxLayout, QLabel, QFrame, QKeySequence, \
QToolBar, QSize, pyqtSignal, QSizePolicy, QToolButton, QAction, \
QPushButton, QHBoxLayout
QToolBar, QSize, pyqtSignal, QPixmap, QToolButton, QAction, \
QDialogButtonBox, QHBoxLayout
from calibre.constants import __appname__, __version__, islinux, isosx
from calibre.gui2 import gprefs, min_available_height, available_width, \
@ -20,6 +20,8 @@ from calibre.gui2.preferences import init_gui, AbortCommit, get_plugin
from calibre.customize.ui import preferences_plugins
from calibre.utils.ordered_dict import OrderedDict
ICON_SIZE = 32
class StatusBar(QStatusBar): # {{{
def __init__(self, parent=None):
@ -42,6 +44,32 @@ class StatusBar(QStatusBar): # {{{
# }}}
class BarTitle(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self._layout = QHBoxLayout()
self.setLayout(self._layout)
self._layout.addStretch(10)
self.icon = QLabel('')
self._layout.addWidget(self.icon)
self.title = QLabel('')
self.title.setStyleSheet('QLabel { font-weight: bold }')
self.title.setAlignment(Qt.AlignLeft | Qt.AlignCenter)
self._layout.addWidget(self.title)
self._layout.addStretch(10)
def show_plugin(self, plugin):
self.pmap = QPixmap(plugin.icon).scaled(ICON_SIZE, ICON_SIZE,
Qt.KeepAspectRatio, Qt.SmoothTransformation)
self.icon.setPixmap(self.pmap)
self.title.setText(plugin.gui_name)
tt = plugin.description
self.setStatusTip(tt)
tt = textwrap.fill(tt)
self.setToolTip(tt)
self.setWhatsThis(tt)
class Category(QWidget): # {{{
plugin_activated = pyqtSignal(object)
@ -88,7 +116,6 @@ class Category(QWidget): # {{{
class Browser(QScrollArea): # {{{
show_plugin = pyqtSignal(object)
close_signal = pyqtSignal()
def __init__(self, parent=None):
QScrollArea.__init__(self, parent)
@ -119,14 +146,6 @@ class Browser(QScrollArea): # {{{
self.container = QWidget(self)
self.container.setLayout(self._layout)
self.setWidget(self.container)
if isosx:
self._osxl = QHBoxLayout()
self.close_button = QPushButton(_('Close'))
self.close_button.clicked.connect(self.close_requested)
self._osxl.addStretch(10)
self._osxl.addWidget(self.close_button)
#self._osxl.addStretch(10)
self._layout.addLayout(self._osxl)
for name, plugins in self.category_map.items():
w = Category(name, plugins, self)
@ -134,8 +153,6 @@ class Browser(QScrollArea): # {{{
self._layout.addWidget(w)
w.plugin_activated.connect(self.show_plugin.emit)
def close_requested(self, *args):
self.close_signal.emit()
# }}}
@ -177,9 +194,15 @@ class Preferences(QMainWindow):
self.setStatusBar(self.status_bar)
self.stack = QStackedWidget(self)
self.setCentralWidget(self.stack)
self.cw = QWidget(self)
self.cw.setLayout(QVBoxLayout())
self.cw.layout().addWidget(self.stack)
self.bb = QDialogButtonBox(QDialogButtonBox.Close)
self.cw.layout().addWidget(self.bb)
self.bb.rejected.connect(self.close, type=Qt.QueuedConnection)
self.setCentralWidget(self.cw)
self.bb.setVisible(isosx)
self.browser = Browser(self)
self.browser.close_signal.connect(self.close, type=Qt.QueuedConnection)
self.browser.show_plugin.connect(self.show_plugin)
self.stack.addWidget(self.browser)
self.scroll_area = QScrollArea(self)
@ -189,7 +212,7 @@ class Preferences(QMainWindow):
self.bar = QToolBar(self)
self.addToolBar(self.bar)
self.bar.setVisible(False)
self.bar.setIconSize(QSize(32, 32))
self.bar.setIconSize(QSize(ICON_SIZE, ICON_SIZE))
self.bar.setMovable(False)
self.bar.setFloatable(False)
self.bar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
@ -197,13 +220,8 @@ class Preferences(QMainWindow):
self.commit)
self.cancel_action = self.bar.addAction(QIcon(I('window-close.png')),
_('&Cancel'), self.cancel)
self.bar_filler = QLabel('')
self.bar_filler.setSizePolicy(QSizePolicy.Expanding,
QSizePolicy.Preferred)
self.bar_filler.setStyleSheet(
'QLabel { font-weight: bold }')
self.bar_filler.setAlignment(Qt.AlignHCenter | Qt.AlignCenter)
self.bar.addWidget(self.bar_filler)
self.bar_title = BarTitle(self.bar)
self.bar.addWidget(self.bar_title)
self.restore_action = self.bar.addAction(QIcon(I('clear_left.png')),
_('Restore &defaults'), self.restore_defaults)
for ac, tt in [('apply', _('Save changes')),
@ -247,7 +265,7 @@ class Preferences(QMainWindow):
self.restore_action.setToolTip(textwrap.fill(tt))
self.restore_action.setWhatsThis(textwrap.fill(tt))
self.restore_action.setStatusTip(tt)
self.bar_filler.setText(plugin.gui_name)
self.bar_title.show_plugin(plugin)
self.setWindowIcon(QIcon(plugin.icon))
self.bar.setVisible(True)

View File

@ -20,7 +20,7 @@ from calibre.utils.date import isoformat, now as nowf
from calibre.utils.logging import default_log as log
FIELDS = ['all', 'author_sort', 'authors', 'comments',
'cover', 'formats', 'id', 'isbn', 'pubdate', 'publisher', 'rating',
'cover', 'formats', 'id', 'isbn', 'ondevice', 'pubdate', 'publisher', 'rating',
'series_index', 'series', 'size', 'tags', 'timestamp', 'title',
'uuid']
@ -96,6 +96,11 @@ class CSV_XML(CatalogPlugin):
# Get the requested output fields as a list
fields = self.get_output_fields(opts)
# If connected device, add 'On Device' values to data
if opts.connected_device['is_device_connected'] and 'ondevice' in fields:
for entry in data:
entry['ondevice'] = db.catalog_plugin_on_device_temp_mapping[entry['id']]['ondevice']
if self.fmt == 'csv':
outfile = codecs.open(path_to_output, 'w', 'utf8')
@ -104,7 +109,6 @@ class CSV_XML(CatalogPlugin):
# Output the entry fields
for entry in data:
print "%s [%s] ondevice: %s" % (entry['title'],entry['id'], repr(db.catalog_plugin_on_device_temp_mapping[entry['id']]))
outstr = []
for field in fields:
item = entry[field]
@ -142,10 +146,10 @@ class CSV_XML(CatalogPlugin):
root.append(record)
for field in ('id', 'uuid', 'title', 'publisher', 'rating', 'size',
'isbn'):
'isbn','ondevice'):
if field in fields:
val = r[field]
if val is None:
if not val:
continue
if not isinstance(val, (str, unicode)):
val = unicode(val)
@ -563,6 +567,13 @@ class EPUB_MOBI(CatalogPlugin):
help=_("Include 'Titles' section in catalog.\n"
"Default: '%default'\n"
"Applies to: ePub, MOBI output formats")),
Option('--generate-series',
default=False,
dest='generate_series',
action = 'store_true',
help=_("Include 'Series' section in catalog.\n"
"Default: '%default'\n"
"Applies to: ePub, MOBI output formats")),
Option('--generate-recently-added',
default=False,
dest='generate_recently_added',
@ -888,6 +899,9 @@ class EPUB_MOBI(CatalogPlugin):
self.__totalSteps += 2
if self.generateRecentlyRead:
self.__totalSteps += 2
if self.opts.generate_series:
self.__totalSteps += 2
# Accessors
if True:
@ -1198,6 +1212,8 @@ class EPUB_MOBI(CatalogPlugin):
self.generateHTMLByAuthor()
if self.opts.generate_titles:
self.generateHTMLByTitle()
if self.opts.generate_series:
self.generateHTMLBySeries()
if self.opts.generate_recently_added:
self.generateHTMLByDateAdded()
if self.generateRecentlyRead:
@ -1211,6 +1227,8 @@ class EPUB_MOBI(CatalogPlugin):
self.generateNCXByAuthor("Authors")
if self.opts.generate_titles:
self.generateNCXByTitle("Titles")
if self.opts.generate_series:
self.generateNCXBySeries("Series")
if self.opts.generate_recently_added:
self.generateNCXByDateAdded("Recently Added")
if self.generateRecentlyRead:
@ -1571,6 +1589,19 @@ class EPUB_MOBI(CatalogPlugin):
emTag = Tag(soup, "em")
if title['series']:
# title<br />series series_index
if self.opts.generate_series:
brTag = Tag(soup,'br')
title_tokens = list(title['title'].partition(':'))
emTag.insert(0, escape(NavigableString(title_tokens[2].strip())))
emTag.insert(1, brTag)
smallTag = Tag(soup,'small')
aTag = Tag(soup,'a')
aTag['href'] = "%s.html#%s_series" % ('BySeries',
re.sub('\W','',title['series']).lower())
aTag.insert(0, title_tokens[0])
smallTag.insert(0, aTag)
emTag.insert(2, smallTag)
else:
brTag = Tag(soup,'br')
title_tokens = list(title['title'].partition(':'))
emTag.insert(0, escape(NavigableString(title_tokens[2].strip())))
@ -1726,7 +1757,7 @@ class EPUB_MOBI(CatalogPlugin):
body.insert(btc, aTag)
btc += 1
'''
if not self.__generateForKindle:
# We don't need this because the Kindle shows section titles
#<h2><a name="byalphatitle" id="byalphatitle"></a>By Title</h2>
h2Tag = Tag(soup, "h2")
@ -1736,7 +1767,6 @@ class EPUB_MOBI(CatalogPlugin):
h2Tag.insert(1,NavigableString('By Title (%d)' % len(self.booksByTitle)))
body.insert(btc,h2Tag)
btc += 1
'''
# <p class="letter_index">
# <p class="book_title">
@ -1931,7 +1961,7 @@ class EPUB_MOBI(CatalogPlugin):
current_series = book['series']
pSeriesTag = Tag(soup,'p')
pSeriesTag['class'] = "series"
pSeriesTag.insert(0,NavigableString(self.NOT_READ_SYMBOL + '%s Series' % book['series']))
pSeriesTag.insert(0,NavigableString(self.NOT_READ_SYMBOL + '%s' % book['series']))
divTag.insert(dtc,pSeriesTag)
dtc += 1
if current_series and not book['series']:
@ -1971,7 +2001,7 @@ class EPUB_MOBI(CatalogPlugin):
divTag.insert(dtc, pBookTag)
dtc += 1
'''
if not self.__generateForKindle:
# Insert the <h2> tag with book_count at the head
#<h2><a name="byalphaauthor" id="byalphaauthor"></a>By Author</h2>
h2Tag = Tag(soup, "h2")
@ -1982,7 +2012,6 @@ class EPUB_MOBI(CatalogPlugin):
h2Tag.insert(1,NavigableString('%s (%d)' % (friendly_name, book_count)))
body.insert(btc,h2Tag)
btc += 1
'''
# Add the divTag to the body
body.insert(btc, divTag)
@ -2048,7 +2077,7 @@ class EPUB_MOBI(CatalogPlugin):
current_series = new_entry['series']
pSeriesTag = Tag(soup,'p')
pSeriesTag['class'] = "series"
pSeriesTag.insert(0,NavigableString(self.NOT_READ_SYMBOL + '%s Series' % new_entry['series']))
pSeriesTag.insert(0,NavigableString(self.NOT_READ_SYMBOL + '%s' % new_entry['series']))
divTag.insert(dtc,pSeriesTag)
dtc += 1
if current_series and not new_entry['series']:
@ -2162,8 +2191,8 @@ class EPUB_MOBI(CatalogPlugin):
aTag['name'] = anchor_name.replace(" ","")
body.insert(btc, aTag)
btc += 1
'''
# We don't need this because the kindle inserts section titles
if not self.__generateForKindle:
#<h2><a name="byalphaauthor" id="byalphaauthor"></a>By Author</h2>
h2Tag = Tag(soup, "h2")
aTag = Tag(soup, "a")
@ -2173,7 +2202,6 @@ class EPUB_MOBI(CatalogPlugin):
h2Tag.insert(1,NavigableString('%s' % friendly_name))
body.insert(btc,h2Tag)
btc += 1
'''
# <p class="letter_index">
# <p class="author_index">
@ -2439,6 +2467,158 @@ class EPUB_MOBI(CatalogPlugin):
outfile.close()
self.htmlFileList.append("content/ByDateRead.html")
def generateHTMLBySeries(self):
'''
Generate a list of series
'''
self.updateProgressFullStep("Fetching series")
self.opts.sort_by = 'series'
# Merge opts.exclude_tags with opts.search_text
# Updated to use exact match syntax
empty_exclude_tags = False if len(self.opts.exclude_tags) else True
search_phrase = 'series:true '
if not empty_exclude_tags:
exclude_tags = self.opts.exclude_tags.split(',')
search_terms = []
for tag in exclude_tags:
search_terms.append("tag:=%s" % tag)
search_phrase += "not (%s)" % " or ".join(search_terms)
# If a list of ids are provided, don't use search_text
if self.opts.ids:
self.opts.search_text = search_phrase
else:
if self.opts.search_text:
self.opts.search_text += " " + search_phrase
else:
self.opts.search_text = search_phrase
# Fetch the database as a dictionary
self.booksBySeries = self.plugin.search_sort_db(self.db, self.opts)
for series_item in self.booksBySeries:
print ' %s %s %s' % (series_item['series'],series_item['series_index'],series_item['title'])
friendly_name = "By Series"
soup = self.generateHTMLEmptyHeader(friendly_name)
body = soup.find('body')
btc = 0
# Insert section tag
aTag = Tag(soup,'a')
aTag['name'] = 'section_start'
body.insert(btc, aTag)
btc += 1
# Insert the anchor
aTag = Tag(soup, "a")
anchor_name = friendly_name.lower()
aTag['name'] = anchor_name.replace(" ","")
body.insert(btc, aTag)
btc += 1
# <p class="letter_index">
# <p class="author_index">
divTag = Tag(soup, "div")
dtc = 0
current_letter = ""
current_series = None
# Loop through booksBySeries
series_count = 0
for book in self.booksBySeries:
# Check for initial letter change
sort_title = self.generateSortTitle(book['series'])
if self.letter_or_symbol(sort_title[0].upper()) != current_letter :
'''
# Start a new letter - anchor only, hidden
current_letter = book['author_sort'][0].upper()
aTag = Tag(soup, "a")
aTag['name'] = "%sseries" % current_letter
divTag.insert(dtc, aTag)
dtc += 1
'''
# Start a new letter with Index letter
current_letter = self.letter_or_symbol(sort_title[0].upper())
pIndexTag = Tag(soup, "p")
pIndexTag['class'] = "letter_index"
aTag = Tag(soup, "a")
aTag['name'] = "%s_series" % self.letter_or_symbol(current_letter)
pIndexTag.insert(0,aTag)
pIndexTag.insert(1,NavigableString(self.letter_or_symbol(sort_title[0].upper())))
divTag.insert(dtc,pIndexTag)
dtc += 1
# Check for series change
if book['series'] != current_series:
# Start a new series
series_count += 1
current_series = book['series']
pSeriesTag = Tag(soup,'p')
pSeriesTag['class'] = "series"
aTag = Tag(soup, 'a')
aTag['name'] = "%s_series" % re.sub('\W','',book['series']).lower()
pSeriesTag.insert(0,aTag)
pSeriesTag.insert(1,NavigableString(self.NOT_READ_SYMBOL + '%s' % book['series']))
divTag.insert(dtc,pSeriesTag)
dtc += 1
# Add books
pBookTag = Tag(soup, "p")
ptc = 0
# book with read/reading/unread symbol
if 'read' in book and book['read']:
# check mark
pBookTag.insert(ptc,NavigableString(self.READ_SYMBOL))
pBookTag['class'] = "read_book"
ptc += 1
elif book['id'] in self.bookmarked_books:
pBookTag.insert(ptc,NavigableString(self.READING_SYMBOL))
pBookTag['class'] = "read_book"
ptc += 1
else:
# hidden check mark
pBookTag['class'] = "unread_book"
pBookTag.insert(ptc,NavigableString(self.NOT_READ_SYMBOL))
ptc += 1
aTag = Tag(soup, "a")
aTag['href'] = "book_%d.html" % (int(float(book['id'])))
# Use series, series index if avail else just title
aTag.insert(0,'%d. %s &middot; %s' % (book['series_index'],escape(book['title']), ' & '.join(book['authors'])))
pBookTag.insert(ptc, aTag)
ptc += 1
divTag.insert(dtc, pBookTag)
dtc += 1
if not self.__generateForKindle:
# Insert the <h2> tag with book_count at the head
#<h2><a name="byseries" id="byseries"></a>By Series</h2>
h2Tag = Tag(soup, "h2")
aTag = Tag(soup, "a")
anchor_name = friendly_name.lower()
aTag['name'] = anchor_name.replace(" ","")
h2Tag.insert(0,aTag)
h2Tag.insert(1,NavigableString('%s (%d)' % (friendly_name, series_count)))
body.insert(btc,h2Tag)
btc += 1
# Add the divTag to the body
body.insert(btc, divTag)
# Write the generated file to contentdir
outfile_spec = "%s/BySeries.html" % (self.contentDir)
outfile = open(outfile_spec, 'w')
outfile.write(soup.prettify())
outfile.close()
self.htmlFileList.append("content/BySeries.html")
def generateHTMLByTags(self):
# Generate individual HTML files for each tag, e.g. Fiction, Nonfiction ...
# Note that special tags - ~+*[] - have already been filtered from books[]
@ -2884,6 +3064,98 @@ class EPUB_MOBI(CatalogPlugin):
self.ncxSoup = ncx_soup
def generateNCXBySeries(self, tocTitle):
self.updateProgressFullStep("NCX 'Series'")
def add_to_series_by_letter(current_series_list):
current_series_list = " &bull; ".join(current_series_list)
current_series_list = self.formatNCXText(current_series_list, dest="description")
series_by_letter.append(current_series_list)
soup = self.ncxSoup
output = "BySeries"
body = soup.find("navPoint")
btc = len(body.contents)
# --- Construct the 'Books By Series' section ---
navPointTag = Tag(soup, 'navPoint')
navPointTag['class'] = "section"
navPointTag['id'] = "byseries-ID"
navPointTag['playOrder'] = self.playOrder
self.playOrder += 1
navLabelTag = Tag(soup, 'navLabel')
textTag = Tag(soup, 'text')
textTag.insert(0, NavigableString(tocTitle))
navLabelTag.insert(0, textTag)
nptc = 0
navPointTag.insert(nptc, navLabelTag)
nptc += 1
contentTag = Tag(soup,"content")
contentTag['src'] = "content/%s.html#section_start" % (output)
navPointTag.insert(nptc, contentTag)
nptc += 1
series_by_letter = []
# Loop over the series titles, find start of each letter, add description_preview_count books
# Special switch for using different title list
title_list = self.booksBySeries
current_letter = self.letter_or_symbol(title_list[0]['series'][0])
title_letters = [current_letter]
current_series_list = []
current_series = ""
for book in title_list:
sort_title = self.generateSortTitle(book['series'])
if self.letter_or_symbol(sort_title[0]) != current_letter:
# Save the old list
add_to_series_by_letter(current_series_list)
# Start the new list
current_letter = self.letter_or_symbol(sort_title[0])
title_letters.append(current_letter)
current_series = book['series']
current_series_list = [book['series']]
else:
if len(current_series_list) < self.descriptionClip and \
book['series'] != current_series :
current_series = book['series']
current_series_list.append(book['series'])
# Add the last book list
add_to_series_by_letter(current_series_list)
# Add *article* entries for each populated series title letter
for (i,books) in enumerate(series_by_letter):
navPointByLetterTag = Tag(soup, 'navPoint')
navPointByLetterTag['class'] = "article"
navPointByLetterTag['id'] = "%sSeries-ID" % (title_letters[i].upper())
navPointTag['playOrder'] = self.playOrder
self.playOrder += 1
navLabelTag = Tag(soup, 'navLabel')
textTag = Tag(soup, 'text')
textTag.insert(0, NavigableString(u"Series beginning with %s" % \
(title_letters[i] if len(title_letters[i])>1 else "'" + title_letters[i] + "'")))
navLabelTag.insert(0, textTag)
navPointByLetterTag.insert(0,navLabelTag)
contentTag = Tag(soup, 'content')
contentTag['src'] = "content/%s.html#%s_series" % (output, title_letters[i])
navPointByLetterTag.insert(1,contentTag)
if self.generateForKindle:
cmTag = Tag(soup, '%s' % 'calibre:meta')
cmTag['name'] = "description"
cmTag.insert(0, NavigableString(self.formatNCXText(books, dest='description')))
navPointByLetterTag.insert(2, cmTag)
navPointTag.insert(nptc, navPointByLetterTag)
nptc += 1
# Add this section to the body
body.insert(btc, navPointTag)
btc += 1
self.ncxSoup = soup
def generateNCXByTitle(self, tocTitle):
self.updateProgressFullStep("NCX 'Titles'")
@ -3754,7 +4026,7 @@ class EPUB_MOBI(CatalogPlugin):
current_series = book['series']
pSeriesTag = Tag(soup,'p')
pSeriesTag['class'] = "series"
pSeriesTag.insert(0,NavigableString(self.NOT_READ_SYMBOL + '%s Series' % book['series']))
pSeriesTag.insert(0,NavigableString(self.NOT_READ_SYMBOL + '%s' % book['series']))
divTag.insert(dtc,pSeriesTag)
dtc += 1

View File

@ -676,7 +676,7 @@ def command_catalog(args, dbpath):
# Parallel initialization in calibre.gui2.tools:generate_catalog()
opts.connected_device = {
'is_device_connected': False,
'kind': device_manager.connected_device_kind,
'kind': None,
'name': None,
'save_template': None,
'serial': None,