mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Catalog generation: Changes for series sorting
This commit is contained in:
commit
b856b40932
@ -17,14 +17,6 @@ p.author {
|
|||||||
font-size:large;
|
font-size:large;
|
||||||
}
|
}
|
||||||
|
|
||||||
p.series {
|
|
||||||
margin-top:0em;
|
|
||||||
margin-bottom:0em;
|
|
||||||
text-align: left;
|
|
||||||
text-indent: 1em;
|
|
||||||
font-size:small;
|
|
||||||
}
|
|
||||||
|
|
||||||
p.tags {
|
p.tags {
|
||||||
margin-top:0em;
|
margin-top:0em;
|
||||||
margin-bottom:0em;
|
margin-bottom:0em;
|
||||||
@ -63,6 +55,14 @@ p.author_index {
|
|||||||
text-indent: 0em;
|
text-indent: 0em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p.series {
|
||||||
|
text-align: left;
|
||||||
|
margin-top:0px;
|
||||||
|
margin-bottom:0px;
|
||||||
|
margin-left:2em;
|
||||||
|
text-indent:-2em;
|
||||||
|
}
|
||||||
|
|
||||||
p.read_book {
|
p.read_book {
|
||||||
text-align:left;
|
text-align:left;
|
||||||
margin-top:0px;
|
margin-top:0px;
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
|
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__copyright__ = '2008-2010, Darko Miletic <darko.miletic at gmail.com>'
|
__copyright__ = '2008-2010, Darko Miletic <darko.miletic at gmail.com>'
|
||||||
'''
|
'''
|
||||||
pagina12.com.ar
|
pagina12.com.ar
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import re, time
|
import re
|
||||||
from calibre import strftime
|
|
||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, NavigableString, CData, Tag
|
from calibre.ebooks.BeautifulSoup import BeautifulSoup
|
||||||
|
|
||||||
class Pagina12(BasicNewsRecipe):
|
class Pagina12(BasicNewsRecipe):
|
||||||
title = 'Pagina - 12'
|
title = 'Pagina - 12'
|
||||||
|
@ -57,7 +57,8 @@ def gui_catalog(fmt, title, dbspec, ids, out_file_name, sync, fmt_options,
|
|||||||
setattr(opts,option, fmt_options[option])
|
setattr(opts,option, fmt_options[option])
|
||||||
|
|
||||||
# Fetch and run the plugin for fmt
|
# Fetch and run the plugin for fmt
|
||||||
|
# Returns 0 if successful, 1 if no catalog built
|
||||||
plugin = plugin_for_catalog_format(fmt)
|
plugin = plugin_for_catalog_format(fmt)
|
||||||
plugin.run(out_file_name, opts, db, notification=notification)
|
return plugin.run(out_file_name, opts, db, notification=notification)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1394,6 +1394,11 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
|
|||||||
self.status_bar.showMessage(_('Generating %s catalog...')%fmt)
|
self.status_bar.showMessage(_('Generating %s catalog...')%fmt)
|
||||||
|
|
||||||
def catalog_generated(self, job):
|
def catalog_generated(self, job):
|
||||||
|
if job.result:
|
||||||
|
# Search terms nulled catalog results
|
||||||
|
return error_dialog(self, _('No books found'),
|
||||||
|
_("No books to catalog\nCheck exclude tags"),
|
||||||
|
show=True)
|
||||||
if job.failed:
|
if job.failed:
|
||||||
return self.job_exception(job)
|
return self.job_exception(job)
|
||||||
id = self.library_view.model().add_catalog(job.catalog_file_path, job.catalog_title)
|
id = self.library_view.model().add_catalog(job.catalog_file_path, job.catalog_title)
|
||||||
|
@ -996,25 +996,21 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
# Return -1 if x<y
|
# Return -1 if x<y
|
||||||
# Return 0 if x==y
|
# Return 0 if x==y
|
||||||
# Return 1 if x>y
|
# Return 1 if x>y
|
||||||
#print "x['author_sort']: %s y['author_sort']: %s" % (x['author_sort'],y['author_sort'])
|
# Different authors - sort by author_sort
|
||||||
if x['author_sort'] > y['author_sort']:
|
if x['author_sort'] > y['author_sort']:
|
||||||
return 1
|
return 1
|
||||||
elif x['author_sort'] < y['author_sort']:
|
elif x['author_sort'] < y['author_sort']:
|
||||||
return -1
|
return -1
|
||||||
else:
|
else:
|
||||||
# Authors equal
|
# Same author
|
||||||
# Books w/o series go first
|
if x['series'] != y['series']:
|
||||||
if x['series'] > y['series']:
|
# Different series
|
||||||
return 1
|
if x['title_sort'].lstrip() > y['title_sort'].lstrip():
|
||||||
elif x['series'] < y['series']:
|
|
||||||
return -1
|
|
||||||
elif not x['series'] and not y['series']:
|
|
||||||
if x['title'] > y['title']:
|
|
||||||
return 1
|
return 1
|
||||||
else:
|
else:
|
||||||
return -1
|
return -1
|
||||||
else:
|
else:
|
||||||
# Both books have series
|
# Same series
|
||||||
if x['series'] == y['series']:
|
if x['series'] == y['series']:
|
||||||
if float(x['series_index']) > float(y['series_index']):
|
if float(x['series_index']) > float(y['series_index']):
|
||||||
return 1
|
return 1
|
||||||
@ -1041,12 +1037,14 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
|
|
||||||
if False and self.verbose:
|
if False and self.verbose:
|
||||||
self.opts.log.info("fetchBooksByAuthor(): %d books" % len(self.booksByAuthor))
|
self.opts.log.info("fetchBooksByAuthor(): %d books" % len(self.booksByAuthor))
|
||||||
self.opts.log.info(" %-40s %-20s %s" % ('title', 'series', 'series_index'))
|
self.opts.log.info(" %-30s %-20s %s" % ('title', 'title_sort','series', 'series_index'))
|
||||||
for title in self.booksByAuthor:
|
for title in self.booksByAuthor:
|
||||||
self.opts.log.info((u" %-40s %-20s %s" % \
|
self.opts.log.info((u" %-30s %-20s %-20s%5s " % \
|
||||||
(title['title'][0:40],
|
(title['title'][:30],
|
||||||
title['series'][0:20] if title['series'] else '',
|
title['series'][:20] if title['series'] else '',
|
||||||
title['series_index'])).encode('utf-8'))
|
title['series_index'],
|
||||||
|
)).encode('utf-8'))
|
||||||
|
raise SystemExit
|
||||||
|
|
||||||
# Build the unique_authors set from existing data
|
# Build the unique_authors set from existing data
|
||||||
authors = [(record['author'], record['author_sort']) for record in self.booksByAuthor]
|
authors = [(record['author'], record['author_sort']) for record in self.booksByAuthor]
|
||||||
@ -1396,8 +1394,9 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
dtc = 0
|
dtc = 0
|
||||||
current_letter = ""
|
current_letter = ""
|
||||||
current_author = ""
|
current_author = ""
|
||||||
|
current_series = None
|
||||||
|
|
||||||
# Loop through books_by_author
|
# Loop through booksByAuthor
|
||||||
book_count = 0
|
book_count = 0
|
||||||
for book in self.booksByAuthor:
|
for book in self.booksByAuthor:
|
||||||
book_count += 1
|
book_count += 1
|
||||||
@ -1435,11 +1434,23 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
divTag.insert(dtc,pAuthorTag)
|
divTag.insert(dtc,pAuthorTag)
|
||||||
dtc += 1
|
dtc += 1
|
||||||
|
|
||||||
|
# Check for series
|
||||||
|
if book['series'] and book['series'] != current_series:
|
||||||
|
# Start a new series
|
||||||
|
current_series = book['series']
|
||||||
|
pSeriesTag = Tag(soup,'p')
|
||||||
|
pSeriesTag['class'] = "series"
|
||||||
|
pSeriesTag.insert(0,NavigableString(self.NOT_READ_SYMBOL + book['series']))
|
||||||
|
divTag.insert(dtc,pSeriesTag)
|
||||||
|
dtc += 1
|
||||||
|
if current_series and not book['series']:
|
||||||
|
current_series = None
|
||||||
|
|
||||||
# Add books
|
# Add books
|
||||||
pBookTag = Tag(soup, "p")
|
pBookTag = Tag(soup, "p")
|
||||||
ptc = 0
|
ptc = 0
|
||||||
|
|
||||||
# Prefix book with read/unread symbol
|
# book with read/unread symbol
|
||||||
if book['read']:
|
if book['read']:
|
||||||
# check mark
|
# check mark
|
||||||
pBookTag.insert(ptc,NavigableString(self.READ_SYMBOL))
|
pBookTag.insert(ptc,NavigableString(self.READ_SYMBOL))
|
||||||
@ -1454,6 +1465,9 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
aTag = Tag(soup, "a")
|
aTag = Tag(soup, "a")
|
||||||
aTag['href'] = "book_%d.html" % (int(float(book['id'])))
|
aTag['href'] = "book_%d.html" % (int(float(book['id'])))
|
||||||
# Use series, series index if avail else just title
|
# Use series, series index if avail else just title
|
||||||
|
if current_series:
|
||||||
|
aTag.insert(0,escape(book['title'][len(book['series'])+1:]))
|
||||||
|
else:
|
||||||
aTag.insert(0,escape(book['title']))
|
aTag.insert(0,escape(book['title']))
|
||||||
pBookTag.insert(ptc, aTag)
|
pBookTag.insert(ptc, aTag)
|
||||||
ptc += 1
|
ptc += 1
|
||||||
@ -1506,6 +1520,7 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
divTag.insert(dtc,pIndexTag)
|
divTag.insert(dtc,pIndexTag)
|
||||||
dtc += 1
|
dtc += 1
|
||||||
current_author = None
|
current_author = None
|
||||||
|
current_series = None
|
||||||
|
|
||||||
for new_entry in this_months_list:
|
for new_entry in this_months_list:
|
||||||
if new_entry['author'] != current_author:
|
if new_entry['author'] != current_author:
|
||||||
@ -1522,6 +1537,18 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
divTag.insert(dtc,pAuthorTag)
|
divTag.insert(dtc,pAuthorTag)
|
||||||
dtc += 1
|
dtc += 1
|
||||||
|
|
||||||
|
# Check for series
|
||||||
|
if new_entry['series'] and new_entry['series'] != current_series:
|
||||||
|
# Start a new series
|
||||||
|
current_series = new_entry['series']
|
||||||
|
pSeriesTag = Tag(soup,'p')
|
||||||
|
pSeriesTag['class'] = "series"
|
||||||
|
pSeriesTag.insert(0,NavigableString(self.NOT_READ_SYMBOL + new_entry['series']))
|
||||||
|
divTag.insert(dtc,pSeriesTag)
|
||||||
|
dtc += 1
|
||||||
|
if current_series and not new_entry['series']:
|
||||||
|
current_series = None
|
||||||
|
|
||||||
# Add books
|
# Add books
|
||||||
pBookTag = Tag(soup, "p")
|
pBookTag = Tag(soup, "p")
|
||||||
ptc = 0
|
ptc = 0
|
||||||
@ -1540,6 +1567,9 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
|
|
||||||
aTag = Tag(soup, "a")
|
aTag = Tag(soup, "a")
|
||||||
aTag['href'] = "book_%d.html" % (int(float(new_entry['id'])))
|
aTag['href'] = "book_%d.html" % (int(float(new_entry['id'])))
|
||||||
|
if current_series:
|
||||||
|
aTag.insert(0,escape(new_entry['title'][len(new_entry['series'])+1:]))
|
||||||
|
else:
|
||||||
aTag.insert(0,escape(new_entry['title']))
|
aTag.insert(0,escape(new_entry['title']))
|
||||||
pBookTag.insert(ptc, aTag)
|
pBookTag.insert(ptc, aTag)
|
||||||
ptc += 1
|
ptc += 1
|
||||||
@ -1641,6 +1671,7 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
this_book['author_sort'] = book['author_sort']
|
this_book['author_sort'] = book['author_sort']
|
||||||
this_book['read'] = book['read']
|
this_book['read'] = book['read']
|
||||||
this_book['id'] = book['id']
|
this_book['id'] = book['id']
|
||||||
|
this_book['series'] = book['series']
|
||||||
normalized_tag = self.genre_tags_dict[friendly_tag]
|
normalized_tag = self.genre_tags_dict[friendly_tag]
|
||||||
genre_tag_list = [key for genre in genre_list for key in genre]
|
genre_tag_list = [key for genre in genre_list for key in genre]
|
||||||
if normalized_tag in genre_tag_list:
|
if normalized_tag in genre_tag_list:
|
||||||
@ -2578,6 +2609,7 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
dtc = 0
|
dtc = 0
|
||||||
|
|
||||||
current_author = ''
|
current_author = ''
|
||||||
|
current_series = None
|
||||||
for book in books:
|
for book in books:
|
||||||
if book['author'] != current_author:
|
if book['author'] != current_author:
|
||||||
# Start a new author with link
|
# Start a new author with link
|
||||||
@ -2593,6 +2625,19 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
divTag.insert(dtc,pAuthorTag)
|
divTag.insert(dtc,pAuthorTag)
|
||||||
dtc += 1
|
dtc += 1
|
||||||
|
|
||||||
|
# Check for series
|
||||||
|
if book['series'] and book['series'] != current_series:
|
||||||
|
# Start a new series
|
||||||
|
current_series = book['series']
|
||||||
|
pSeriesTag = Tag(soup,'p')
|
||||||
|
pSeriesTag['class'] = "series"
|
||||||
|
pSeriesTag.insert(0,NavigableString(self.NOT_READ_SYMBOL + book['series']))
|
||||||
|
divTag.insert(dtc,pSeriesTag)
|
||||||
|
dtc += 1
|
||||||
|
|
||||||
|
if current_series and not book['series']:
|
||||||
|
current_series = None
|
||||||
|
|
||||||
# Add books
|
# Add books
|
||||||
pBookTag = Tag(soup, "p")
|
pBookTag = Tag(soup, "p")
|
||||||
ptc = 0
|
ptc = 0
|
||||||
@ -2609,6 +2654,10 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
# Add the book title
|
# Add the book title
|
||||||
aTag = Tag(soup, "a")
|
aTag = Tag(soup, "a")
|
||||||
aTag['href'] = "book_%d.html" % (int(float(book['id'])))
|
aTag['href'] = "book_%d.html" % (int(float(book['id'])))
|
||||||
|
# Use series, series index if avail else just title
|
||||||
|
if current_series:
|
||||||
|
aTag.insert(0,escape(book['title'][len(book['series'])+1:]))
|
||||||
|
else:
|
||||||
aTag.insert(0,escape(book['title']))
|
aTag.insert(0,escape(book['title']))
|
||||||
pBookTag.insert(ptc, aTag)
|
pBookTag.insert(ptc, aTag)
|
||||||
ptc += 1
|
ptc += 1
|
||||||
@ -2879,9 +2928,41 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
return char
|
return char
|
||||||
|
|
||||||
def markdownComments(self, comments):
|
def markdownComments(self, comments):
|
||||||
''' Convert random comment text to normalized, xml-legal block of <p>s'''
|
'''
|
||||||
|
Convert random comment text to normalized, xml-legal block of <p>s
|
||||||
|
'plain text' returns as
|
||||||
|
<p>plain text</p>
|
||||||
|
|
||||||
comments = comments.replace('\r', '')
|
'plain text with <i>minimal</i> <b>markup</b>' returns as
|
||||||
|
<p>plain text with <i>minimal</i> <b>markup</b></p>
|
||||||
|
|
||||||
|
'<p>pre-formatted text</p> returns untouched
|
||||||
|
|
||||||
|
'A line of text\n\nFollowed by a line of text' returns as
|
||||||
|
<p>A line of text</p>
|
||||||
|
<p>Followed by a line of text</p>
|
||||||
|
|
||||||
|
'A line of text.\nA second line of text.\rA third line of text' returns as
|
||||||
|
<p>A line of text.<br />A second line of text.<br />A third line of text.</p>
|
||||||
|
|
||||||
|
'...end of a paragraph.Somehow the break was lost...' returns as
|
||||||
|
<p>...end of a paragraph.</p>
|
||||||
|
<p>Somehow the break was lost...</p>
|
||||||
|
|
||||||
|
Deprecated HTML returns as HTML via BeautifulSoup()
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
# Explode lost CRs to \n\n
|
||||||
|
# Hackish - ignoring sentences ending or beginning in numbers to avoid
|
||||||
|
# confusion with decimal points.
|
||||||
|
for lost_cr in re.finditer('([a-z])([\.\?!])([A-Z])',comments):
|
||||||
|
comments = comments.replace(lost_cr.group(),
|
||||||
|
'%s%s\n\n%s' % (lost_cr.group(1),
|
||||||
|
lost_cr.group(2),
|
||||||
|
lost_cr.group(3)))
|
||||||
|
|
||||||
|
# Convert \n\n to <p>s
|
||||||
if re.search('\n\n', comments):
|
if re.search('\n\n', comments):
|
||||||
soup = BeautifulSoup()
|
soup = BeautifulSoup()
|
||||||
split_ps = comments.split('\n\n')
|
split_ps = comments.split('\n\n')
|
||||||
@ -2891,7 +2972,11 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
pTag.insert(0,p)
|
pTag.insert(0,p)
|
||||||
soup.insert(tsc,pTag)
|
soup.insert(tsc,pTag)
|
||||||
tsc += 1
|
tsc += 1
|
||||||
else:
|
comments = soup.renderContents()
|
||||||
|
|
||||||
|
# Convert solo returns to <br />
|
||||||
|
comments = re.sub('[\r\n]','<br />', comments)
|
||||||
|
|
||||||
soup = BeautifulSoup(comments)
|
soup = BeautifulSoup(comments)
|
||||||
|
|
||||||
result = BeautifulSoup()
|
result = BeautifulSoup()
|
||||||
@ -2924,7 +3009,6 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
ptc = 0
|
ptc = 0
|
||||||
# Clean up NavigableStrings for xml
|
# Clean up NavigableStrings for xml
|
||||||
sub_tokens = list(token.contents)
|
sub_tokens = list(token.contents)
|
||||||
sub_soup = BeautifulSoup()
|
|
||||||
for sub_token in sub_tokens:
|
for sub_token in sub_tokens:
|
||||||
if type(sub_token) is NavigableString:
|
if type(sub_token) is NavigableString:
|
||||||
sub_token.replaceWith(prepare_string_for_xml(sub_token))
|
sub_token.replaceWith(prepare_string_for_xml(sub_token))
|
||||||
@ -3001,6 +3085,12 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
'CLI' if opts.cli_environment else 'GUI'))
|
'CLI' if opts.cli_environment else 'GUI'))
|
||||||
if opts_dict['ids']:
|
if opts_dict['ids']:
|
||||||
log(" Book count: %d" % len(opts_dict['ids']))
|
log(" Book count: %d" % len(opts_dict['ids']))
|
||||||
|
|
||||||
|
# If exclude_genre is blank, assume user wants all genre tags included
|
||||||
|
if opts.exclude_genre.strip() == '':
|
||||||
|
opts.exclude_genre = '\[^.\]'
|
||||||
|
log(" converting empty exclude_genre to '\[^.\]'")
|
||||||
|
|
||||||
# Display opts
|
# Display opts
|
||||||
keys = opts_dict.keys()
|
keys = opts_dict.keys()
|
||||||
keys.sort()
|
keys.sort()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user