diff --git a/resources/catalog/stylesheet.css b/resources/catalog/stylesheet.css index 7bfbbd22cc..b5770599e6 100644 --- a/resources/catalog/stylesheet.css +++ b/resources/catalog/stylesheet.css @@ -33,7 +33,7 @@ p.description { p.date_index { font-size:x-large; - text-align:right; + text-align:center; font-weight:bold; margin-top:1em; margin-bottom:0px; @@ -41,8 +41,9 @@ p.date_index { p.letter_index { font-size:x-large; - text-align:left; - margin-top:0px; + text-align:center; + font-weight:bold; + margin-top:1em; margin-bottom:0px; } diff --git a/resources/images/news/information_dk.png b/resources/images/news/information_dk.png new file mode 100644 index 0000000000..301e2992c7 Binary files /dev/null and b/resources/images/news/information_dk.png differ diff --git a/resources/images/news/jp_dk.png b/resources/images/news/jp_dk.png new file mode 100644 index 0000000000..c9553659aa Binary files /dev/null and b/resources/images/news/jp_dk.png differ diff --git a/resources/images/news/politiken_dk.png b/resources/images/news/politiken_dk.png new file mode 100644 index 0000000000..66f324a8c7 Binary files /dev/null and b/resources/images/news/politiken_dk.png differ diff --git a/resources/recipes/information_dk.recipe b/resources/recipes/information_dk.recipe new file mode 100644 index 0000000000..1db5a7c47e --- /dev/null +++ b/resources/recipes/information_dk.recipe @@ -0,0 +1,50 @@ + +__license__ = 'GPL v3' +__copyright__ = '2010, Darko Miletic ' +''' +information.dk +''' + +from calibre.web.feeds.news import BasicNewsRecipe + +class Information_dk(BasicNewsRecipe): + title = 'Information - Denmark' + __author__ = 'Darko Miletic' + description = 'News from Denmark' + publisher = 'information.dk' + category = 'news, politics, Denmark' + oldest_article = 2 + max_articles_per_feed = 100 + no_stylesheets = True + remove_empty_feeds = True + use_embedded_content = False + encoding = 'utf8' + language = 'da' + + conversion_options = { + 'comment' : description + , 'tags' : category + , 'publisher': publisher + , 'language' : language + } + + feeds = [ + (u'Nyheder fra' , u'http://www.information.dk/feed') + ,(u'Bedst lige nu' , u'http://www.information.dk/bedstligenu/feed') + ,(u'Politik og internationalt' , u'http://www.information.dk/politik/feed') + ,(u'Kunst og kultur' , u'http://www.information.dk/kultur/feed') + ,(u'Moderne Tider' , u'http://www.information.dk/modernetider/feed') + ,(u'Klima' , u'http://www.information.dk/klima/feed') + ,(u'Opinion' , u'http://www.information.dk/opinion/feed') + ,(u'Literatur' , u'http://www.information.dk/litteratur/feed') + ,(u'Film' , u'http://www.information.dk/film/feed') + ,(u'Kunst' , u'http://www.information.dk/kunst/feed') + ] + + remove_tags_before = dict(name='h1',attrs={'class':'print-title'}) + remove_tags_after = dict(name='div',attrs={'class':'print-footer'}) + remove_tags = [dict(name=['object','link'])] + + def print_version(self, url): + return url.replace('information.dk/','information.dk/print/') + diff --git a/resources/recipes/jp_dk.recipe b/resources/recipes/jp_dk.recipe new file mode 100644 index 0000000000..cdf10f29da --- /dev/null +++ b/resources/recipes/jp_dk.recipe @@ -0,0 +1,50 @@ + +__license__ = 'GPL v3' +__copyright__ = '2010, Darko Miletic ' +''' +jp.dk +''' + +from calibre.web.feeds.news import BasicNewsRecipe + +class JP_dk(BasicNewsRecipe): + title = 'Jyllands-Posten' + __author__ = 'Darko Miletic' + description = 'News from Denmark' + publisher = 'jp.dk' + category = 'news, politics, Denmark' + oldest_article = 2 + max_articles_per_feed = 100 + no_stylesheets = True + use_embedded_content = False + encoding = 'cp1252' + language = 'da' + + extra_css = ' body{font-family: Arial,Verdana,Helvetica,Geneva,sans-serif } h1{font-family: Times,Georgia,Verdana,serif } ' + + conversion_options = { + 'comment' : description + , 'tags' : category + , 'publisher': publisher + , 'language' : language + } + + feeds = [ + (u'Tophistorier', u'http://www.jp.dk/rss/topnyheder.jsp') + ,(u'Seneste nyt' , u'http://jp.dk/index.jsp?service=rssfeed&submode=seneste') + ,(u'Indland' , u'http://www.jp.dk/rss/indland.jsp') + ,(u'Udland' , u'http://www.jp.dk/rss/udland.jsp') + ,(u'Ny viden' , u'http://www.jp.dk/rss/nyviden.jsp') + ,(u'Timeout' , u'http://www.jp.dk/rss/timeout.jsp') + ,(u'Kultur' , u'http://www.jp.dk/rss/kultur.jsp') + ,(u'Sport' , u'http://www.jp.dk/rss/sport.jsp') + ] + + remove_tags = [ + dict(name=['object','link']) + ,dict(name='p',attrs={'class':'artByline'}) + ] + + def print_version(self, url): + return url + '?service=printversion' + diff --git a/resources/recipes/metro_montreal.recipe b/resources/recipes/metro_montreal.recipe index 9c308a91d8..094f00316f 100644 --- a/resources/recipes/metro_montreal.recipe +++ b/resources/recipes/metro_montreal.recipe @@ -4,7 +4,7 @@ class Metro_Montreal(BasicNewsRecipe): title = u'M\xe9tro Montr\xe9al' __author__ = 'Jerry Clapperton' - description = 'Le quotidien le plus branché sur le monde' + description = u'Le quotidien le plus branch\xe9 sur le monde' language = 'fr' oldest_article = 7 diff --git a/resources/recipes/nin.recipe b/resources/recipes/nin.recipe index 535652b6a0..0872467d2f 100644 --- a/resources/recipes/nin.recipe +++ b/resources/recipes/nin.recipe @@ -1,46 +1,42 @@ -#!/usr/bin/env python __license__ = 'GPL v3' -__copyright__ = '2008-2009, Darko Miletic ' +__copyright__ = '2008-2010, Darko Miletic ' ''' -nin.co.rs +www.nin.co.rs ''' import re, urllib from calibre import strftime from calibre.web.feeds.news import BasicNewsRecipe -from calibre.ebooks.BeautifulSoup import Tag class Nin(BasicNewsRecipe): title = 'NIN online' __author__ = 'Darko Miletic' - description = 'Nedeljne informativne novine' - publisher = 'NIN D.O.O.' + description = 'Nedeljne Informativne Novine' + publisher = 'NIN d.o.o.' category = 'news, politics, Serbia' no_stylesheets = True oldest_article = 15 - simultaneous_downloads = 1 - delay = 1 encoding = 'utf-8' needs_subscription = True + remove_empty_feeds = True PREFIX = 'http://www.nin.co.rs' INDEX = PREFIX + '/?change_lang=ls' LOGIN = PREFIX + '/?logout=true' use_embedded_content = False language = 'sr' - lang = 'sr-Latn-RS' - direction = 'ltr' - extra_css = '@font-face {font-family: "serif1";src:url(res:///opt/sony/ebook/FONT/tt0011m_.ttf)} @font-face {font-family: "sans1";src:url(res:///opt/sony/ebook/FONT/tt0003m_.ttf)} body{font-family: serif1, serif} .article_description{font-family: sans1, sans-serif} .artTitle{font-size: x-large; font-weight: bold} .columnhead{font-size: small; font-weight: bold}' + extra_css = ' @font-face {font-family: "sans1";src:url(res:///opt/sony/ebook/FONT/tt0003m_.ttf)} body{font-family: Verdana, Lucida, sans1, sans-serif} .article_description{font-family: Verdana, Lucida, sans1, sans-serif} .artTitle{font-size: x-large; font-weight: bold; color: #900} .izjava{font-size: x-large; font-weight: bold} .columnhead{font-size: small; font-weight: bold;} img{margin-top:0.5em; margin-bottom: 0.7em} b{margin-top: 1em} ' conversion_options = { 'comment' : description , 'tags' : category , 'publisher' : publisher , 'language' : language - , 'pretty_print' : True + , 'linearize_tables' : True } preprocess_regexps = [(re.compile(u'\u0110'), lambda match: u'\u00D0')] + remove_attributes = ['height','width'] def get_browser(self): br = BasicNewsRecipe.get_browser() @@ -65,35 +61,20 @@ class Nin(BasicNewsRecipe): cover_url = self.PREFIX + link_item['src'] return cover_url - def preprocess_html(self, soup): - soup.html['lang'] = self.lang - soup.html['dir' ] = self.direction - mlang = Tag(soup,'meta',[("http-equiv","Content-Language"),("content",self.lang)]) - mcharset = Tag(soup,'meta',[("http-equiv","Content-Type"),("content","text/html; charset=utf-8")]) - soup.head.insert(0,mlang) - soup.head.insert(1,mcharset) - attribs = [ 'style','font','valign' - ,'colspan','width','height' - ,'rowspan','summary','align' - ,'cellspacing','cellpadding' - ,'frames','rules','border' - ] - for item in soup.body.findAll(name=['table','td','tr','th','caption','thead','tfoot','tbody','colgroup','col']): - item.name = 'div' - for attrib in attribs: - if item.has_key(attrib): - del item[attrib] - return soup - def parse_index(self): articles = [] + count = 0 soup = self.index_to_soup(self.PREFIX) for item in soup.findAll('a',attrs={'class':'lmeninavFont'}): + count = count +1 + if self.test and count > 2: + return articles section = self.tag_to_string(item) feedlink = self.PREFIX + item['href'] feedpage = self.index_to_soup(feedlink) self.report_progress(0, _('Fetching feed')+' %s...'%(section)) inarts = [] + count2 = 0 for art in feedpage.findAll('span',attrs={'class':'artTitle'}): alink = art.parent url = self.PREFIX + alink['href'] @@ -110,3 +91,4 @@ class Nin(BasicNewsRecipe): }) articles.append((section,inarts)) return articles + diff --git a/resources/recipes/oc_register.recipe b/resources/recipes/oc_register.recipe new file mode 100644 index 0000000000..9a04585a3c --- /dev/null +++ b/resources/recipes/oc_register.recipe @@ -0,0 +1,73 @@ +#!/usr/bin/env python +__license__ = 'GPL v3' +__author__ = 'Lorenzo Vigentini' +__copyright__ = '2009, Lorenzo Vigentini ' +description = 'News from the Orange county - v1.01 (29, January 2010)' + +''' +http://www.ocregister.com/ +''' + +from calibre.web.feeds.news import BasicNewsRecipe + +class ocRegister(BasicNewsRecipe): + author = 'Lorenzo Vigentini' + description = 'News from the Orange county' + + cover_url = 'http://images.onset.freedom.com/ocregister/logo.gif' + title = u'Orange County Register' + publisher = 'Orange County Register Communication' + category = 'News, finance, economy, politics' + + language = 'en' + timefmt = '[%a, %d %b, %Y]' + + oldest_article = 1 + max_articles_per_feed = 25 + use_embedded_content = False + recursion = 10 + + remove_javascript = True + no_stylesheets = True + + def print_version(self,url): + printUrl = 'http://www.ocregister.com/common/printer/view.php?db=ocregister&id=' + segments = url.split('/') + subSegments = (segments[4]).split('.') + myArticle = (subSegments[0]).replace('-', '') + myURL= printUrl + myArticle + return myURL + + keep_only_tags = [ + dict(name='div', attrs={'id':'ArticleContentWrap'}) + ] + + remove_tags = [ + dict(name='div', attrs={'class':'hideForPrint'}), + dict(name='div', attrs={'id':'ContentFooter'}) + ] + + feeds = [ + (u'News', u'http://www.ocregister.com/common/rss/rss.php?catID=18800'), + (u'Today paper', u'http://www.ocregister.com/common/rss/rss.php?catID=18976'), + (u'Business', u'http://www.ocregister.com/common/rss/rss.php?catID=18909'), + (u'Cars', u'http://www.ocregister.com/common/rss/rss.php?catID=20128'), + (u'Entertainment', u'http://www.ocregister.com/common/rss/rss.php?catID=18926'), + (u'Home', u'http://www.ocregister.com/common/rss/rss.php?catID=19142'), + (u'Life', u'http://www.ocregister.com/common/rss/rss.php?catID=18936'), + (u'Opinion', u'http://www.ocregister.com/common/rss/rss.php?catID=18963'), + (u'Sports', u'http://www.ocregister.com/common/rss/rss.php?catID=18901'), + (u'Travel', u'http://www.ocregister.com/common/rss/rss.php?catID=18959') + ] + + extra_css = ''' + h1 {color:#ff6600;font-family:Arial,Helvetica,sans-serif; font-size:20px; font-size-adjust:none; font-stretch:normal; font-style:normal; font-variant:normal; font-weight:bold; line-height:20px;} + h2 {color:#4D4D4D;font-family:Arial,Helvetica,sans-serif; font-size:16px; font-size-adjust:none; font-stretch:normal; font-style:normal; font-variant:normal; font-weight:bold; line-height:16px; } + h3 {color:#4D4D4D;font-family:Arial,Helvetica,sans-serif; font-size:15px; font-size-adjust:none; font-stretch:normal; font-style:normal; font-variant:normal; font-weight:bold; line-height:15px;} + h4 {color:#333333; font-family:Arial,Helvetica,sans-serif;font-size:13px; font-size-adjust:none; font-stretch:normal; font-style:normal; font-variant:normal; font-weight:bold; line-height:13px; } + h5 {color:#333333; font-family:Arial,Helvetica,sans-serif; font-size:11px; font-size-adjust:none; font-stretch:normal; font-style:normal; font-variant:normal; font-weight:bold; line-height:11px; text-transform:uppercase;} + #articledate {color:#333333;font-family:Arial,Helvetica,sans-serif;font-size:10px; font-size-adjust:none; font-stretch:normal; font-style:italic; font-variant:normal; font-weight:bold; line-height:10px; text-decoration:none;} + #articlebyline {color:#4D4D4D;font-family:Arial,Helvetica,sans-serif;font-size:10px; font-size-adjust:none; font-stretch:normal; font-style:bold; font-variant:normal; font-weight:bold; line-height:10px; text-decoration:none;} + img {align:left;} + #topstoryhead {color:#ff6600;font-family:Arial,Helvetica,sans-serif; font-size:22px; font-size-adjust:none; font-stretch:normal; font-style:normal; font-variant:normal; font-weight:bold; line-height:20px;} + ''' diff --git a/resources/recipes/politiken_dk.recipe b/resources/recipes/politiken_dk.recipe new file mode 100644 index 0000000000..aa117fda8d --- /dev/null +++ b/resources/recipes/politiken_dk.recipe @@ -0,0 +1,55 @@ + +__license__ = 'GPL v3' +__copyright__ = '2010, Darko Miletic ' +''' +politiken.dk +''' + +from calibre.web.feeds.news import BasicNewsRecipe + +class Politiken_dk(BasicNewsRecipe): + title = 'Politiken.dk' + __author__ = 'Darko Miletic' + description = 'News from Denmark' + publisher = 'politiken.dk' + category = 'news, politics, Denmark' + oldest_article = 2 + max_articles_per_feed = 100 + no_stylesheets = True + remove_empty_feeds = True + use_embedded_content = False + encoding = 'cp1252' + language = 'da' + + extra_css = ' body{font-family: Arial,Helvetica,sans-serif } h1{font-family: Georgia,"Times New Roman",Times,serif } ' + + conversion_options = { + 'comment' : description + , 'tags' : category + , 'publisher': publisher + , 'language' : language + } + + feeds = [ + (u'Tophistorier' , u'http://politiken.dk/rss/tophistorier.rss') + ,(u'Seneste nyt' , u'http://politiken.dk/rss/senestenyt.rss') + ,(u'Mest laeste' , u'http://politiken.dk/rss/mestlaeste.rss') + ,(u'Danmark' , u'http://politiken.dk/rss/indland.rss') + ,(u'Politik' , u'http://politiken.dk/rss/politik.rss') + ,(u'Klima' , u'http://politiken.dk/rss/klima.rss') + ,(u'Internationalt' , u'http://politiken.dk/rss/udland.rss') + ,(u'Erhverv' , u'http://politiken.dk/rss/erhverv.rss') + ,(u'Kultur' , u'http://politiken.dk/rss/kultur.rss') + ,(u'Sport' , u'http://politiken.dk/rss/sport.rss') + ,(u'Uddannelse' , u'http://politiken.dk/rss/uddannelse.rss') + ,(u'Videnskab' , u'http://politiken.dk/rss/videnskab.rss') + ] + remove_tags_before = dict(name='h1') + remove_tags = [ + dict(name=['object','link']) + ,dict(name='div',attrs={'class':'footer'}) + ] + + def print_version(self, url): + return url + '?service=print' + diff --git a/resources/recipes/wash_post.recipe b/resources/recipes/wash_post.recipe index 5e62aa753c..a917371cec 100644 --- a/resources/recipes/wash_post.recipe +++ b/resources/recipes/wash_post.recipe @@ -46,3 +46,10 @@ class WashingtonPost(BasicNewsRecipe): div['style'] = '' return soup + def preprocess_html(self, soup): + for tag in soup.findAll('font'): + if tag.has_key('size'): + if tag['size'] == '+2': + if tag.b: + return soup + return None diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index 7181c16329..fed22f87e2 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -89,6 +89,8 @@ def _config(): help=_('Maximum number of waiting worker processes')) c.add_opt('get_social_metadata', default=True, help=_('Download social metadata (tags/rating/etc.)')) + c.add_opt('overwrite_author_title_metadata', default=True, + help=_('Overwrite author and title with new metadata')) c.add_opt('enforce_cpu_limit', default=True, help=_('Limit max simultaneous jobs to number of CPUs')) diff --git a/src/calibre/gui2/convert/gui_conversion.py b/src/calibre/gui2/convert/gui_conversion.py index 67c50758f8..70321b049b 100644 --- a/src/calibre/gui2/convert/gui_conversion.py +++ b/src/calibre/gui2/convert/gui_conversion.py @@ -23,7 +23,7 @@ def gui_convert(input, output, recommendations, notification=DummyReporter(), plumber.run() -def gui_catalog(fmt, title, dbspec, ids, out_file_name, fmt_options, +def gui_catalog(fmt, title, dbspec, ids, out_file_name, sync, fmt_options, notification=DummyReporter(), log=None): if log is None: log = Log() @@ -46,6 +46,7 @@ def gui_catalog(fmt, title, dbspec, ids, out_file_name, fmt_options, opts.ids = ids opts.search_text = None opts.sort_by = None + opts.sync = sync # Extract the option dictionary to comma-separated lists for option in fmt_options: diff --git a/src/calibre/gui2/dialogs/config/__init__.py b/src/calibre/gui2/dialogs/config/__init__.py index 156faec7ce..88697e55bb 100644 --- a/src/calibre/gui2/dialogs/config/__init__.py +++ b/src/calibre/gui2/dialogs/config/__init__.py @@ -458,6 +458,7 @@ class ConfigDialog(ResizableDialog, Ui_Dialog): self.connect(self.button_open_config_dir, SIGNAL('clicked()'), self.open_config_dir) self.opt_get_social_metadata.setChecked(config['get_social_metadata']) + self.opt_overwrite_author_title_metadata.setChecked(config['overwrite_author_title_metadata']) self.opt_enforce_cpu_limit.setChecked(config['enforce_cpu_limit']) self.device_detection_button.clicked.connect(self.debug_device_detection) @@ -751,6 +752,7 @@ class ConfigDialog(ResizableDialog, Ui_Dialog): config['upload_news_to_device'] = self.sync_news.isChecked() config['search_as_you_type'] = self.search_as_you_type.isChecked() config['get_social_metadata'] = self.opt_get_social_metadata.isChecked() + config['overwrite_author_title_metadata'] = self.opt_overwrite_author_title_metadata.isChecked() config['enforce_cpu_limit'] = bool(self.opt_enforce_cpu_limit.isChecked()) fmts = [] for i in range(self.viewer.count()): diff --git a/src/calibre/gui2/dialogs/config/config.ui b/src/calibre/gui2/dialogs/config/config.ui index b9306b0f10..6da5362248 100644 --- a/src/calibre/gui2/dialogs/config/config.ui +++ b/src/calibre/gui2/dialogs/config/config.ui @@ -171,6 +171,13 @@ + + + + Overwrite & author/title by default when fetching metadata + + + diff --git a/src/calibre/gui2/dialogs/fetch_metadata.py b/src/calibre/gui2/dialogs/fetch_metadata.py index b021a2470d..5a0957be31 100644 --- a/src/calibre/gui2/dialogs/fetch_metadata.py +++ b/src/calibre/gui2/dialogs/fetch_metadata.py @@ -119,6 +119,7 @@ class FetchMetadata(QDialog, Ui_FetchMetadata): self.matches.setMouseTracking(True) self.fetch_metadata() self.opt_get_social_metadata.setChecked(config['get_social_metadata']) + self.opt_overwrite_author_title_metadata.setChecked(config['overwrite_author_title_metadata']) def show_summary(self, current, *args): @@ -149,7 +150,8 @@ class FetchMetadata(QDialog, Ui_FetchMetadata): self.fetcher.start() self.pi.start(_('Finding metadata...')) self._hangcheck = QTimer(self) - self.connect(self._hangcheck, SIGNAL('timeout()'), self.hangcheck) + self.connect(self._hangcheck, SIGNAL('timeout()'), self.hangcheck, + Qt.QueuedConnection) self.start_time = time.time() self._hangcheck.start(100) diff --git a/src/calibre/gui2/dialogs/fetch_metadata.ui b/src/calibre/gui2/dialogs/fetch_metadata.ui index fe97b32f28..f14d402e11 100644 --- a/src/calibre/gui2/dialogs/fetch_metadata.ui +++ b/src/calibre/gui2/dialogs/fetch_metadata.ui @@ -116,6 +116,13 @@ + + + + Overwrite &author/title with author/title of selected book + + + diff --git a/src/calibre/gui2/dialogs/metadata_single.py b/src/calibre/gui2/dialogs/metadata_single.py index 89b7c92125..846851fd21 100644 --- a/src/calibre/gui2/dialogs/metadata_single.py +++ b/src/calibre/gui2/dialogs/metadata_single.py @@ -574,9 +574,10 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog): det_msg=det, show=True) else: book.tags = [] - self.title.setText(book.title) - self.authors.setText(authors_to_string(book.authors)) - if book.author_sort: self.author_sort.setText(book.author_sort) + if d.opt_overwrite_author_title_metadata.isChecked(): + self.title.setText(book.title) + self.authors.setText(authors_to_string(book.authors)) + if book.author_sort: self.author_sort.setText(book.author_sort) if book.publisher: self.publisher.setEditText(book.publisher) if book.isbn: self.isbn.setText(book.isbn) if book.pubdate: diff --git a/src/calibre/gui2/metadata.py b/src/calibre/gui2/metadata.py index ecdca29422..d63e9648cc 100644 --- a/src/calibre/gui2/metadata.py +++ b/src/calibre/gui2/metadata.py @@ -12,6 +12,7 @@ from Queue import Queue, Empty from calibre.ebooks.metadata.fetch import search, get_social_metadata +from calibre.gui2 import config from calibre.ebooks.metadata.library_thing import cover_from_isbn from calibre.customize.ui import get_isbndb_key @@ -98,6 +99,10 @@ class DownloadMetadata(Thread): self.fetched_metadata[id] = fmi if fmi.isbn and self.get_covers: self.worker.jobs.put(fmi.isbn) + if (not config['overwrite_author_title_metadata']): + fmi.authors = mi.authors + fmi.author_sort = mi.author_sort + fmi.title = mi.title mi.smart_update(fmi) if mi.isbn and self.get_social_metadata: self.social_metadata_exceptions = get_social_metadata(mi) diff --git a/src/calibre/gui2/tools.py b/src/calibre/gui2/tools.py index 7dc83baf32..bd34f84821 100644 --- a/src/calibre/gui2/tools.py +++ b/src/calibre/gui2/tools.py @@ -254,11 +254,13 @@ def generate_catalog(parent, dbspec, ids): dbspec, ids, out.name, + d.catalog_sync, d.fmt_options ] out.close() - # This calls gui2.convert.gui_conversion:gui_catalog() + # This returns to gui2.ui:generate_catalog() + # Which then calls gui2.convert.gui_conversion:gui_catalog() return 'gui_catalog', args, _('Generate catalog'), out.name, d.catalog_sync, \ d.catalog_title diff --git a/src/calibre/library/catalog.py b/src/calibre/library/catalog.py index 6aa664a166..f289c9a868 100644 --- a/src/calibre/library/catalog.py +++ b/src/calibre/library/catalog.py @@ -796,6 +796,12 @@ class EPUB_MOBI(CatalogPlugin): shutil.copy(os.path.join(catalog_resources,file[1]), os.path.join(self.catalogPath, file[0])) + # Create the custom masthead image overwriting default + try: + self.generate_masthead_image(os.path.join(self.catalogPath, 'images/mastheadImage.gif')) + except: + pass + def fetchBooksByTitle(self): self.updateProgressFullStep("Fetching database") @@ -1794,7 +1800,11 @@ class EPUB_MOBI(CatalogPlugin): # Add the author tag cmTag = Tag(ncx_soup, '%s' % 'calibre:meta') cmTag['name'] = "author" - cmTag.insert(0, NavigableString(self.formatNCXText(book['author']))) + navStr = '%s | %s' % (self.formatNCXText(book['author']), + book['date'].split()[1]) + if 'tags' in book: + navStr += ' | %s' % self.formatNCXText(' · '.join(sorted(book['tags']))) + cmTag.insert(0, NavigableString(navStr)) navPointVolumeTag.insert(2, cmTag) # Add the description tag @@ -1996,9 +2006,10 @@ class EPUB_MOBI(CatalogPlugin): self.updateProgressFullStep("NCX Recently Added") def add_to_master_month_list(current_titles_list): + book_count = len(current_titles_list) current_titles_list = " • ".join(current_titles_list) current_titles_list = self.generateShortDescription(self.formatNCXText(current_titles_list)) - master_month_list.append((current_titles_list, current_date)) + master_month_list.append((current_titles_list, current_date, book_count)) soup = self.ncxSoup HTML_file = "content/ByDateAdded.html" @@ -2028,7 +2039,7 @@ class EPUB_MOBI(CatalogPlugin): # Create an NCX article entry for each populated month # Loop over the booksByDate list, find start of each month, # add description_preview_count titles - # self.authors[0]:friendly [1]:author_sort [2]:book_count + # master_month_list(list,date,count) current_titles_list = [] master_month_list = [] current_date = self.booksByDate[0]['timestamp'] @@ -2074,6 +2085,13 @@ class EPUB_MOBI(CatalogPlugin): cmTag.insert(0, NavigableString(books_by_month[0])) navPointByMonthTag.insert(2, cmTag) + cmTag = Tag(soup, '%s' % 'calibre:meta') + cmTag['name'] = "author" + navStr = '%d titles' % books_by_month[2] if books_by_month[2] > 1 else \ + '%d title' % books_by_month[2] + cmTag.insert(0, NavigableString(navStr)) + navPointByMonthTag.insert(3, cmTag) + navPointTag.insert(nptc, navPointByMonthTag) nptc += 1 @@ -2172,7 +2190,7 @@ class EPUB_MOBI(CatalogPlugin): for title in genre['books']: titles.append(title['title']) titles = sorted(titles, key=lambda x:(self.generateSortTitle(x),self.generateSortTitle(x))) - titles_list = self.generateShortDescription(" • ".join(titles)) + titles_list = self.generateShortDescription(u" • ".join(titles)) cmTag.insert(0, NavigableString(self.formatNCXText(titles_list))) navPointVolumeTag.insert(3, cmTag) @@ -2275,9 +2293,9 @@ class EPUB_MOBI(CatalogPlugin): else: continue if self.verbose: - self.opts.log.info(' %d Genre tags (exclude_genre: %s):' % \ + self.opts.log.info(u' %d Genre tags in database (exclude_genre: %s):' % \ (len(filtered_tags), self.opts.exclude_genre)) - self.opts.log.info(' %s' % ', '.join(filtered_tags)) + self.opts.log.info(u' %s' % ', '.join(filtered_tags)) return filtered_tags @@ -2479,6 +2497,26 @@ class EPUB_MOBI(CatalogPlugin): titleTag.insert(0,escape(NavigableString(title))) return soup + def generate_masthead_image(self, out_path): + MI_WIDTH = 600 + MI_HEIGHT = 60 + + try: + from PIL import Image, ImageDraw, ImageFont + Image, ImageDraw, ImageFont + except ImportError: + import Image, ImageDraw, ImageFont + + img = Image.new('RGB', (MI_WIDTH, MI_HEIGHT), 'white') + draw = ImageDraw.Draw(img) + font = ImageFont.truetype(P('fonts/liberation/LiberationSerif-Bold.ttf'), 48) + text = self.title.encode('utf-8') + width, height = draw.textsize(text, font=font) + left = max(int((MI_WIDTH - width)/2.), 0) + top = max(int((MI_HEIGHT - height)/2.), 0) + draw.text((left, top), text, fill=(0,0,0), font=font) + img.save(open(out_path, 'wb'), 'GIF') + def generateShortDescription(self, description): # Truncate the description to description_clip, on word boundaries if necessary if not description: @@ -2611,13 +2649,18 @@ class EPUB_MOBI(CatalogPlugin): # Add local options opts.creator = "calibre" - opts.descriptionClip = 380 if self.opts.output_profile.endswith('dx') else 90 + op = self.opts.output_profile + if op is None: + op = 'default' + opts.descriptionClip = 380 if op.endswith('dx') or 'kindle' not in op else 90 opts.basename = "Catalog" opts.plugin_path = self.plugin_path if opts.verbose: opts_dict = vars(opts) - log("%s(): Generating %s for %s" % (self.name,self.fmt,opts.output_profile)) + gui = True if 'sync' in opts_dict else False + log("%s(): Generating %s for %s in %s environment" % \ + (self.name,self.fmt,opts.output_profile, 'GUI' if gui else 'CLI')) if opts_dict['ids']: log(" Book count: %d" % len(opts_dict['ids'])) # Display opts @@ -2627,7 +2670,7 @@ class EPUB_MOBI(CatalogPlugin): for key in keys: if key in ['catalog_title','exclude_genre','exclude_tags','note_tag', - 'numbers_as_text','read_tag','search_text','sort_by']: + 'numbers_as_text','read_tag','search_text','sort_by','sync']: log(" %s: %s" % (key, opts_dict[key])) # Launch the Catalog builder diff --git a/src/calibre/web/feeds/news.py b/src/calibre/web/feeds/news.py index 113d7dd756..d182d856d8 100644 --- a/src/calibre/web/feeds/news.py +++ b/src/calibre/web/feeds/news.py @@ -770,7 +770,11 @@ class BasicNewsRecipe(Recipe): self.download_masthead(murl) if self.masthead_path is None: self.masthead_path = os.path.join(self.output_dir, 'mastheadImage.jpg') - self.default_masthead_image(self.masthead_path) + try: + self.default_masthead_image(self.masthead_path) + except: + self.log.exception('Failed to generate default masthead image') + self.masthead_path = None if self.test: feeds = feeds[:2] @@ -1061,7 +1065,7 @@ class BasicNewsRecipe(Recipe): opf = OPFCreator(dir, mi) # Add mastheadImage entry to section mp = getattr(self, 'masthead_path', None) - if mp is not None: + if mp is not None and os.access(mp, os.R_OK): from calibre.ebooks.metadata.opf2 import Guide ref = Guide.Reference(os.path.basename(self.masthead_path), os.getcwdu()) ref.type = 'masthead'