mirror of
				https://github.com/kovidgoyal/calibre.git
				synced 2025-11-03 19:17:02 -05:00 
			
		
		
		
	GwR catalog 1.0 revisions
This commit is contained in:
		
							parent
							
								
									46119745cb
								
							
						
					
					
						commit
						9013a5d97d
					
				
							
								
								
									
										39
									
								
								resources/catalog/section_list_templates.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								resources/catalog/section_list_templates.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python
 | 
				
			||||||
 | 
					# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__license__   = 'GPL v3'
 | 
				
			||||||
 | 
					__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
 | 
				
			||||||
 | 
					__docformat__ = 'restructuredtext en'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					'''
 | 
				
			||||||
 | 
					    Available fields:
 | 
				
			||||||
 | 
					    {title}          Title of the book
 | 
				
			||||||
 | 
					    {series}         Series name
 | 
				
			||||||
 | 
					    {series_index}   Number of the book in the series
 | 
				
			||||||
 | 
					    {rating}         Rating
 | 
				
			||||||
 | 
					    {rating_parens}  Rating, in parentheses
 | 
				
			||||||
 | 
					    {pubyear}        Year the book was published
 | 
				
			||||||
 | 
					    {pubyear_parens} Year the book was published, in parentheses
 | 
				
			||||||
 | 
					'''
 | 
				
			||||||
 | 
					# Books by Author
 | 
				
			||||||
 | 
					by_authors_normal_title_template = '{title} {pubyear_parens}'
 | 
				
			||||||
 | 
					by_authors_series_title_template = '[{series_index}] {title} {pubyear_parens}'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Books by Title
 | 
				
			||||||
 | 
					by_titles_normal_title_template = '{title}'
 | 
				
			||||||
 | 
					by_titles_series_title_template = '{title} ({series} [{series_index}])'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Books by Series
 | 
				
			||||||
 | 
					by_series_title_template = '[{series_index}] {title} {pubyear_parens}'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Books by Genre
 | 
				
			||||||
 | 
					by_genres_normal_title_template = '{title} {pubyear_parens}'
 | 
				
			||||||
 | 
					by_genres_series_title_template = '{series_index}. {title} {pubyear_parens}'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Recently Added
 | 
				
			||||||
 | 
					by_recently_added_normal_title_template = '{title}'
 | 
				
			||||||
 | 
					by_recently_added_series_title_template = '{title} ({series} [{series_index}])'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# By Month added
 | 
				
			||||||
 | 
					by_month_added_normal_title_template = '{title} {pubyear_parens}'
 | 
				
			||||||
 | 
					by_month_added_series_title_template = '[{series_index}] {title} {pubyear_parens}'
 | 
				
			||||||
@ -5,11 +5,11 @@ __license__   = 'GPL v3'
 | 
				
			|||||||
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
 | 
					__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
 | 
				
			||||||
__docformat__ = 'restructuredtext en'
 | 
					__docformat__ = 'restructuredtext en'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import os, shutil
 | 
					import re, os, shutil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PyQt4.Qt import QModelIndex
 | 
					from PyQt4.Qt import QModelIndex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from calibre.gui2 import error_dialog, choose_dir
 | 
					from calibre.gui2 import choose_dir, error_dialog, info_dialog, warning_dialog
 | 
				
			||||||
from calibre.gui2.tools import generate_catalog
 | 
					from calibre.gui2.tools import generate_catalog
 | 
				
			||||||
from calibre.utils.config import dynamic
 | 
					from calibre.utils.config import dynamic
 | 
				
			||||||
from calibre.gui2.actions import InterfaceAction
 | 
					from calibre.gui2.actions import InterfaceAction
 | 
				
			||||||
@ -55,10 +55,16 @@ class GenerateCatalogAction(InterfaceAction):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def catalog_generated(self, job):
 | 
					    def catalog_generated(self, job):
 | 
				
			||||||
        if job.result:
 | 
					        if job.result:
 | 
				
			||||||
            # Error during catalog generation
 | 
					            # Problems during catalog generation
 | 
				
			||||||
            return error_dialog(self.gui, _('Catalog generation terminated'),
 | 
					            dialog_title = job.result.pop(0)
 | 
				
			||||||
                    job.result,
 | 
					            if re.match('warning:', job.result[0].lower()):
 | 
				
			||||||
                    show=True)
 | 
					                job.result.append("Catalog generation complete.")
 | 
				
			||||||
 | 
					                warning_dialog(self.gui, dialog_title, '\n'.join(job.result), show=True)
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                job.result.append("Catalog generation terminated.")
 | 
				
			||||||
 | 
					                error_dialog(self.gui, dialog_title,'\n'.join(job.result),show=True)
 | 
				
			||||||
 | 
					                return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if job.failed:
 | 
					        if job.failed:
 | 
				
			||||||
            return self.gui.job_exception(job)
 | 
					            return self.gui.job_exception(job)
 | 
				
			||||||
        id = self.gui.library_view.model().add_catalog(job.catalog_file_path, job.catalog_title)
 | 
					        id = self.gui.library_view.model().add_catalog(job.catalog_file_path, job.catalog_title)
 | 
				
			||||||
 | 
				
			|||||||
@ -546,9 +546,9 @@ class EPUB_MOBI(CatalogPlugin):
 | 
				
			|||||||
    name = 'Catalog_EPUB_MOBI'
 | 
					    name = 'Catalog_EPUB_MOBI'
 | 
				
			||||||
    description = 'EPUB/MOBI catalog generator'
 | 
					    description = 'EPUB/MOBI catalog generator'
 | 
				
			||||||
    supported_platforms = ['windows', 'osx', 'linux']
 | 
					    supported_platforms = ['windows', 'osx', 'linux']
 | 
				
			||||||
    minimum_calibre_version = (0, 6, 34)
 | 
					    minimum_calibre_version = (0, 7, 40)
 | 
				
			||||||
    author = 'Greg Riker'
 | 
					    author = 'Greg Riker'
 | 
				
			||||||
    version = (0, 0, 1)
 | 
					    version = (1, 0, 0)
 | 
				
			||||||
    file_types = set(['epub','mobi'])
 | 
					    file_types = set(['epub','mobi'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    THUMB_SMALLEST = "1.0"
 | 
					    THUMB_SMALLEST = "1.0"
 | 
				
			||||||
@ -900,15 +900,7 @@ class EPUB_MOBI(CatalogPlugin):
 | 
				
			|||||||
        '''
 | 
					        '''
 | 
				
			||||||
        Generates catalog source files from calibre database
 | 
					        Generates catalog source files from calibre database
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Implementation notes
 | 
					        Flow of control:
 | 
				
			||||||
        - 'Marker tags' in a book's metadata are used to flag special conditions:
 | 
					 | 
				
			||||||
                    (Defaults)
 | 
					 | 
				
			||||||
                    '~' : Do not catalog this book
 | 
					 | 
				
			||||||
                    '+' : Mark this book as read (check mark) in lists
 | 
					 | 
				
			||||||
                    '*' : Display trailing text as 'Note: <text>' in top frame next to cover
 | 
					 | 
				
			||||||
            '[<source>] : Source of content (e.g., Amazon, Project Gutenberg).  Do not create genre
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        - Program flow
 | 
					 | 
				
			||||||
            gui2.actions.catalog:generate_catalog()
 | 
					            gui2.actions.catalog:generate_catalog()
 | 
				
			||||||
            gui2.tools:generate_catalog() or library.cli:command_catalog()
 | 
					            gui2.tools:generate_catalog() or library.cli:command_catalog()
 | 
				
			||||||
            called from gui2.convert.gui_conversion:gui_catalog()
 | 
					            called from gui2.convert.gui_conversion:gui_catalog()
 | 
				
			||||||
@ -953,7 +945,7 @@ class EPUB_MOBI(CatalogPlugin):
 | 
				
			|||||||
            self.__creator = opts.creator
 | 
					            self.__creator = opts.creator
 | 
				
			||||||
            self.__db = db
 | 
					            self.__db = db
 | 
				
			||||||
            self.__descriptionClip = opts.descriptionClip
 | 
					            self.__descriptionClip = opts.descriptionClip
 | 
				
			||||||
            self.__error = None
 | 
					            self.__error = []
 | 
				
			||||||
            self.__generateForKindle = True if (self.opts.fmt == 'mobi' and \
 | 
					            self.__generateForKindle = True if (self.opts.fmt == 'mobi' and \
 | 
				
			||||||
                                       self.opts.output_profile and \
 | 
					                                       self.opts.output_profile and \
 | 
				
			||||||
                                       self.opts.output_profile.startswith("kindle")) else False
 | 
					                                       self.opts.output_profile.startswith("kindle")) else False
 | 
				
			||||||
@ -1033,6 +1025,22 @@ class EPUB_MOBI(CatalogPlugin):
 | 
				
			|||||||
                # +1 thumbs
 | 
					                # +1 thumbs
 | 
				
			||||||
                self.__totalSteps += 3
 | 
					                self.__totalSteps += 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # Load section list templates
 | 
				
			||||||
 | 
					            templates = ['by_authors_normal_title_template',
 | 
				
			||||||
 | 
					                         'by_authors_series_title_template',
 | 
				
			||||||
 | 
					                         'by_titles_normal_title_template',
 | 
				
			||||||
 | 
					                         'by_titles_series_title_template',
 | 
				
			||||||
 | 
					                         'by_series_title_template',
 | 
				
			||||||
 | 
					                         'by_genres_normal_title_template',
 | 
				
			||||||
 | 
					                         'by_genres_series_title_template',
 | 
				
			||||||
 | 
					                         'by_recently_added_normal_title_template',
 | 
				
			||||||
 | 
					                         'by_recently_added_series_title_template',
 | 
				
			||||||
 | 
					                         'by_month_added_normal_title_template',
 | 
				
			||||||
 | 
					                         'by_month_added_series_title_template']
 | 
				
			||||||
 | 
					            execfile(P(os.path.join('catalog','section_list_templates.py')),locals())
 | 
				
			||||||
 | 
					            for t in templates:
 | 
				
			||||||
 | 
					                setattr(self,t,eval(t))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Accessors
 | 
					        # Accessors
 | 
				
			||||||
        if True:
 | 
					        if True:
 | 
				
			||||||
            '''
 | 
					            '''
 | 
				
			||||||
@ -1420,26 +1428,12 @@ class EPUB_MOBI(CatalogPlugin):
 | 
				
			|||||||
            '''
 | 
					            '''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            self.updateProgressFullStep("Sorting database")
 | 
					            self.updateProgressFullStep("Sorting database")
 | 
				
			||||||
 | 
					 | 
				
			||||||
            '''
 | 
					 | 
				
			||||||
            # Sort titles case-insensitive, by author
 | 
					 | 
				
			||||||
            self.booksByAuthor = sorted(self.booksByTitle,
 | 
					 | 
				
			||||||
                                 key=lambda x:(x['author_sort'].upper(), x['author_sort'].upper()))
 | 
					 | 
				
			||||||
            '''
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            self.booksByAuthor = list(self.booksByTitle)
 | 
					            self.booksByAuthor = list(self.booksByTitle)
 | 
				
			||||||
            self.booksByAuthor.sort(self.author_compare)
 | 
					            self.booksByAuthor = sorted(self.booksByAuthor, key=self.booksByAuthorSorter_author)
 | 
				
			||||||
 | 
					#             for book in self.booksByAuthor:
 | 
				
			||||||
            if False and self.verbose:
 | 
					#                 print "{0:<30}  {1:<30}  {2:<30}".format(book['title'],book['author'],book['author_sort'])
 | 
				
			||||||
                self.opts.log.info("fetchBooksByAuthor(): %d books" % len(self.booksByAuthor))
 | 
					#             print
 | 
				
			||||||
                self.opts.log.info(" %-30s %-20s %s" % ('title', 'series', 'series_index'))
 | 
					#             stop
 | 
				
			||||||
                for title in self.booksByAuthor:
 | 
					 | 
				
			||||||
                    self.opts.log.info((u" %-30s %-20s%5s " % \
 | 
					 | 
				
			||||||
                                        (title['title'][:30],
 | 
					 | 
				
			||||||
                                         title['series'][:20] if title['series'] else '',
 | 
					 | 
				
			||||||
                                         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'].capitalize()) for record in self.booksByAuthor]
 | 
					            authors = [(record['author'], record['author_sort'].capitalize()) for record in self.booksByAuthor]
 | 
				
			||||||
@ -1457,16 +1451,17 @@ class EPUB_MOBI(CatalogPlugin):
 | 
				
			|||||||
                    multiple_authors = True
 | 
					                    multiple_authors = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if author != current_author and i:
 | 
					                if author != current_author and i:
 | 
				
			||||||
                    # Warn, exit if friendly matches previous, but sort doesn't
 | 
					                    # Exit if author matches previous, but author_sort doesn't match
 | 
				
			||||||
                    if author[0] == current_author[0]:
 | 
					                    if author[0] == current_author[0]:
 | 
				
			||||||
                        error_msg = _('''
 | 
					                        error_msg = _('''
 | 
				
			||||||
\n*** Metadata error ***
 | 
					Inconsistent Author Sort values for Author '{0}', unable to continue building catalog.\n
 | 
				
			||||||
Inconsistent Author Sort values for Author '{0}', unable to continue building catalog.
 | 
					 | 
				
			||||||
Select all books by '{0}', apply correct Author Sort value in Edit Metadata dialog,
 | 
					Select all books by '{0}', apply correct Author Sort value in Edit Metadata dialog,
 | 
				
			||||||
then rebuild the catalog.\n''').format(author[0])
 | 
					then rebuild the catalog.\n''').format(author[0])
 | 
				
			||||||
 | 
					                        self.opts.log.warn('\n*** Metadata error ***')
 | 
				
			||||||
                        self.opts.log.warn(error_msg)
 | 
					                        self.opts.log.warn(error_msg)
 | 
				
			||||||
                        self.error = error_msg
 | 
					
 | 
				
			||||||
 | 
					                        self.error.append('Metadata error')
 | 
				
			||||||
 | 
					                        self.error.append(error_msg)
 | 
				
			||||||
                        return False
 | 
					                        return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    # New author, save the previous author/sort/count
 | 
					                    # New author, save the previous author/sort/count
 | 
				
			||||||
@ -1496,16 +1491,8 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
            return True
 | 
					            return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def fetchBooksByTitle(self):
 | 
					        def fetchBooksByTitle(self):
 | 
				
			||||||
 | 
					 | 
				
			||||||
            self.updateProgressFullStep("Fetching database")
 | 
					            self.updateProgressFullStep("Fetching database")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # Get the database as a dictionary
 | 
					 | 
				
			||||||
            # Sort by title
 | 
					 | 
				
			||||||
            # Search is a string like this:
 | 
					 | 
				
			||||||
            # not tag:<exclude_tag> author:"Riker"
 | 
					 | 
				
			||||||
            # So we need to merge opts.exclude_tag with opts.search_text
 | 
					 | 
				
			||||||
            # not tag:"~" author:"Riker"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            self.opts.sort_by = 'title'
 | 
					            self.opts.sort_by = 'title'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # Merge opts.exclude_tags with opts.search_text
 | 
					            # Merge opts.exclude_tags with opts.search_text
 | 
				
			||||||
@ -1528,7 +1515,6 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
                else:
 | 
					                else:
 | 
				
			||||||
                    self.opts.search_text = search_phrase
 | 
					                    self.opts.search_text = search_phrase
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            #print "fetchBooksByTitle(): opts.search_text: %s" % self.opts.search_text
 | 
					 | 
				
			||||||
            # Fetch the database as a dictionary
 | 
					            # Fetch the database as a dictionary
 | 
				
			||||||
            data = self.plugin.search_sort_db(self.db, self.opts)
 | 
					            data = self.plugin.search_sort_db(self.db, self.opts)
 | 
				
			||||||
            data = self.processExclusions(data)
 | 
					            data = self.processExclusions(data)
 | 
				
			||||||
@ -1536,8 +1522,6 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
            # Populate this_title{} from data[{},{}]
 | 
					            # Populate this_title{} from data[{},{}]
 | 
				
			||||||
            titles = []
 | 
					            titles = []
 | 
				
			||||||
            for record in data:
 | 
					            for record in data:
 | 
				
			||||||
                if False:
 | 
					 | 
				
			||||||
                    print "available record metadata:\n%s" % sorted(record.keys())
 | 
					 | 
				
			||||||
                this_title = {}
 | 
					                this_title = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                this_title['id'] = record['id']
 | 
					                this_title['id'] = record['id']
 | 
				
			||||||
@ -1547,7 +1531,6 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
                if record['series']:
 | 
					                if record['series']:
 | 
				
			||||||
                    this_title['series'] = record['series']
 | 
					                    this_title['series'] = record['series']
 | 
				
			||||||
                    this_title['series_index'] = record['series_index']
 | 
					                    this_title['series_index'] = record['series_index']
 | 
				
			||||||
                    this_title['title'] = self.generateSeriesTitle(this_title)
 | 
					 | 
				
			||||||
                else:
 | 
					                else:
 | 
				
			||||||
                    this_title['series'] = None
 | 
					                    this_title['series'] = None
 | 
				
			||||||
                    this_title['series_index'] = 0.0
 | 
					                    this_title['series_index'] = 0.0
 | 
				
			||||||
@ -1572,7 +1555,12 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
                    this_title['publisher'] = re.sub('&', '&', record['publisher'])
 | 
					                    this_title['publisher'] = re.sub('&', '&', record['publisher'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                this_title['rating'] = record['rating'] if record['rating'] else 0
 | 
					                this_title['rating'] = record['rating'] if record['rating'] else 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if re.match('0100-01-01',str(record['pubdate'].date())):
 | 
				
			||||||
 | 
					                    this_title['date'] = None
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
                    this_title['date'] = strftime(u'%B %Y', record['pubdate'].timetuple())
 | 
					                    this_title['date'] = strftime(u'%B %Y', record['pubdate'].timetuple())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                this_title['timestamp'] = record['timestamp']
 | 
					                this_title['timestamp'] = record['timestamp']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if record['comments']:
 | 
					                if record['comments']:
 | 
				
			||||||
@ -1646,7 +1634,7 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
                                                               title['title_sort'][0:40])).decode('mac-roman'))
 | 
					                                                               title['title_sort'][0:40])).decode('mac-roman'))
 | 
				
			||||||
                return True
 | 
					                return True
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                self.error = _("No books found to catalog.\nCheck 'Excluded books' criteria in E-book options.")
 | 
					                self.error.append( _("No books found to catalog.\nCheck 'Excluded books' criteria in E-book options."))
 | 
				
			||||||
                return False
 | 
					                return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def fetchBookmarks(self):
 | 
					        def fetchBookmarks(self):
 | 
				
			||||||
@ -1748,13 +1736,12 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
                self.bookmarked_books = {}
 | 
					                self.bookmarked_books = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def generateHTMLDescriptions(self):
 | 
					        def generateHTMLDescriptions(self):
 | 
				
			||||||
            # Write each title to a separate HTML file in contentdir
 | 
					            '''
 | 
				
			||||||
 | 
					            Write each title to a separate HTML file in contentdir
 | 
				
			||||||
 | 
					            '''
 | 
				
			||||||
            self.updateProgressFullStep("'Descriptions'")
 | 
					            self.updateProgressFullStep("'Descriptions'")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            for (title_num, title) in enumerate(self.booksByTitle):
 | 
					            for (title_num, title) in enumerate(self.booksByTitle):
 | 
				
			||||||
                if False:
 | 
					 | 
				
			||||||
                    self.opts.log.info("%3s: %s - %s" % (title['id'], title['title'], title['author']))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                self.updateProgressMicroStep("Description %d of %d" % \
 | 
					                self.updateProgressMicroStep("Description %d of %d" % \
 | 
				
			||||||
                                             (title_num, len(self.booksByTitle)),
 | 
					                                             (title_num, len(self.booksByTitle)),
 | 
				
			||||||
                                             float(title_num*100/len(self.booksByTitle))/100)
 | 
					                                             float(title_num*100/len(self.booksByTitle))/100)
 | 
				
			||||||
@ -1768,8 +1755,9 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
                outfile.close()
 | 
					                outfile.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def generateHTMLByTitle(self):
 | 
					        def generateHTMLByTitle(self):
 | 
				
			||||||
            # Write books by title A-Z to HTML file
 | 
					            '''
 | 
				
			||||||
 | 
					            Write books by title A-Z to HTML file
 | 
				
			||||||
 | 
					            '''
 | 
				
			||||||
            self.updateProgressFullStep("'Titles'")
 | 
					            self.updateProgressFullStep("'Titles'")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            soup = self.generateHTMLEmptyHeader("Books By Alpha Title")
 | 
					            soup = self.generateHTMLEmptyHeader("Books By Alpha Title")
 | 
				
			||||||
@ -1807,22 +1795,11 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
            current_letter = ""
 | 
					            current_letter = ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # Re-sort title list without leading series/series_index
 | 
					            # Re-sort title list without leading series/series_index
 | 
				
			||||||
 | 
					            # Incoming title <series> <series_index>: <title>
 | 
				
			||||||
            if not self.useSeriesPrefixInTitlesSection:
 | 
					            if not self.useSeriesPrefixInTitlesSection:
 | 
				
			||||||
                nspt = deepcopy(self.booksByTitle)
 | 
					                nspt = deepcopy(self.booksByTitle)
 | 
				
			||||||
                for book in nspt:
 | 
					                nspt = sorted(nspt, key=lambda x:(x['title_sort'].upper(), x['title_sort'].upper()))
 | 
				
			||||||
                    if book['series']:
 | 
					 | 
				
			||||||
                        tokens = book['title'].partition(':')
 | 
					 | 
				
			||||||
                        book['title'] = '%s (%s)' % (tokens[2].strip(), tokens[0])
 | 
					 | 
				
			||||||
                        book['title_sort'] = self.generateSortTitle(book['title'])
 | 
					 | 
				
			||||||
                nspt = sorted(nspt,
 | 
					 | 
				
			||||||
                                     key=lambda x:(x['title_sort'].upper(), x['title_sort'].upper()))
 | 
					 | 
				
			||||||
                self.booksByTitle_noSeriesPrefix = nspt
 | 
					                self.booksByTitle_noSeriesPrefix = nspt
 | 
				
			||||||
                if False and self.verbose:
 | 
					 | 
				
			||||||
                    self.opts.log.info("no_series_prefix_titles: %d books" % len(nspt))
 | 
					 | 
				
			||||||
                    self.opts.log.info(" %-40s %-40s" % ('title', 'title_sort'))
 | 
					 | 
				
			||||||
                    for title in nspt:
 | 
					 | 
				
			||||||
                        self.opts.log.info((u" %-40s %-40s" % (title['title'][0:40],
 | 
					 | 
				
			||||||
                                                               title['title_sort'][0:40])).encode('utf-8'))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # Loop through the books by title
 | 
					            # Loop through the books by title
 | 
				
			||||||
            title_list = self.booksByTitle
 | 
					            title_list = self.booksByTitle
 | 
				
			||||||
@ -1878,7 +1855,14 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
                aTag = Tag(soup, "a")
 | 
					                aTag = Tag(soup, "a")
 | 
				
			||||||
                if self.opts.generate_descriptions:
 | 
					                if self.opts.generate_descriptions:
 | 
				
			||||||
                    aTag['href'] = "book_%d.html" % (int(float(book['id'])))
 | 
					                    aTag['href'] = "book_%d.html" % (int(float(book['id'])))
 | 
				
			||||||
                aTag.insert(0,escape(book['title']))
 | 
					
 | 
				
			||||||
 | 
					                # Generate the title from the template
 | 
				
			||||||
 | 
					                args = self.generateFormatArgs(book)
 | 
				
			||||||
 | 
					                if book['series']:
 | 
				
			||||||
 | 
					                    formatted_title = self.by_titles_series_title_template.format(**args).rstrip()
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    formatted_title = self.by_titles_normal_title_template.format(**args).rstrip()
 | 
				
			||||||
 | 
					                aTag.insert(0,NavigableString(escape(formatted_title)))
 | 
				
			||||||
                pBookTag.insert(ptc, aTag)
 | 
					                pBookTag.insert(ptc, aTag)
 | 
				
			||||||
                ptc += 1
 | 
					                ptc += 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1916,7 +1900,9 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
            self.htmlFileList_1.append("content/ByAlphaTitle.html")
 | 
					            self.htmlFileList_1.append("content/ByAlphaTitle.html")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def generateHTMLByAuthor(self):
 | 
					        def generateHTMLByAuthor(self):
 | 
				
			||||||
            # Write books by author A-Z
 | 
					            '''
 | 
				
			||||||
 | 
					            Write books by author A-Z
 | 
				
			||||||
 | 
					            '''
 | 
				
			||||||
            self.updateProgressFullStep("'Authors'")
 | 
					            self.updateProgressFullStep("'Authors'")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            friendly_name = "Authors"
 | 
					            friendly_name = "Authors"
 | 
				
			||||||
@ -1953,7 +1939,8 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
            current_author = ''
 | 
					            current_author = ''
 | 
				
			||||||
            current_letter = ''
 | 
					            current_letter = ''
 | 
				
			||||||
            current_series = None
 | 
					            current_series = None
 | 
				
			||||||
            for book in self.booksByAuthor:
 | 
					            for book in sorted(self.booksByAuthor, key = self.booksByAuthorSorter_author_sort):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                book_count += 1
 | 
					                book_count += 1
 | 
				
			||||||
                if self.letter_or_symbol(book['author_sort'][0].upper()) != current_letter :
 | 
					                if self.letter_or_symbol(book['author_sort'][0].upper()) != current_letter :
 | 
				
			||||||
                    # Start a new letter with Index letter
 | 
					                    # Start a new letter with Index letter
 | 
				
			||||||
@ -2067,14 +2054,18 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
                aTag = Tag(soup, "a")
 | 
					                aTag = Tag(soup, "a")
 | 
				
			||||||
                if self.opts.generate_descriptions:
 | 
					                if self.opts.generate_descriptions:
 | 
				
			||||||
                    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 title, + year of publication
 | 
					
 | 
				
			||||||
 | 
					                # Generate the title from the template
 | 
				
			||||||
 | 
					                args = self.generateFormatArgs(book)
 | 
				
			||||||
                if current_series:
 | 
					                if current_series:
 | 
				
			||||||
                    aTag.insert(0,'%s (%s)' % (escape(book['title'][len(book['series'])+1:]),
 | 
					                    #aTag.insert(0,'%s%s' % (escape(book['title'][len(book['series'])+1:]),pubyear))
 | 
				
			||||||
                                               book['date'].split()[1]))
 | 
					                    formatted_title = self.by_authors_series_title_template.format(**args).rstrip()
 | 
				
			||||||
                else:
 | 
					                else:
 | 
				
			||||||
                    aTag.insert(0,'%s (%s)' % (escape(book['title']),
 | 
					                    #aTag.insert(0,'%s%s' % (escape(book['title']), pubyear))
 | 
				
			||||||
                                               book['date'].split()[1]))
 | 
					                    formatted_title = self.by_authors_normal_title_template.format(**args).rstrip()
 | 
				
			||||||
                    non_series_books += 1
 | 
					                    non_series_books += 1
 | 
				
			||||||
 | 
					                aTag.insert(0,NavigableString(escape(formatted_title)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                pBookTag.insert(ptc, aTag)
 | 
					                pBookTag.insert(ptc, aTag)
 | 
				
			||||||
                ptc += 1
 | 
					                ptc += 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -2111,7 +2102,6 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
            # Add the divTag to the body
 | 
					            # Add the divTag to the body
 | 
				
			||||||
            body.insert(btc, divTag)
 | 
					            body.insert(btc, divTag)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
            # Write the generated file to contentdir
 | 
					            # Write the generated file to contentdir
 | 
				
			||||||
            outfile_spec = "%s/ByAlphaAuthor.html" % (self.contentDir)
 | 
					            outfile_spec = "%s/ByAlphaAuthor.html" % (self.contentDir)
 | 
				
			||||||
            outfile = open(outfile_spec, 'w')
 | 
					            outfile = open(outfile_spec, 'w')
 | 
				
			||||||
@ -2120,13 +2110,15 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
            self.htmlFileList_1.append("content/ByAlphaAuthor.html")
 | 
					            self.htmlFileList_1.append("content/ByAlphaAuthor.html")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def generateHTMLByDateAdded(self):
 | 
					        def generateHTMLByDateAdded(self):
 | 
				
			||||||
            # Write books by reverse chronological order
 | 
					            '''
 | 
				
			||||||
 | 
					            Write books by reverse chronological order
 | 
				
			||||||
 | 
					            '''
 | 
				
			||||||
            self.updateProgressFullStep("'Recently Added'")
 | 
					            self.updateProgressFullStep("'Recently Added'")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            def add_books_to_HTML_by_month(this_months_list, dtc):
 | 
					            def add_books_to_HTML_by_month(this_months_list, dtc):
 | 
				
			||||||
                if len(this_months_list):
 | 
					                if len(this_months_list):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    this_months_list.sort(self.author_compare)
 | 
					                    this_months_list = sorted(this_months_list, key=self.booksByAuthorSorter_author_sort)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    # Create a new month anchor
 | 
					                    # Create a new month anchor
 | 
				
			||||||
                    date_string = strftime(u'%B %Y', current_date.timetuple())
 | 
					                    date_string = strftime(u'%B %Y', current_date.timetuple())
 | 
				
			||||||
@ -2156,16 +2148,6 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
                            divTag.insert(dtc,pAuthorTag)
 | 
					                            divTag.insert(dtc,pAuthorTag)
 | 
				
			||||||
                            dtc += 1
 | 
					                            dtc += 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        '''
 | 
					 | 
				
			||||||
                        # Insert an <hr /> between non-series and series
 | 
					 | 
				
			||||||
                        if not current_series and non_series_books and new_entry['series']:
 | 
					 | 
				
			||||||
                            # Insert an <hr />
 | 
					 | 
				
			||||||
                            hrTag = Tag(soup,'hr')
 | 
					 | 
				
			||||||
                            hrTag['class'] = "series_divider"
 | 
					 | 
				
			||||||
                            divTag.insert(dtc,hrTag)
 | 
					 | 
				
			||||||
                            dtc += 1
 | 
					 | 
				
			||||||
                        '''
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        # Check for series
 | 
					                        # Check for series
 | 
				
			||||||
                        if new_entry['series'] and new_entry['series'] != current_series:
 | 
					                        if new_entry['series'] and new_entry['series'] != current_series:
 | 
				
			||||||
                            # Start a new series
 | 
					                            # Start a new series
 | 
				
			||||||
@ -2213,11 +2195,15 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
                        aTag = Tag(soup, "a")
 | 
					                        aTag = Tag(soup, "a")
 | 
				
			||||||
                        if self.opts.generate_descriptions:
 | 
					                        if self.opts.generate_descriptions:
 | 
				
			||||||
                            aTag['href'] = "book_%d.html" % (int(float(new_entry['id'])))
 | 
					                            aTag['href'] = "book_%d.html" % (int(float(new_entry['id'])))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        # Generate the title from the template
 | 
				
			||||||
 | 
					                        args = self.generateFormatArgs(new_entry)
 | 
				
			||||||
                        if current_series:
 | 
					                        if current_series:
 | 
				
			||||||
                            aTag.insert(0,escape(new_entry['title'][len(new_entry['series'])+1:]))
 | 
					                            formatted_title = self.by_month_added_series_title_template.format(**args).rstrip()
 | 
				
			||||||
                        else:
 | 
					                        else:
 | 
				
			||||||
                            aTag.insert(0,escape(new_entry['title']))
 | 
					                            formatted_title = self.by_month_added_normal_title_template.format(**args).rstrip()
 | 
				
			||||||
                            non_series_books += 1
 | 
					                            non_series_books += 1
 | 
				
			||||||
 | 
					                        aTag.insert(0,NavigableString(escape(formatted_title)))
 | 
				
			||||||
                        pBookTag.insert(ptc, aTag)
 | 
					                        pBookTag.insert(ptc, aTag)
 | 
				
			||||||
                        ptc += 1
 | 
					                        ptc += 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -2265,7 +2251,14 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
                        aTag = Tag(soup, "a")
 | 
					                        aTag = Tag(soup, "a")
 | 
				
			||||||
                        if self.opts.generate_descriptions:
 | 
					                        if self.opts.generate_descriptions:
 | 
				
			||||||
                            aTag['href'] = "book_%d.html" % (int(float(new_entry['id'])))
 | 
					                            aTag['href'] = "book_%d.html" % (int(float(new_entry['id'])))
 | 
				
			||||||
                        aTag.insert(0,escape(new_entry['title']))
 | 
					
 | 
				
			||||||
 | 
					                        # Generate the title from the template
 | 
				
			||||||
 | 
					                        args = self.generateFormatArgs(new_entry)
 | 
				
			||||||
 | 
					                        if new_entry['series']:
 | 
				
			||||||
 | 
					                            formatted_title = self.by_recently_added_series_title_template.format(**args).rstrip()
 | 
				
			||||||
 | 
					                        else:
 | 
				
			||||||
 | 
					                            formatted_title = self.by_recently_added_normal_title_template.format(**args).rstrip()
 | 
				
			||||||
 | 
					                        aTag.insert(0,NavigableString(escape(formatted_title)))
 | 
				
			||||||
                        pBookTag.insert(ptc, aTag)
 | 
					                        pBookTag.insert(ptc, aTag)
 | 
				
			||||||
                        ptc += 1
 | 
					                        ptc += 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -2323,17 +2316,12 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
            divTag = Tag(soup, "div")
 | 
					            divTag = Tag(soup, "div")
 | 
				
			||||||
            dtc = 0
 | 
					            dtc = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # Add books by date range
 | 
					            # >>> Books by date range <<<
 | 
				
			||||||
            if self.useSeriesPrefixInTitlesSection:
 | 
					            if self.useSeriesPrefixInTitlesSection:
 | 
				
			||||||
                self.booksByDateRange = sorted(self.booksByTitle,
 | 
					                self.booksByDateRange = sorted(self.booksByTitle,
 | 
				
			||||||
                                 key=lambda x:(x['timestamp'], x['timestamp']),reverse=True)
 | 
					                                 key=lambda x:(x['timestamp'], x['timestamp']),reverse=True)
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                nspt = deepcopy(self.booksByTitle)
 | 
					                nspt = deepcopy(self.booksByTitle)
 | 
				
			||||||
                for book in nspt:
 | 
					 | 
				
			||||||
                    if book['series']:
 | 
					 | 
				
			||||||
                        tokens = book['title'].partition(':')
 | 
					 | 
				
			||||||
                        book['title'] = '%s (%s)' % (tokens[2].strip(), tokens[0])
 | 
					 | 
				
			||||||
                        book['title_sort'] = self.generateSortTitle(book['title'])
 | 
					 | 
				
			||||||
                self.booksByDateRange = sorted(nspt, key=lambda x:(x['timestamp'], x['timestamp']),reverse=True)
 | 
					                self.booksByDateRange = sorted(nspt, key=lambda x:(x['timestamp'], x['timestamp']),reverse=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            date_range_list = []
 | 
					            date_range_list = []
 | 
				
			||||||
@ -2356,15 +2344,6 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
                dtc = add_books_to_HTML_by_date_range(date_range_list, date_range, dtc)
 | 
					                dtc = add_books_to_HTML_by_date_range(date_range_list, date_range, dtc)
 | 
				
			||||||
                date_range_list = [book]
 | 
					                date_range_list = [book]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            '''
 | 
					 | 
				
			||||||
            if books_added_in_date_range:
 | 
					 | 
				
			||||||
                # Add an <hr> separating date ranges from months
 | 
					 | 
				
			||||||
                hrTag = Tag(soup,'hr')
 | 
					 | 
				
			||||||
                hrTag['class'] = "description_divider"
 | 
					 | 
				
			||||||
                divTag.insert(dtc,hrTag)
 | 
					 | 
				
			||||||
                dtc += 1
 | 
					 | 
				
			||||||
            '''
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            # >>>> Books by month <<<<
 | 
					            # >>>> Books by month <<<<
 | 
				
			||||||
            # Sort titles case-insensitive for by month using series prefix
 | 
					            # Sort titles case-insensitive for by month using series prefix
 | 
				
			||||||
            self.booksByMonth = sorted(self.booksByTitle,
 | 
					            self.booksByMonth = sorted(self.booksByTitle,
 | 
				
			||||||
@ -2395,7 +2374,9 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
            self.htmlFileList_2.append("content/ByDateAdded.html")
 | 
					            self.htmlFileList_2.append("content/ByDateAdded.html")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def generateHTMLByDateRead(self):
 | 
					        def generateHTMLByDateRead(self):
 | 
				
			||||||
            # Write books by active bookmarks
 | 
					            '''
 | 
				
			||||||
 | 
					            Write books by active bookmarks
 | 
				
			||||||
 | 
					            '''
 | 
				
			||||||
            friendly_name = 'Recently Read'
 | 
					            friendly_name = 'Recently Read'
 | 
				
			||||||
            self.updateProgressFullStep("'%s'" % friendly_name)
 | 
					            self.updateProgressFullStep("'%s'" % friendly_name)
 | 
				
			||||||
            if not self.bookmarked_books:
 | 
					            if not self.bookmarked_books:
 | 
				
			||||||
@ -2533,32 +2514,6 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
            self.booksByDateRead = sorted(bookmarked_books,
 | 
					            self.booksByDateRead = sorted(bookmarked_books,
 | 
				
			||||||
                             key=lambda x:(x['bookmark_timestamp'], x['bookmark_timestamp']),reverse=True)
 | 
					                             key=lambda x:(x['bookmark_timestamp'], x['bookmark_timestamp']),reverse=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            '''
 | 
					 | 
				
			||||||
            # >>>> Recently by date range <<<<
 | 
					 | 
				
			||||||
            date_range_list = []
 | 
					 | 
				
			||||||
            today_time = datetime.datetime.utcnow()
 | 
					 | 
				
			||||||
            today_time.replace(hour=23, minute=59, second=59)
 | 
					 | 
				
			||||||
            books_added_in_date_range = False
 | 
					 | 
				
			||||||
            for (i, date) in enumerate(self.DATE_RANGE):
 | 
					 | 
				
			||||||
                date_range_limit = self.DATE_RANGE[i]
 | 
					 | 
				
			||||||
                if i:
 | 
					 | 
				
			||||||
                    date_range = '%d to %d days ago' % (self.DATE_RANGE[i-1], self.DATE_RANGE[i])
 | 
					 | 
				
			||||||
                else:
 | 
					 | 
				
			||||||
                    date_range = 'Last %d days' % (self.DATE_RANGE[i])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                for book in self.booksByDateRead:
 | 
					 | 
				
			||||||
                    bookmark_time = datetime.datetime.utcfromtimestamp(book['bookmark_timestamp'])
 | 
					 | 
				
			||||||
                    delta = today_time-bookmark_time
 | 
					 | 
				
			||||||
                    if delta.days <= date_range_limit:
 | 
					 | 
				
			||||||
                        date_range_list.append(book)
 | 
					 | 
				
			||||||
                        books_added_in_date_range = True
 | 
					 | 
				
			||||||
                    else:
 | 
					 | 
				
			||||||
                        break
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                dtc = add_books_to_HTML_by_date_range(date_range_list, date_range, dtc)
 | 
					 | 
				
			||||||
                date_range_list = [book]
 | 
					 | 
				
			||||||
            '''
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            # >>>> Recently read by day <<<<
 | 
					            # >>>> Recently read by day <<<<
 | 
				
			||||||
            current_date = datetime.date.fromordinal(1)
 | 
					            current_date = datetime.date.fromordinal(1)
 | 
				
			||||||
            todays_list = []
 | 
					            todays_list = []
 | 
				
			||||||
@ -2713,10 +2668,15 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
                # Use series, series index if avail else just title
 | 
					                # Use series, series index if avail else just title
 | 
				
			||||||
                #aTag.insert(0,'%d. %s · %s' % (book['series_index'],escape(book['title']), ' & '.join(book['authors'])))
 | 
					                #aTag.insert(0,'%d. %s · %s' % (book['series_index'],escape(book['title']), ' & '.join(book['authors'])))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                # Link to book
 | 
					                # Reassert 'date' since this is the result of a new search
 | 
				
			||||||
                aTag.insert(0,'%d. %s (%s)' % (book['series_index'],
 | 
					                if re.match('0100-01-01',str(book['pubdate'].date())):
 | 
				
			||||||
                                               escape(book['title']),
 | 
					                    book['date'] = None
 | 
				
			||||||
                                               strftime(u'%Y', book['pubdate'].timetuple())))
 | 
					                else:
 | 
				
			||||||
 | 
					                    book['date'] = strftime(u'%B %Y', book['pubdate'].timetuple())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                args = self.generateFormatArgs(book)
 | 
				
			||||||
 | 
					                formatted_title = self.by_series_title_template.format(**args).rstrip()
 | 
				
			||||||
 | 
					                aTag.insert(0,NavigableString(escape(formatted_title)))
 | 
				
			||||||
                pBookTag.insert(ptc, aTag)
 | 
					                pBookTag.insert(ptc, aTag)
 | 
				
			||||||
                ptc += 1
 | 
					                ptc += 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -2760,10 +2720,11 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
            self.htmlFileList_1.append("content/BySeries.html")
 | 
					            self.htmlFileList_1.append("content/BySeries.html")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def generateHTMLByTags(self):
 | 
					        def generateHTMLByTags(self):
 | 
				
			||||||
            # Generate individual HTML files for each tag, e.g. Fiction, Nonfiction ...
 | 
					            '''
 | 
				
			||||||
            # Note that special tags - ~+*[] -  have already been filtered from books[]
 | 
					            Generate individual HTML files for each tag, e.g. Fiction, Nonfiction ...
 | 
				
			||||||
            # There may be synonomous tags
 | 
					            Note that special tags -  have already been filtered from books[]
 | 
				
			||||||
 | 
					            There may be synonomous tags
 | 
				
			||||||
 | 
					            '''
 | 
				
			||||||
            self.updateProgressFullStep("'Genres'")
 | 
					            self.updateProgressFullStep("'Genres'")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            self.genre_tags_dict = self.filterDbTags(self.db.all_tags())
 | 
					            self.genre_tags_dict = self.filterDbTags(self.db.all_tags())
 | 
				
			||||||
@ -2787,6 +2748,8 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
                        this_book['tags'] = book['tags']
 | 
					                        this_book['tags'] = book['tags']
 | 
				
			||||||
                        this_book['id'] = book['id']
 | 
					                        this_book['id'] = book['id']
 | 
				
			||||||
                        this_book['series'] = book['series']
 | 
					                        this_book['series'] = book['series']
 | 
				
			||||||
 | 
					                        this_book['series_index'] = book['series_index']
 | 
				
			||||||
 | 
					                        this_book['date'] = book['date']
 | 
				
			||||||
                        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:
 | 
				
			||||||
@ -2843,13 +2806,7 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
                            unique_authors.append((current_author[0], current_author[1], books_by_current_author))
 | 
					                            unique_authors.append((current_author[0], current_author[1], books_by_current_author))
 | 
				
			||||||
                        else:
 | 
					                        else:
 | 
				
			||||||
                            books_by_current_author += 1
 | 
					                            books_by_current_author += 1
 | 
				
			||||||
                    '''
 | 
					
 | 
				
			||||||
                    # Extract the unique entries
 | 
					 | 
				
			||||||
                    unique_authors = []
 | 
					 | 
				
			||||||
                    for author in authors:
 | 
					 | 
				
			||||||
                        if not author in unique_authors:
 | 
					 | 
				
			||||||
                            unique_authors.append(author)
 | 
					 | 
				
			||||||
                    '''
 | 
					 | 
				
			||||||
                    # Write the genre book list as an article
 | 
					                    # Write the genre book list as an article
 | 
				
			||||||
                    titles_spanned = self.generateHTMLByGenre(genre, True if index==0 else False,
 | 
					                    titles_spanned = self.generateHTMLByGenre(genre, True if index==0 else False,
 | 
				
			||||||
                                          genre_tag_set[genre],
 | 
					                                          genre_tag_set[genre],
 | 
				
			||||||
@ -2863,18 +2820,14 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
                                              'books':genre_tag_set[genre],
 | 
					                                              'books':genre_tag_set[genre],
 | 
				
			||||||
                                              'titles_spanned':titles_spanned})
 | 
					                                              'titles_spanned':titles_spanned})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if False and self.opts.verbose:
 | 
					 | 
				
			||||||
                for genre in master_genre_list:
 | 
					 | 
				
			||||||
                    print "genre['tag']: %s" % genre['tag']
 | 
					 | 
				
			||||||
                    for book in genre['books']:
 | 
					 | 
				
			||||||
                        print book['title']
 | 
					 | 
				
			||||||
            self.genres = master_genre_list
 | 
					            self.genres = master_genre_list
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def generateThumbnails(self):
 | 
					        def generateThumbnails(self):
 | 
				
			||||||
            # Generate a thumbnail per cover.  If a current thumbnail exists, skip
 | 
					            '''
 | 
				
			||||||
            # If a cover doesn't exist, use default
 | 
					            Generate a thumbnail per cover.  If a current thumbnail exists, skip
 | 
				
			||||||
            # Return list of active thumbs
 | 
					            If a cover doesn't exist, use default
 | 
				
			||||||
 | 
					            Return list of active thumbs
 | 
				
			||||||
 | 
					            '''
 | 
				
			||||||
            self.updateProgressFullStep("'Thumbnails'")
 | 
					            self.updateProgressFullStep("'Thumbnails'")
 | 
				
			||||||
            thumbs = ['thumbnail_default.jpg']
 | 
					            thumbs = ['thumbnail_default.jpg']
 | 
				
			||||||
            image_dir = "%s/images" % self.catalogPath
 | 
					            image_dir = "%s/images" % self.catalogPath
 | 
				
			||||||
@ -2886,45 +2839,51 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                thumb_file = 'thumbnail_%d.jpg' % int(title['id'])
 | 
					                thumb_file = 'thumbnail_%d.jpg' % int(title['id'])
 | 
				
			||||||
                thumb_generated = True
 | 
					                thumb_generated = True
 | 
				
			||||||
 | 
					                valid_cover = True
 | 
				
			||||||
                try:
 | 
					                try:
 | 
				
			||||||
                    self.generateThumbnail(title, image_dir, thumb_file)
 | 
					 | 
				
			||||||
                    thumbs.append("thumbnail_%d.jpg" % int(title['id']))
 | 
					                    thumbs.append("thumbnail_%d.jpg" % int(title['id']))
 | 
				
			||||||
 | 
					                    self.generateThumbnail(title, image_dir, thumb_file)
 | 
				
			||||||
                except:
 | 
					                except:
 | 
				
			||||||
 | 
					                    if 'cover' in title and os.path.exists(title['cover']):
 | 
				
			||||||
 | 
					                        valid_cover = False
 | 
				
			||||||
 | 
					                        self.opts.log.warn(" *** Invalid cover file for '%s' ***" % (title['title']))
 | 
				
			||||||
 | 
					                        if not self.error:
 | 
				
			||||||
 | 
					                            self.error.append('Invalid cover files')
 | 
				
			||||||
 | 
					                        self.error.append("Warning: invalid cover file for '%s', default cover substituted.\n" % (title['title']))
 | 
				
			||||||
                    thumb_generated = False
 | 
					                    thumb_generated = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
                if not thumb_generated:
 | 
					                if not thumb_generated:
 | 
				
			||||||
                    # Use default cover
 | 
					                    self.opts.log.warn(" using default cover for '%s'" % (title['title']))
 | 
				
			||||||
                    if False and self.verbose:
 | 
					 | 
				
			||||||
                        self.opts.log.warn(" using default cover for '%s'" % \
 | 
					 | 
				
			||||||
                        (title['title']))
 | 
					 | 
				
			||||||
                    # Check to make sure default is current
 | 
					                    # Check to make sure default is current
 | 
				
			||||||
                    # Check to see if thumbnail exists
 | 
					                    # Check to see if thumbnail exists
 | 
				
			||||||
                    thumb_fp = "%s/thumbnail_default.jpg" % (image_dir)
 | 
					                    default_thumb_fp = os.path.join(image_dir,"thumbnail_default.jpg")
 | 
				
			||||||
                    cover = "%s/DefaultCover.png" % (self.catalogPath)
 | 
					                    cover = os.path.join(self.catalogPath, "DefaultCover.png")
 | 
				
			||||||
                    if not os.path.exists(cover):
 | 
					                    if not os.path.exists(cover):
 | 
				
			||||||
                        shutil.copyfile(I('book.png'), cover)
 | 
					                        shutil.copyfile(I('book.png'), cover)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if os.path.isfile(thumb_fp):
 | 
					                    if os.path.isfile(default_thumb_fp):
 | 
				
			||||||
                        # Check to see if default cover is newer than thumbnail
 | 
					                        # Check to see if default cover is newer than thumbnail
 | 
				
			||||||
                        # os.path.getmtime() = modified time
 | 
					                        # os.path.getmtime() = modified time
 | 
				
			||||||
                        # os.path.ctime() = creation time
 | 
					                        # os.path.ctime() = creation time
 | 
				
			||||||
                        cover_timestamp = os.path.getmtime(cover)
 | 
					                        cover_timestamp = os.path.getmtime(cover)
 | 
				
			||||||
                        thumb_timestamp = os.path.getmtime(thumb_fp)
 | 
					                        thumb_timestamp = os.path.getmtime(default_thumb_fp)
 | 
				
			||||||
                        if thumb_timestamp < cover_timestamp:
 | 
					                        if thumb_timestamp < cover_timestamp:
 | 
				
			||||||
                            if False and self.verbose:
 | 
					                            if False and self.verbose:
 | 
				
			||||||
                                self.opts.log.warn("updating thumbnail_default for %s" % title['title'])
 | 
					                                self.opts.log.warn("updating thumbnail_default for %s" % title['title'])
 | 
				
			||||||
                            #title['cover'] = "%s/DefaultCover.jpg" % self.catalogPath
 | 
					                            #title['cover'] = os.path.join(self.catalogPath,"DefaultCover.jpg")
 | 
				
			||||||
                            title['cover'] = cover
 | 
					                            title['cover'] = cover
 | 
				
			||||||
                            self.generateThumbnail(title, image_dir, "thumbnail_default.jpg")
 | 
					                            self.generateThumbnail(title, image_dir,
 | 
				
			||||||
 | 
					                                                "thumbnail_default.jpg" if valid_cover else thumb_file)
 | 
				
			||||||
                    else:
 | 
					                    else:
 | 
				
			||||||
                        if False and self.verbose:
 | 
					                        if False and self.verbose:
 | 
				
			||||||
                            self.opts.log.warn(" generating new thumbnail_default.jpg")
 | 
					                            self.opts.log.warn(" generating new thumbnail_default.jpg")
 | 
				
			||||||
                        #title['cover'] = "%s/DefaultCover.jpg" % self.catalogPath
 | 
					                        #title['cover'] = os.path.join(self.catalogPath,"DefaultCover.jpg")
 | 
				
			||||||
                        title['cover'] = cover
 | 
					                        title['cover'] = cover
 | 
				
			||||||
                        self.generateThumbnail(title, image_dir, "thumbnail_default.jpg")
 | 
					                        self.generateThumbnail(title, image_dir,
 | 
				
			||||||
 | 
					                                                "thumbnail_default.jpg" if valid_cover else thumb_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # Write the thumb_width to the file validating cache contents
 | 
					
 | 
				
			||||||
 | 
					            # Write thumb_width to the file, validating cache contents
 | 
				
			||||||
            # Allows detection of aborted catalog builds
 | 
					            # Allows detection of aborted catalog builds
 | 
				
			||||||
            with ZipFile(self.__archive_path, mode='a') as zfw:
 | 
					            with ZipFile(self.__archive_path, mode='a') as zfw:
 | 
				
			||||||
                zfw.writestr('thumb_width', self.opts.thumb_width)
 | 
					                zfw.writestr('thumb_width', self.opts.thumb_width)
 | 
				
			||||||
@ -3162,15 +3121,17 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
                navLabelTag = Tag(ncx_soup, "navLabel")
 | 
					                navLabelTag = Tag(ncx_soup, "navLabel")
 | 
				
			||||||
                textTag = Tag(ncx_soup, "text")
 | 
					                textTag = Tag(ncx_soup, "text")
 | 
				
			||||||
                if book['series']:
 | 
					                if book['series']:
 | 
				
			||||||
                    tokens = list(book['title'].partition(':'))
 | 
					                    series_index = str(book['series_index'])
 | 
				
			||||||
 | 
					                    if series_index.endswith('.0'):
 | 
				
			||||||
 | 
					                        series_index = series_index[:-2]
 | 
				
			||||||
                    if self.generateForKindle:
 | 
					                    if self.generateForKindle:
 | 
				
			||||||
                        # Don't include Author for Kindle
 | 
					                        # Don't include Author for Kindle
 | 
				
			||||||
                        textTag.insert(0, NavigableString(self.formatNCXText('%s (%s)' % \
 | 
					                        textTag.insert(0, NavigableString(self.formatNCXText('%s (%s [%s])' %
 | 
				
			||||||
                                                      (tokens[2].strip(), tokens[0]), dest='title')))
 | 
					                                       (book['title'], book['series'], series_index), dest='title')))
 | 
				
			||||||
                    else:
 | 
					                    else:
 | 
				
			||||||
                        # Include Author for non-Kindle
 | 
					                        # Include Author for non-Kindle
 | 
				
			||||||
                        textTag.insert(0, NavigableString(self.formatNCXText('%s · %s (%s)' % \
 | 
					                        textTag.insert(0, NavigableString(self.formatNCXText('%s (%s [%s]) · %s ' %
 | 
				
			||||||
                                                      (tokens[2].strip(), book['author'], tokens[0]), dest='title')))
 | 
					                                       (book['title'], book['series'], series_index, book['author']), dest='title')))
 | 
				
			||||||
                else:
 | 
					                else:
 | 
				
			||||||
                    if self.generateForKindle:
 | 
					                    if self.generateForKindle:
 | 
				
			||||||
                        # Don't include Author for Kindle
 | 
					                        # Don't include Author for Kindle
 | 
				
			||||||
@ -3725,43 +3686,6 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
                    add_to_master_date_range_list(current_titles_list)
 | 
					                    add_to_master_date_range_list(current_titles_list)
 | 
				
			||||||
                current_titles_list = [book['title']]
 | 
					                current_titles_list = [book['title']]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            '''
 | 
					 | 
				
			||||||
            # Add *article* entries for each populated date range
 | 
					 | 
				
			||||||
            # master_date_range_list{}: [0]:titles list [1]:datestr
 | 
					 | 
				
			||||||
            for books_by_date_range in master_date_range_list:
 | 
					 | 
				
			||||||
                navPointByDateRangeTag = Tag(soup, 'navPoint')
 | 
					 | 
				
			||||||
                navPointByDateRangeTag['class'] = "article"
 | 
					 | 
				
			||||||
                navPointByDateRangeTag['id'] = "%s-ID" %  books_by_date_range[1].replace(' ','')
 | 
					 | 
				
			||||||
                navPointTag['playOrder'] = self.playOrder
 | 
					 | 
				
			||||||
                self.playOrder += 1
 | 
					 | 
				
			||||||
                navLabelTag = Tag(soup, 'navLabel')
 | 
					 | 
				
			||||||
                textTag = Tag(soup, 'text')
 | 
					 | 
				
			||||||
                textTag.insert(0, NavigableString(books_by_date_range[1]))
 | 
					 | 
				
			||||||
                navLabelTag.insert(0, textTag)
 | 
					 | 
				
			||||||
                navPointByDateRangeTag.insert(0,navLabelTag)
 | 
					 | 
				
			||||||
                contentTag = Tag(soup, 'content')
 | 
					 | 
				
			||||||
                contentTag['src'] = "%s#bdr_%s" % (HTML_file,
 | 
					 | 
				
			||||||
                    books_by_date_range[1].replace(' ',''))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                navPointByDateRangeTag.insert(1,contentTag)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if self.generateForKindle:
 | 
					 | 
				
			||||||
                    cmTag = Tag(soup, '%s' % 'calibre:meta')
 | 
					 | 
				
			||||||
                    cmTag['name'] = "description"
 | 
					 | 
				
			||||||
                    cmTag.insert(0, NavigableString(books_by_date_range[0]))
 | 
					 | 
				
			||||||
                    navPointByDateRangeTag.insert(2, cmTag)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    cmTag = Tag(soup, '%s' % 'calibre:meta')
 | 
					 | 
				
			||||||
                    cmTag['name'] = "author"
 | 
					 | 
				
			||||||
                    navStr = '%d titles' % books_by_date_range[2] if books_by_date_range[2] > 1 else \
 | 
					 | 
				
			||||||
                             '%d title' % books_by_date_range[2]
 | 
					 | 
				
			||||||
                    cmTag.insert(0, NavigableString(navStr))
 | 
					 | 
				
			||||||
                    navPointByDateRangeTag.insert(3, cmTag)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                navPointTag.insert(nptc, navPointByDateRangeTag)
 | 
					 | 
				
			||||||
                nptc += 1
 | 
					 | 
				
			||||||
            '''
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            # Create an NCX article entry for each populated day
 | 
					            # Create an NCX article entry for each populated day
 | 
				
			||||||
            # Loop over the booksByDate list, find start of each month,
 | 
					            # Loop over the booksByDate list, find start of each month,
 | 
				
			||||||
            # add description_preview_count titles
 | 
					            # add description_preview_count titles
 | 
				
			||||||
@ -3944,7 +3868,8 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
            outfile = open("%s/%s.ncx" % (self.catalogPath, self.basename), 'w')
 | 
					            outfile = open("%s/%s.ncx" % (self.catalogPath, self.basename), 'w')
 | 
				
			||||||
            outfile.write(self.ncxSoup.prettify())
 | 
					            outfile.write(self.ncxSoup.prettify())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Helpers
 | 
					
 | 
				
			||||||
 | 
					        # --------------- Helpers ---------------
 | 
				
			||||||
        def author_to_author_sort(self, author):
 | 
					        def author_to_author_sort(self, author):
 | 
				
			||||||
            tokens = author.split()
 | 
					            tokens = author.split()
 | 
				
			||||||
            tokens = tokens[-1:] + tokens[:-1]
 | 
					            tokens = tokens[-1:] + tokens[:-1]
 | 
				
			||||||
@ -3952,45 +3877,39 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
                tokens[0] += ','
 | 
					                tokens[0] += ','
 | 
				
			||||||
            return ' '.join(tokens).capitalize()
 | 
					            return ' '.join(tokens).capitalize()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def author_compare(self,x,y):
 | 
					        def booksByAuthorSorter_author_sort(self, book):
 | 
				
			||||||
            # Return -1 if x<y
 | 
					            '''
 | 
				
			||||||
            # Return  0 if x==y
 | 
					            Sort non-series books before series books
 | 
				
			||||||
            # Return  1 if x>y
 | 
					            '''
 | 
				
			||||||
 | 
					            if not book['series']:
 | 
				
			||||||
 | 
					                key = '%s %s' % (book['author_sort'],
 | 
				
			||||||
 | 
					                                 book['title_sort'].capitalize())
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                index = book['series_index']
 | 
				
			||||||
 | 
					                integer = int(index)
 | 
				
			||||||
 | 
					                fraction = index-integer
 | 
				
			||||||
 | 
					                series_index = '%04d%s' % (integer, str('%0.4f' % fraction).lstrip('0'))
 | 
				
			||||||
 | 
					                key = '%s ~%s %s' % (book['author_sort'],
 | 
				
			||||||
 | 
					                                     self.generateSortTitle(book['series']),
 | 
				
			||||||
 | 
					                                     series_index)
 | 
				
			||||||
 | 
					            return key
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # Different authors - sort by author_sort
 | 
					        def booksByAuthorSorter_author(self, book):
 | 
				
			||||||
            if x['author_sort'].capitalize() > y['author_sort'].capitalize():
 | 
					            '''
 | 
				
			||||||
                return 1
 | 
					            Sort non-series books before series books
 | 
				
			||||||
            elif x['author_sort'].capitalize() < y['author_sort'].capitalize():
 | 
					            '''
 | 
				
			||||||
                return -1
 | 
					            if not book['series']:
 | 
				
			||||||
 | 
					                key = '%s %s' % (self.author_to_author_sort(book['author']),
 | 
				
			||||||
 | 
					                                 book['title_sort'].capitalize())
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                # Same author
 | 
					                index = book['series_index']
 | 
				
			||||||
                if x['series'] != y['series']:
 | 
					                integer = int(index)
 | 
				
			||||||
                    # One title is a series, the other is not
 | 
					                fraction = index-integer
 | 
				
			||||||
                    if not x['series']:
 | 
					                series_index = '%04d%s' % (integer, str('%0.4f' % fraction).lstrip('0'))
 | 
				
			||||||
                        # Sort regular titles < series titles
 | 
					                key = '%s ~%s %s' % (self.author_to_author_sort(book['author']),
 | 
				
			||||||
                        return -1
 | 
					                                     self.generateSortTitle(book['series']),
 | 
				
			||||||
                    elif not y['series']:
 | 
					                                     series_index)
 | 
				
			||||||
                        return 1
 | 
					            return key
 | 
				
			||||||
 | 
					 | 
				
			||||||
                    # Different series
 | 
					 | 
				
			||||||
                    if x['title_sort'].lstrip() > y['title_sort'].lstrip():
 | 
					 | 
				
			||||||
                        return 1
 | 
					 | 
				
			||||||
                    else:
 | 
					 | 
				
			||||||
                        return -1
 | 
					 | 
				
			||||||
                else:
 | 
					 | 
				
			||||||
                    # Same series
 | 
					 | 
				
			||||||
                    if x['series'] == y['series']:
 | 
					 | 
				
			||||||
                        if float(x['series_index']) > float(y['series_index']):
 | 
					 | 
				
			||||||
                            return 1
 | 
					 | 
				
			||||||
                        elif float(x['series_index']) < float(y['series_index']):
 | 
					 | 
				
			||||||
                            return -1
 | 
					 | 
				
			||||||
                        else:
 | 
					 | 
				
			||||||
                            return 0
 | 
					 | 
				
			||||||
                    else:
 | 
					 | 
				
			||||||
                        if x['series'] > y['series']:
 | 
					 | 
				
			||||||
                            return 1
 | 
					 | 
				
			||||||
                        else:
 | 
					 | 
				
			||||||
                            return -1
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def calculateThumbnailSize(self):
 | 
					        def calculateThumbnailSize(self):
 | 
				
			||||||
            ''' Calculate thumbnail dimensions based on device DPI.  Scale Kindle by 50% '''
 | 
					            ''' Calculate thumbnail dimensions based on device DPI.  Scale Kindle by 50% '''
 | 
				
			||||||
@ -4155,6 +4074,20 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
            # Strip white space to ''
 | 
					            # Strip white space to ''
 | 
				
			||||||
            return re.sub("\W","", author)
 | 
					            return re.sub("\W","", author)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        def generateFormatArgs(self, book):
 | 
				
			||||||
 | 
					            series_index = str(book['series_index'])
 | 
				
			||||||
 | 
					            if series_index.endswith('.0'):
 | 
				
			||||||
 | 
					                series_index = series_index[:-2]
 | 
				
			||||||
 | 
					            args = dict(
 | 
				
			||||||
 | 
					                    title = book['title'],
 | 
				
			||||||
 | 
					                    series = book['series'],
 | 
				
			||||||
 | 
					                    series_index = series_index,
 | 
				
			||||||
 | 
					                    rating = self.generateRatingString(book),
 | 
				
			||||||
 | 
					                    rating_parens = '(%s)' % self.generateRatingString(book) if 'rating' in book else '',
 | 
				
			||||||
 | 
					                    pubyear = book['date'].split()[1] if book['date'] else '',
 | 
				
			||||||
 | 
					                    pubyear_parens = "(%s)" % book['date'].split()[1] if book['date'] else '')
 | 
				
			||||||
 | 
					            return args
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def generateHTMLByGenre(self, genre, section_head, books, outfile):
 | 
					        def generateHTMLByGenre(self, genre, section_head, books, outfile):
 | 
				
			||||||
            # Write an HTML file of this genre's book list
 | 
					            # Write an HTML file of this genre's book list
 | 
				
			||||||
            # Return a list with [(first_author, first_book), (last_author, last_book)]
 | 
					            # Return a list with [(first_author, first_book), (last_author, last_book)]
 | 
				
			||||||
@ -4201,16 +4134,6 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
                    divTag.insert(dtc,pAuthorTag)
 | 
					                    divTag.insert(dtc,pAuthorTag)
 | 
				
			||||||
                    dtc += 1
 | 
					                    dtc += 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                '''
 | 
					 | 
				
			||||||
                # Insert an <hr /> between non-series and series
 | 
					 | 
				
			||||||
                if not current_series and non_series_books and book['series']:
 | 
					 | 
				
			||||||
                    # Insert an <hr />
 | 
					 | 
				
			||||||
                    hrTag = Tag(soup,'hr')
 | 
					 | 
				
			||||||
                    hrTag['class'] = "series_divider"
 | 
					 | 
				
			||||||
                    divTag.insert(dtc,hrTag)
 | 
					 | 
				
			||||||
                    dtc += 1
 | 
					 | 
				
			||||||
                '''
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                # Check for series
 | 
					                # Check for series
 | 
				
			||||||
                if book['series'] and book['series'] != current_series:
 | 
					                if book['series'] and book['series'] != current_series:
 | 
				
			||||||
                    # Start a new series
 | 
					                    # Start a new series
 | 
				
			||||||
@ -4235,17 +4158,6 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
                pBookTag = Tag(soup, "p")
 | 
					                pBookTag = Tag(soup, "p")
 | 
				
			||||||
                ptc = 0
 | 
					                ptc = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                '''
 | 
					 | 
				
			||||||
                # This if clause does not display MISSING_SYMBOL for wishlist items
 | 
					 | 
				
			||||||
                # If this is the wishlist_tag genre, don't show missing symbols
 | 
					 | 
				
			||||||
                # normalized_wishlist_tag = self.genre_tags_dict[self.opts.wishlist_tag]
 | 
					 | 
				
			||||||
                if self.opts.wishlist_tag in book['tags'] and \
 | 
					 | 
				
			||||||
                   self.genre_tags_dict[self.opts.wishlist_tag] != genre:
 | 
					 | 
				
			||||||
                    pBookTag['class'] = "wishlist_item"
 | 
					 | 
				
			||||||
                    pBookTag.insert(ptc,NavigableString(self.MISSING_SYMBOL))
 | 
					 | 
				
			||||||
                    ptc += 1
 | 
					 | 
				
			||||||
                '''
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                #  book with read|reading|unread symbol or wishlist item
 | 
					                #  book with read|reading|unread symbol or wishlist item
 | 
				
			||||||
                if self.opts.wishlist_tag in book.get('tags', []):
 | 
					                if self.opts.wishlist_tag in book.get('tags', []):
 | 
				
			||||||
                        pBookTag['class'] = "wishlist_item"
 | 
					                        pBookTag['class'] = "wishlist_item"
 | 
				
			||||||
@ -4271,12 +4183,18 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
                aTag = Tag(soup, "a")
 | 
					                aTag = Tag(soup, "a")
 | 
				
			||||||
                if self.opts.generate_descriptions:
 | 
					                if self.opts.generate_descriptions:
 | 
				
			||||||
                    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
 | 
					
 | 
				
			||||||
 | 
					                # Generate the title from the template
 | 
				
			||||||
 | 
					                args = self.generateFormatArgs(book)
 | 
				
			||||||
                if current_series:
 | 
					                if current_series:
 | 
				
			||||||
                    aTag.insert(0,escape(book['title'][len(book['series'])+1:]))
 | 
					                    #aTag.insert(0,escape(book['title'][len(book['series'])+1:]))
 | 
				
			||||||
 | 
					                    formatted_title = self.by_genres_series_title_template.format(**args).rstrip()
 | 
				
			||||||
                else:
 | 
					                else:
 | 
				
			||||||
                    aTag.insert(0,escape(book['title']))
 | 
					                    #aTag.insert(0,escape(book['title']))
 | 
				
			||||||
 | 
					                    formatted_title = self.by_genres_normal_title_template.format(**args).rstrip()
 | 
				
			||||||
                    non_series_books += 1
 | 
					                    non_series_books += 1
 | 
				
			||||||
 | 
					                aTag.insert(0,NavigableString(escape(formatted_title)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                pBookTag.insert(ptc, aTag)
 | 
					                pBookTag.insert(ptc, aTag)
 | 
				
			||||||
                ptc += 1
 | 
					                ptc += 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -4322,36 +4240,21 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
                            xmlns=XHTML_NS,
 | 
					                            xmlns=XHTML_NS,
 | 
				
			||||||
                            )
 | 
					                            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                generated_html = P('catalog/template.xhtml',
 | 
					                generated_html = P(os.path.join('catalog','template.xhtml'),
 | 
				
			||||||
                        data=True).decode('utf-8').format(**args)
 | 
					                        data=True).decode('utf-8').format(**args)
 | 
				
			||||||
                generated_html = substitute_entites(generated_html)
 | 
					                generated_html = substitute_entites(generated_html)
 | 
				
			||||||
                return BeautifulSoup(generated_html)
 | 
					                return BeautifulSoup(generated_html)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if False:
 | 
					 | 
				
			||||||
                print "title metadata:\n%s" % ', '.join(sorted(book.keys()))
 | 
					 | 
				
			||||||
            if False:
 | 
					 | 
				
			||||||
                for item in sorted(book.keys()):
 | 
					 | 
				
			||||||
                    try:
 | 
					 | 
				
			||||||
                        print "%s: %s%s" % (item, book[item][:50], '...' if len(book[item])>50 else '')
 | 
					 | 
				
			||||||
                    except:
 | 
					 | 
				
			||||||
                        print "%s: %s" % (item, book[item])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            # Generate the template arguments
 | 
					            # Generate the template arguments
 | 
				
			||||||
            css = P('catalog/stylesheet.css', data=True).decode('utf-8')
 | 
					            css = P(os.path.join('catalog','stylesheet.css'), data=True).decode('utf-8')
 | 
				
			||||||
            title_str = escape(book['title'])
 | 
					            title_str = title = escape(book['title'])
 | 
				
			||||||
 | 
					            series = ''
 | 
				
			||||||
            # Title/series
 | 
					            series_index = ''
 | 
				
			||||||
            if book['series']:
 | 
					            if book['series']:
 | 
				
			||||||
                series_id, _, title = book['title'].partition(':')
 | 
					 | 
				
			||||||
                title = escape(title.strip())
 | 
					 | 
				
			||||||
                series = escape(book['series'])
 | 
					                series = escape(book['series'])
 | 
				
			||||||
                series_index = str(book['series_index'])
 | 
					                series_index = str(book['series_index'])
 | 
				
			||||||
                if series_index.endswith('.0'):
 | 
					                if series_index.endswith('.0'):
 | 
				
			||||||
                    series_index = series_index[:-2]
 | 
					                    series_index = series_index[:-2]
 | 
				
			||||||
            else:
 | 
					 | 
				
			||||||
                title = escape(book['title'])
 | 
					 | 
				
			||||||
                series = ''
 | 
					 | 
				
			||||||
                series_index = ''
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # Author, author_prefix (read|reading|none symbol or missing symbol)
 | 
					            # Author, author_prefix (read|reading|none symbol or missing symbol)
 | 
				
			||||||
            author = book['author']
 | 
					            author = book['author']
 | 
				
			||||||
@ -4392,7 +4295,10 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            # Date of publication
 | 
					            # Date of publication
 | 
				
			||||||
            pubdate = book['date']
 | 
					            pubdate = book['date']
 | 
				
			||||||
 | 
					            if pubdate:
 | 
				
			||||||
                pubmonth, pubyear = pubdate.split(' ')
 | 
					                pubmonth, pubyear = pubdate.split(' ')
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                pubmonth = pubyear = ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # Thumb
 | 
					            # Thumb
 | 
				
			||||||
            _soup = BeautifulSoup('<html>',selfClosingTags=['img'])
 | 
					            _soup = BeautifulSoup('<html>',selfClosingTags=['img'])
 | 
				
			||||||
@ -4525,7 +4431,7 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
        def generateMastheadImage(self, out_path):
 | 
					        def generateMastheadImage(self, out_path):
 | 
				
			||||||
            from calibre.ebooks.conversion.config import load_defaults
 | 
					            from calibre.ebooks.conversion.config import load_defaults
 | 
				
			||||||
            from calibre.utils.fonts import fontconfig
 | 
					            from calibre.utils.fonts import fontconfig
 | 
				
			||||||
            font_path = default_font = P('fonts/liberation/LiberationSerif-Bold.ttf')
 | 
					            font_path = default_font = P(os.path.join('fonts','liberation','LiberationSerif-Bold.ttf'))
 | 
				
			||||||
            recs = load_defaults('mobi_output')
 | 
					            recs = load_defaults('mobi_output')
 | 
				
			||||||
            masthead_font_family = recs.get('masthead_font', 'Default')
 | 
					            masthead_font_family = recs.get('masthead_font', 'Default')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -4562,16 +4468,15 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
            draw.text((left, top), text, fill=(0,0,0), font=font)
 | 
					            draw.text((left, top), text, fill=(0,0,0), font=font)
 | 
				
			||||||
            img.save(open(out_path, 'wb'), 'GIF')
 | 
					            img.save(open(out_path, 'wb'), 'GIF')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def generateSeriesTitle(self, title):
 | 
					        def generateRatingString(self, book):
 | 
				
			||||||
            if float(title['series_index']) - int(title['series_index']):
 | 
					            rating = ''
 | 
				
			||||||
                series_title = '%s %4.2f: %s' % (title['series'],
 | 
					            if 'rating' in book:
 | 
				
			||||||
                                                title['series_index'],
 | 
					                stars = int(book['rating']) / 2
 | 
				
			||||||
                                                title['title'])
 | 
					                if stars:
 | 
				
			||||||
            else:
 | 
					                    star_string = self.FULL_RATING_SYMBOL * stars
 | 
				
			||||||
                series_title = '%s %d: %s' % (title['series'],
 | 
					                    empty_stars = self.EMPTY_RATING_SYMBOL * (5 - stars)
 | 
				
			||||||
                                             title['series_index'],
 | 
					                    rating = '%s%s' % (star_string,empty_stars)
 | 
				
			||||||
                                             title['title'])
 | 
					            return rating
 | 
				
			||||||
            return series_title
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def generateShortDescription(self, description, dest=None):
 | 
					        def generateShortDescription(self, description, dest=None):
 | 
				
			||||||
            # Truncate the description, on word boundaries if necessary
 | 
					            # Truncate the description, on word boundaries if necessary
 | 
				
			||||||
@ -4610,9 +4515,11 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
                raise RuntimeError
 | 
					                raise RuntimeError
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def generateSortTitle(self, title):
 | 
					        def generateSortTitle(self, title):
 | 
				
			||||||
            # Generate a string suitable for sorting from the title
 | 
					            '''
 | 
				
			||||||
            # Ignore leading stop words
 | 
					            Generate a string suitable for sorting from the title
 | 
				
			||||||
            # Optionally convert leading numbers to strings
 | 
					            Ignore leading stop words
 | 
				
			||||||
 | 
					            Optionally convert leading numbers to strings
 | 
				
			||||||
 | 
					            '''
 | 
				
			||||||
            from calibre.ebooks.metadata import title_sort
 | 
					            from calibre.ebooks.metadata import title_sort
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # Strip stop words
 | 
					            # Strip stop words
 | 
				
			||||||
@ -4912,10 +4819,10 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        class NotImplementedError:
 | 
					        class NotImplementedError:
 | 
				
			||||||
            def __init__(self, error):
 | 
					            def __init__(self, error):
 | 
				
			||||||
                self.error = error
 | 
					                self.error.append(error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            def logerror(self):
 | 
					            def logerror(self):
 | 
				
			||||||
                self.opts.log.info('%s not implemented' % self.error)
 | 
					                self.opts.log.info('%s not implemented' % error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def run(self, path_to_output, opts, db, notification=DummyReporter()):
 | 
					    def run(self, path_to_output, opts, db, notification=DummyReporter()):
 | 
				
			||||||
        opts.log = log
 | 
					        opts.log = log
 | 
				
			||||||
@ -4982,11 +4889,12 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
        if opts_dict['ids']:
 | 
					        if opts_dict['ids']:
 | 
				
			||||||
            build_log.append(" book count: %d" % len(opts_dict['ids']))
 | 
					            build_log.append(" book count: %d" % len(opts_dict['ids']))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        sections_list = ['Authors']
 | 
					 | 
				
			||||||
        '''
 | 
					        '''
 | 
				
			||||||
 | 
					        sections_list = []
 | 
				
			||||||
        if opts.generate_authors:
 | 
					        if opts.generate_authors:
 | 
				
			||||||
            sections_list.append('Authors')
 | 
					            sections_list.append('Authors')
 | 
				
			||||||
        '''
 | 
					        '''
 | 
				
			||||||
 | 
					        sections_list = ['Authors']
 | 
				
			||||||
        if opts.generate_titles:
 | 
					        if opts.generate_titles:
 | 
				
			||||||
            sections_list.append('Titles')
 | 
					            sections_list.append('Titles')
 | 
				
			||||||
        if opts.generate_genres:
 | 
					        if opts.generate_genres:
 | 
				
			||||||
@ -5042,7 +4950,7 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
            if catalog_source_built:
 | 
					            if catalog_source_built:
 | 
				
			||||||
                log.info(" Completed catalog source generation\n")
 | 
					                log.info(" Completed catalog source generation\n")
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                log.warn(" No database hits with supplied criteria")
 | 
					                log.warn(" *** Errors during catalog generation, check log for details ***")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if catalog_source_built:
 | 
					        if catalog_source_built:
 | 
				
			||||||
            recommendations = []
 | 
					            recommendations = []
 | 
				
			||||||
@ -5072,8 +4980,6 @@ then rebuild the catalog.\n''').format(author[0])
 | 
				
			|||||||
                            abort_after_input_dump=False)
 | 
					                            abort_after_input_dump=False)
 | 
				
			||||||
            plumber.merge_ui_recommendations(recommendations)
 | 
					            plumber.merge_ui_recommendations(recommendations)
 | 
				
			||||||
            plumber.run()
 | 
					            plumber.run()
 | 
				
			||||||
            # returns to gui2.actions.catalog:catalog_generated()
 | 
					
 | 
				
			||||||
            return None
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
        # returns to gui2.actions.catalog:catalog_generated()
 | 
					        # returns to gui2.actions.catalog:catalog_generated()
 | 
				
			||||||
        return catalog.error
 | 
					        return catalog.error
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user