From f0232f60fa83b8111e4ba6c8dc84caa88c454708 Mon Sep 17 00:00:00 2001 From: GRiker Date: Fri, 22 Jan 2010 15:42:31 -0700 Subject: [PATCH 01/25] Temporary fix for MOBI indexing problem --- src/calibre/library/catalog.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/calibre/library/catalog.py b/src/calibre/library/catalog.py index b62d1a0f29..2aa09b3cb6 100644 --- a/src/calibre/library/catalog.py +++ b/src/calibre/library/catalog.py @@ -1169,7 +1169,7 @@ class EPUB_MOBI(CatalogPlugin): book_count = 0 for book in self.booksByAuthor: book_count += 1 - if book['author_sort'][0] != current_letter : + if book['author_sort'][0].upper() != current_letter : ''' # Start a new letter - anchor only, hidden current_letter = book['author_sort'][0].upper() @@ -1810,14 +1810,12 @@ class EPUB_MOBI(CatalogPlugin): self.playOrder += 1 navLabelTag = Tag(soup, 'navLabel') textTag = Tag(soup, 'text') - # textTag.insert(0, NavigableString('%s (%d)' % (section_title,len(sorted_authors)))) textTag.insert(0, NavigableString('%s' % tocTitle)) navLabelTag.insert(0, textTag) nptc = 0 navPointTag.insert(nptc, navLabelTag) nptc += 1 contentTag = Tag(soup,"content") - # contentTag['src'] = "%s#%s" % (HTML_file, file_ID) contentTag['src'] = "%s#section_start" % HTML_file navPointTag.insert(nptc, contentTag) nptc += 1 @@ -2522,7 +2520,7 @@ class EPUB_MOBI(CatalogPlugin): opts.fmt = self.fmt = path_to_output.rpartition('.')[2] # Add local options - opts.creator = "calibre" + opts.creator = "Calibre" opts.dbs_fname = "CatalogSnapshot.dat" opts.descriptionClip = 250 opts.basename = "Catalog" From f2776c02eb64a6961bc1dc6798b150c8693a5d8f Mon Sep 17 00:00:00 2001 From: GRiker Date: Fri, 22 Jan 2010 15:54:25 -0700 Subject: [PATCH 02/25] Fix & in authors field --- src/calibre/library/catalog.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/calibre/library/catalog.py b/src/calibre/library/catalog.py index 2aa09b3cb6..2201ea8b1a 100644 --- a/src/calibre/library/catalog.py +++ b/src/calibre/library/catalog.py @@ -917,7 +917,8 @@ class EPUB_MOBI(CatalogPlugin): authorTag = body.find(attrs={'class':'author'}) aTag = Tag(soup, "a") aTag['href'] = "%s.html#%s" % ("ByAlphaAuthor", self.generateAuthorAnchor(title['author'])) - aTag.insert(0, escape(title['author'])) + #aTag.insert(0, escape(title['author'])) + aTag.insert(0, title['author']) authorTag.insert(0, NavigableString("by ")) authorTag.insert(1, aTag) From ab10ac42ba3dddbcd97ffd15653686e49d58c80a Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 22 Jan 2010 15:57:24 -0700 Subject: [PATCH 03/25] Fix tags markup in catalog --- resources/catalog/stylesheet.css | 2 ++ src/calibre/gui2/viewer/documentview.py | 2 +- src/calibre/library/catalog.py | 4 ++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/resources/catalog/stylesheet.css b/resources/catalog/stylesheet.css index 056c2f5ee8..458d1a9bf0 100644 --- a/resources/catalog/stylesheet.css +++ b/resources/catalog/stylesheet.css @@ -1,3 +1,5 @@ +body { background-color: white; } + p.title { margin-top:0em; margin-bottom:1em; diff --git a/src/calibre/gui2/viewer/documentview.py b/src/calibre/gui2/viewer/documentview.py index 124651bdf3..f6fce62eac 100644 --- a/src/calibre/gui2/viewer/documentview.py +++ b/src/calibre/gui2/viewer/documentview.py @@ -178,7 +178,7 @@ class Document(QWebPage): def set_user_stylesheet(self): raw = config().parse().user_css - raw = '::selection {background:#ffff00; color:#000;}\n'+raw + raw = '::selection {background:#ffff00; color:#000;}\nbody {background-color: white;}\n'+raw data = 'data:text/css;charset=utf-8;base64,' data += b64encode(raw.encode('utf-8')) self.settings().setUserStyleSheetUrl(QUrl(data)) diff --git a/src/calibre/library/catalog.py b/src/calibre/library/catalog.py index f60ca4a106..c20e0c761e 100644 --- a/src/calibre/library/catalog.py +++ b/src/calibre/library/catalog.py @@ -938,6 +938,8 @@ class EPUB_MOBI(CatalogPlugin): # Insert a spacer to match the author indent fontTag = Tag(soup,"font") fontTag['style'] = 'color:white;font-size:large' + if self.opts.fmt == 'epub': + fontTag['style'] += ';opacity: 0.0' fontTag.insert(0, NavigableString("by ")) tagsTag.insert(ttc, fontTag) ttc += 1 @@ -948,6 +950,8 @@ class EPUB_MOBI(CatalogPlugin): aTag.insert(0,escape(NavigableString(tag))) emTag = Tag(soup, "em") emTag.insert(0, aTag) + if ttc < len(title['tags']): + emTag.insert(1, NavigableString(', ')) tagsTag.insert(ttc, emTag) ttc += 1 From 57064a70fa226a3b376c911b424a34446f1bec08 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 22 Jan 2010 16:12:51 -0700 Subject: [PATCH 04/25] Fix progress reporting magnitude in epub/mobi catalog plugin --- src/calibre/library/catalog.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/calibre/library/catalog.py b/src/calibre/library/catalog.py index 3764fdd313..aaf1c4bc95 100644 --- a/src/calibre/library/catalog.py +++ b/src/calibre/library/catalog.py @@ -2510,14 +2510,14 @@ class EPUB_MOBI(CatalogPlugin): self.current_step += 1 self.progressString = description self.progressInt = ((self.current_step-1)*100)/self.total_steps - self.reporter(self.progressInt, self.progressString) + self.reporter(self.progressInt/100., self.progressString) return "%d%% %s" % (self.progressInt, self.progressString) def updateProgressMicroStep(self, description, micro_step_pct): step_range = 100/self.total_steps self.progressString = description self.progressInt = ((self.current_step-1)*100)/self.total_steps + (micro_step_pct*step_range)/100 - self.reporter(self.progressInt, self.progressString) + self.reporter(self.progressInt/100., self.progressString) return "%d%% %s" % (self.progressInt, self.progressString) def run(self, path_to_output, opts, db, notification=DummyReporter()): From a46a050b0bcbd6568575eae9ba11d71ce5f2d2dc Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 22 Jan 2010 16:20:23 -0700 Subject: [PATCH 05/25] version 0.6.35 --- src/calibre/constants.py | 2 +- src/calibre/gui2/catalog/catalog_epub_mobi.py | 2 +- src/calibre/library/catalog.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/calibre/constants.py b/src/calibre/constants.py index 2c4aeeb766..84676c8acc 100644 --- a/src/calibre/constants.py +++ b/src/calibre/constants.py @@ -2,7 +2,7 @@ __license__ = 'GPL v3' __copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net' __docformat__ = 'restructuredtext en' __appname__ = 'calibre' -__version__ = '0.6.34' +__version__ = '0.6.35' __author__ = "Kovid Goyal " import re diff --git a/src/calibre/gui2/catalog/catalog_epub_mobi.py b/src/calibre/gui2/catalog/catalog_epub_mobi.py index 9b9911b5d4..841ba5f6ad 100644 --- a/src/calibre/gui2/catalog/catalog_epub_mobi.py +++ b/src/calibre/gui2/catalog/catalog_epub_mobi.py @@ -14,7 +14,7 @@ from PyQt4.Qt import QWidget class PluginWidget(QWidget,Ui_Form): - TITLE = _('EPUB/MOBI Options') + TITLE = _('E-book Options') HELP = _('Options specific to')+' EPUB/MOBI '+_('output') OPTION_FIELDS = [('exclude_genre','\[[\w ]*\]'), ('exclude_tags','~'), diff --git a/src/calibre/library/catalog.py b/src/calibre/library/catalog.py index aaf1c4bc95..9329f314ca 100644 --- a/src/calibre/library/catalog.py +++ b/src/calibre/library/catalog.py @@ -230,7 +230,7 @@ class EPUB_MOBI(CatalogPlugin): minimum_calibre_version = (0, 6, 34) author = 'Greg Riker' version = (0, 0, 1) - file_types = set(['epub','mobi']) + file_types = set(['epub']) cli_options = [Option('--catalog-title', default = 'My Catalog', From 1d3f0e63923df4e17dec503be2d7eff1552eff9d Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 22 Jan 2010 16:59:55 -0700 Subject: [PATCH 06/25] IGN:Tag release --- src/calibre/translations/calibre.pot | 236 ++++++++++++++++++--------- 1 file changed, 157 insertions(+), 79 deletions(-) diff --git a/src/calibre/translations/calibre.pot b/src/calibre/translations/calibre.pot index 142bb500b3..2d6a0efc05 100644 --- a/src/calibre/translations/calibre.pot +++ b/src/calibre/translations/calibre.pot @@ -4,9 +4,9 @@ # msgid "" msgstr "" -"Project-Id-Version: calibre 0.6.34\n" -"POT-Creation-Date: 2010-01-21 20:05+MST\n" -"PO-Revision-Date: 2010-01-21 20:05+MST\n" +"Project-Id-Version: calibre 0.6.35\n" +"POT-Creation-Date: 2010-01-22 16:20+MST\n" +"PO-Revision-Date: 2010-01-22 16:20+MST\n" "Last-Translator: Automatically generated\n" "Language-Team: LANGUAGE\n" "MIME-Version: 1.0\n" @@ -216,19 +216,19 @@ msgstr "" msgid "Set metadata from %s files" msgstr "" -#: /home/kovid/work/calibre/src/calibre/customize/conversion.py:99 +#: /home/kovid/work/calibre/src/calibre/customize/conversion.py:102 msgid "Conversion Input" msgstr "" -#: /home/kovid/work/calibre/src/calibre/customize/conversion.py:122 +#: /home/kovid/work/calibre/src/calibre/customize/conversion.py:125 msgid "Specify the character encoding of the input document. If set this option will override any encoding declared by the document itself. Particularly useful for documents that do not declare an encoding or that have erroneous encoding declarations." msgstr "" -#: /home/kovid/work/calibre/src/calibre/customize/conversion.py:225 +#: /home/kovid/work/calibre/src/calibre/customize/conversion.py:228 msgid "Conversion Output" msgstr "" -#: /home/kovid/work/calibre/src/calibre/customize/conversion.py:239 +#: /home/kovid/work/calibre/src/calibre/customize/conversion.py:242 msgid "If specified, the output plugin will try to create output that is as human readable as possible. May not have any effect for some output plugins." msgstr "" @@ -2134,6 +2134,7 @@ msgid "CSV/XML Options" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_csv_xml.py:17 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_epub_mobi.py:18 #: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input.py:16 #: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output.py:16 #: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_input.py:13 @@ -2151,6 +2152,7 @@ msgid "Options specific to" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_csv_xml.py:17 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_epub_mobi.py:18 #: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output.py:16 #: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_output.py:15 #: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output.py:20 @@ -2162,7 +2164,8 @@ msgstr "" msgid "output" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_csv_xml_ui.py:34 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_csv_xml_ui.py:36 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_epub_mobi_ui.py:51 #: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_tab_template_ui.py:27 #: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input_ui.py:84 #: /home/kovid/work/calibre/src/calibre/gui2/convert/debug_ui.py:49 @@ -2193,10 +2196,34 @@ msgstr "" msgid "Form" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_csv_xml_ui.py:35 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_csv_xml_ui.py:37 msgid "Fields to include in output:" msgstr "" +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_epub_mobi.py:17 +msgid "E-book Options" +msgstr "" + +#: +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_epub_mobi_ui.py:52 +msgid "Tags to exclude as genres (regex):" +msgstr "" + +#: +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_epub_mobi_ui.py:53 +msgid "'Don't include this book' tag:" +msgstr "" + +#: +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_epub_mobi_ui.py:54 +msgid "'Mark this book as read' tag:" +msgstr "" + +#: +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_epub_mobi_ui.py:55 +msgid "Additional note tag prefix:" +msgstr "" + #: #: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_tab_template_ui.py:28 msgid "Tab template for catalog.ui" @@ -2799,7 +2826,7 @@ msgid "RB Output" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/convert/regex_builder.py:77 -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1633 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1637 msgid "Choose the format to view" msgstr "" @@ -3331,7 +3358,7 @@ msgstr "" msgid "&Next" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/catalog.py:38 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/catalog.py:37 msgid "My Books" msgstr "" @@ -3457,7 +3484,7 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:477 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:821 #: /home/kovid/work/calibre/src/calibre/gui2/ui.py:158 -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1242 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1246 #: /home/kovid/work/calibre/src/calibre/utils/ipc/job.py:53 msgid "Error" msgstr "" @@ -5398,7 +5425,7 @@ msgid "Save to disk in a single directory" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/ui.py:306 -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1741 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1745 msgid "Save only %s format to disk" msgstr "" @@ -5453,7 +5480,7 @@ msgid "Calibre Library" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/ui.py:485 -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1897 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1901 msgid "Choose a location for your ebook library." msgstr "" @@ -5558,8 +5585,8 @@ msgid "Cannot delete" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1075 -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1627 -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1646 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1631 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1650 msgid "No book selected" msgstr "" @@ -5567,219 +5594,227 @@ msgstr "" msgid "Choose formats to be deleted" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1101 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1103 msgid "Choose formats not to be deleted" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1137 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1141 msgid "The selected books will be permanently deleted and the files removed from your computer. Are you sure?" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1164 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1168 msgid "Deleting books from device." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1195 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1199 msgid "Cannot download metadata" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1196 -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1253 -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1286 -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1311 -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1370 -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1483 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1200 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1257 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1290 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1315 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1374 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1487 msgid "No books selected" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1211 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1215 msgid "social metadata" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1213 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1217 msgid "covers" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1213 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1217 msgid "metadata" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1215 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1219 msgid "Downloading %s for %d book(s)" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1237 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1241 msgid "Failed to download some metadata" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1238 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1242 msgid "Failed to download metadata for the following:" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1241 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1245 msgid "Failed to download metadata:" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1252 -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1285 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1256 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1289 msgid "Cannot edit metadata" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1310 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1314 msgid "Cannot save to disk" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1313 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1317 msgid "Choose destination directory" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1340 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1344 msgid "Error while saving" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1341 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1345 msgid "There was an error while saving." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1348 -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1349 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1352 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1353 msgid "Could not save some books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1350 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1354 msgid "Click the show details button to see which ones." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1371 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1375 msgid "No books selected to generate catalog for" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1388 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1392 msgid "Generating %s catalog..." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1399 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1403 msgid "Catalog generated." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1417 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1406 +msgid "Export Catalog Directory" +msgstr "" + +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1407 +msgid "Select destination for %s.%s" +msgstr "" + +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1421 msgid "Fetching news from " msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1431 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1435 msgid " fetched." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1482 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1486 msgid "Cannot convert" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1511 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1515 msgid "Starting conversion of %d book(s)" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1627 -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1683 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1631 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1687 msgid "Cannot view" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1645 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1649 msgid "Cannot open folder" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1667 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1671 msgid "Multiple Books Selected" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1668 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1672 msgid "You are attempting to open %d books. Opening too many books at once can be slow and have a negative effect on the responsiveness of your computer. Once started the process cannot be stopped until complete. Do you wish to continue?" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1684 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1688 msgid "%s has no available formats." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1725 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1729 msgid "Cannot configure" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1726 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1730 msgid "Cannot configure while there are running jobs." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1769 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1773 msgid "No detailed info available" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1770 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1774 msgid "No detailed information is available for books on the device." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1825 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1829 msgid "Error talking to device" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1826 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1830 msgid "There was a temporary error talking to the device. Please unplug and reconnect the device and or reboot." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1849 -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1877 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1853 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1881 msgid "Conversion Error" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1850 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1854 msgid "

Could not convert: %s

It is a DRMed book. You must first remove the DRM using third party tools." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1863 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1867 msgid "Recipe Disabled" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1878 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1882 msgid "Failed" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1906 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1910 msgid "Invalid library location" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1907 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1911 msgid "Could not access %s. Using %s as the library." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1957 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1961 msgid "is the result of the efforts of many volunteers from all over the world. If you find it useful, please consider donating to support its development." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1982 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1986 msgid "There are active jobs. Are you sure you want to quit?" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1985 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1989 msgid "" " is communicating with the device!
\n" " Quitting may cause corruption on the device.
\n" " Are you sure you want to quit?" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1989 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1993 msgid "WARNING: Active jobs" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:2041 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:2045 msgid "will keep running in the system tray. To close it, choose Quit in the context menu of the system tray." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:2060 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:2064 msgid "Latest version: %s" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:2068 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:2072 msgid "Update available" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:2069 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:2073 msgid "%s has been updated to version %s. See the new features. Visit the download page?" msgstr "" @@ -5991,7 +6026,7 @@ msgstr "" msgid "The standard font type" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/viewer/documentview.py:407 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/documentview.py:408 msgid "&Lookup in dictionary" msgstr "" @@ -6524,7 +6559,7 @@ msgstr "" msgid "The maximum number of matches to return per OPDS query. This affects Stanza, WordPlayer, etc. integration." msgstr "" -#: /home/kovid/work/calibre/src/calibre/library/catalog.py:28 +#: /home/kovid/work/calibre/src/calibre/library/catalog.py:34 msgid "" "The fields to output when cataloging books in the database. Should be a comma-separated list of fields.\n" "Available fields: %s.\n" @@ -6532,7 +6567,7 @@ msgid "" "Applies to: CSV, XML output formats" msgstr "" -#: /home/kovid/work/calibre/src/calibre/library/catalog.py:37 +#: /home/kovid/work/calibre/src/calibre/library/catalog.py:43 msgid "" "Output field to sort on.\n" "Available fields: author_sort, id, rating, size, timestamp, title.\n" @@ -6540,6 +6575,49 @@ msgid "" "Applies to: CSV, XML output formats" msgstr "" +#: /home/kovid/work/calibre/src/calibre/library/catalog.py:238 +msgid "" +"Title of generated catalog used as title in metadata.\n" +"Default: '%default'\n" +"Applies to: ePub, MOBI output formats" +msgstr "" + +#: /home/kovid/work/calibre/src/calibre/library/catalog.py:244 +msgid "" +"Regex describing tags to exclude as genres.\n" +"Default: '%default' excludes bracketed tags, e.g. '[]'\n" +"Applies to: ePub, MOBI output formats" +msgstr "" + +#: /home/kovid/work/calibre/src/calibre/library/catalog.py:249 +msgid "" +"Comma-separated list of tag words indicating book should be excluded from output. Case-insensitive.\n" +"--exclude-tags=skip will match 'skip this book' and 'Skip will like this'.\n" +"Default: '%default'\n" +"Applies to: ePub, MOBI output formats" +msgstr "" + +#: /home/kovid/work/calibre/src/calibre/library/catalog.py:256 +msgid "" +"Tag indicating book has been read.\n" +"Default: '%default'\n" +"Applies to: ePub, MOBI output formats" +msgstr "" + +#: /home/kovid/work/calibre/src/calibre/library/catalog.py:261 +msgid "" +"Tag prefix for user notes, e.g. '*Jeff might enjoy reading this'.\n" +"Default: '%default'\n" +"Applies to: ePub, MOBI output formats" +msgstr "" + +#: /home/kovid/work/calibre/src/calibre/library/catalog.py:267 +msgid "" +"Specifies the output profile. In some cases, an output profile is required to optimize the catalog for the device. For example, 'kindle' or 'kindle_dx' creates a structured Table of Contents with Sections and Articles.\n" +"Default: '%default'\n" +"Applies to: ePub, MOBI output formats" +msgstr "" + #: /home/kovid/work/calibre/src/calibre/library/cli.py:121 msgid "Path to the calibre library. Default is to use the path stored in the settings." msgstr "" From 29444f04db933796caf7273abb033b57de33a480 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 22 Jan 2010 17:41:29 -0700 Subject: [PATCH 07/25] ... --- Changelog.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog.yaml b/Changelog.yaml index c9ece5cfbc..db050844d8 100644 --- a/Changelog.yaml +++ b/Changelog.yaml @@ -36,7 +36,7 @@ - title: "News downloads: When getting an article URL from a RSS feed, look first for an original article link. This speeds up the download of news services that use a syndication service like feedburner or pheedo to publish their RSS feeds." bug fixes: - - "Windows device detection: Don't do expensive polling while waiting for device disconnect. This should fix the problems people have with their floppy drive being activated while an e-book reader is connected" + - title: "Windows device detection: Don't do expensive polling while waiting for device disconnect. This should fix the problems people have with their floppy drive being activated while an e-book reader is connected" - title: "PML Input: Fix creation of metadata Table of Contents" tickets: [5633] From 4d7a1cbf7cdd27f1caea0a6b922737b2d2b5cac1 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 22 Jan 2010 17:44:27 -0700 Subject: [PATCH 08/25] ... --- Changelog.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog.yaml b/Changelog.yaml index db050844d8..f5835a0b1a 100644 --- a/Changelog.yaml +++ b/Changelog.yaml @@ -84,7 +84,7 @@ author: Darko Miletic - title: Pajamas Media - autor: Krittika Goyal + author: Krittika Goyal - title: Algemeen Dagbla author: kwetal From f4865b39de1cd0ca9952b7c1a09fbf2a3d656cb1 Mon Sep 17 00:00:00 2001 From: GRiker Date: Sat, 23 Jan 2010 07:23:09 -0700 Subject: [PATCH 09/25] GwR MOBI bug fixes, exclude Catalog from Catalogs, minor tweaks --- src/calibre/customize/__init__.py | 10 ++- src/calibre/ebooks/mobi/writer.py | 1 - src/calibre/gui2/dialogs/catalog.py | 4 +- src/calibre/library/catalog.py | 117 ++++++++++++++++------------ 4 files changed, 76 insertions(+), 56 deletions(-) diff --git a/src/calibre/customize/__init__.py b/src/calibre/customize/__init__.py index 0980f7b3a3..53cf82a4a3 100644 --- a/src/calibre/customize/__init__.py +++ b/src/calibre/customize/__init__.py @@ -255,9 +255,13 @@ class CatalogPlugin(Plugin): def search_sort_db(self, db, opts): - # If declared, --ids overrides any declared search criteria - if not opts.ids and opts.search_text: - db.search(opts.search_text) + # Don't add Catalogs to the generated Catalogs + if opts.search_text: + opts.search_text += ' not tag:Catalog' + else: + opts.search_text = 'not tag:Catalog' + + db.search(opts.search_text) if opts.sort_by: # 2nd arg = ascending diff --git a/src/calibre/ebooks/mobi/writer.py b/src/calibre/ebooks/mobi/writer.py index a21799cff6..f92e1bf2f9 100644 --- a/src/calibre/ebooks/mobi/writer.py +++ b/src/calibre/ebooks/mobi/writer.py @@ -619,7 +619,6 @@ class MobiWriter(object): self._oeb.log.warning('_generate_indexed_navpoints: Failed to generate index') # Zero out self._HTMLRecords, return False self._HTMLRecords = [] - #last_name = None return False previousOffset = offset diff --git a/src/calibre/gui2/dialogs/catalog.py b/src/calibre/gui2/dialogs/catalog.py index 7009824679..880b7b0fd6 100644 --- a/src/calibre/gui2/dialogs/catalog.py +++ b/src/calibre/gui2/dialogs/catalog.py @@ -46,18 +46,16 @@ class Catalog(QDialog, Ui_Dialog): name = plugin.name.lower().replace(' ', '_') if type(plugin) in builtin_plugins: - info("Adding widget for builtin Catalog plugin %s" % plugin.name) try: catalog_widget = __import__('calibre.gui2.catalog.'+name, fromlist=[1]) pw = catalog_widget.PluginWidget() - info("Initializing %s" % name) pw.initialize(name) pw.ICON = I('forward.svg') self.widgets.append(pw) [self.fmts.append([file_type.upper(), pw.sync_enabled,pw]) for file_type in plugin.file_types] except ImportError: - info("ImportError with %s" % name) + info("ImportError initializing %s" % name) continue else: # Load dynamic tab diff --git a/src/calibre/library/catalog.py b/src/calibre/library/catalog.py index 9329f314ca..8a5072d622 100644 --- a/src/calibre/library/catalog.py +++ b/src/calibre/library/catalog.py @@ -65,7 +65,10 @@ class CSV_XML(CatalogPlugin): for key in keys: log(" %s: %s" % (key, opts_dict[key])) - # Get the sorted, filtered database as a dictionary + # If a list of ids are provided, don't use search_text + if opts.ids: + opts.search_text = None + data = self.search_sort_db(db, opts) if not len(data): @@ -230,7 +233,7 @@ class EPUB_MOBI(CatalogPlugin): minimum_calibre_version = (0, 6, 34) author = 'Greg Riker' version = (0, 0, 1) - file_types = set(['epub']) + file_types = set(['epub','mobi']) cli_options = [Option('--catalog-title', default = 'My Catalog', @@ -446,8 +449,8 @@ class EPUB_MOBI(CatalogPlugin): ''' # Number of discrete steps to catalog creation - current_step = 0 - total_steps = 13 + current_step = 0.0 + total_steps = 13.0 # Used to xlate pubdate to friendly format MONTHS = ['January', 'February','March','April','May','June', @@ -498,7 +501,7 @@ class EPUB_MOBI(CatalogPlugin): self.__playOrder = 1 self.__plugin = plugin self.__plugin_path = opts.plugin_path - self.__progressInt = 0 + self.__progressInt = 0.0 self.__progressString = '' self.__reporter = notification self.__stylesheet = stylesheet @@ -751,14 +754,11 @@ class EPUB_MOBI(CatalogPlugin): search_terms.append("tag:%s" % tag) search_phrase = "not (%s)" % " or ".join(search_terms) - # Allow for no search_text - if self.opts.search_text: - self.opts.search_text = self.opts.search_text + " " + search_phrase - else: + # If a list of ids are provided, don't use search_text + if self.opts.ids: self.opts.search_text = search_phrase - - if self.verbose and False: - print "self.opts.search_text: %s" % self.opts.search_text + else: + self.opts.search_text = self.opts.search_text + " " + search_phrase # Fetch the database as a dictionary data = self.plugin.search_sort_db(self.db, self.opts) @@ -807,7 +807,7 @@ class EPUB_MOBI(CatalogPlugin): # Re-sort based on title_sort self.booksByTitle = sorted(titles, - key=lambda x:(x['title_sort'], x['title_sort'])) + key=lambda x:(x['title_sort'].upper(), x['title_sort'].upper())) def fetchBooksByAuthor(self): # Generate a list of titles sorted by author from the database @@ -815,23 +815,37 @@ class EPUB_MOBI(CatalogPlugin): if self.verbose: print self.updateProgressFullStep("fetchBooksByAuthor()") + # Sort titles based on upper case authors self.booksByAuthor = sorted(self.booksByTitle, - key=lambda x:(x['author_sort'], x['author_sort'])) + key=lambda x:(x['author_sort'].upper(), x['author_sort'].upper())) - # Search_text already initialized - # Get the database sorted by author_sort - self.opts.sort_by = 'author_sort' - data = self.plugin.search_sort_db(self.db, self.opts) + if True: + # Build the unique_authors set from existing data + authors = [(record['author'], record['author_sort']) for record in self.booksByAuthor] + else: + # Search_text already initialized + # Get the database sorted by author_sort + self.opts.sort_by = 'author_sort' + data = self.plugin.search_sort_db(self.db, self.opts) - # Build the unique_authors set - authors = [] - for record in data: - # There may be multiple authors - author_list = [] - for author in record['authors']: - author_list.append(author) - authors_concatenated = ", ".join(author_list) - authors.append((authors_concatenated, record['author_sort'])) + # GwR diagnostic: show sorted order + print "self.booksByAuthor in sort order:" + for book in self.booksByAuthor: + print "%s %s" % (book['author_sort'], book['title']) + print "data set in sort order:" + for book in data: + print "%s %s" % (book['author_sort'], book['title']) + + # Build the unique_authors set + authors = [] + for record in data: + # There may be multiple authors + author_list = [] + for author in record['authors']: + author_list.append(author) + authors_concatenated = ", ".join(author_list) + authors.append((authors_concatenated, record['author_sort'])) + # authors[] contains a list of all book authors, with multiple entries for multiple books by author # unique_authors : (([0]:friendly [1]:sort [2]:book_count)) @@ -860,7 +874,7 @@ class EPUB_MOBI(CatalogPlugin): unique_authors.append((current_author[0], current_author[1], books_by_current_author)) - if self.verbose and False: + if False and self.verbose: print "\nget_books_by_author(): %d unique authors" % len(unique_authors) for author in unique_authors[0:3]: print "%s" % author[0] @@ -880,7 +894,7 @@ class EPUB_MOBI(CatalogPlugin): print "%3s: %s - %s" % (title['id'], title['title'], title['author']) self.updateProgressMicroStep("generating book descriptions ...", - 100*title_num/len(self.booksByTitle)) + float(title_num*100/len(self.booksByTitle))/100) # Generate the header soup = self.generateHTMLDescriptionHeader("%s" % title['title']) @@ -1059,15 +1073,15 @@ class EPUB_MOBI(CatalogPlugin): # Loop through the books by title for book in self.booksByTitle: - if book['title_sort'][0] != current_letter : + if book['title_sort'][0].upper() != current_letter : # Start a new letter - current_letter = book['title_sort'][0] + current_letter = book['title_sort'][0].upper() pIndexTag = Tag(soup, "p") pIndexTag['class'] = "letter_index" aTag = Tag(soup, "a") - aTag['name'] = "%stitles" % book['title_sort'][0] + aTag['name'] = "%stitles" % book['title_sort'][0].upper() pIndexTag.insert(0,aTag) - pIndexTag.insert(1,NavigableString(book['title_sort'][0])) + pIndexTag.insert(1,NavigableString(book['title_sort'][0].upper())) divTag.insert(dtc,pIndexTag) dtc += 1 @@ -1714,6 +1728,7 @@ class EPUB_MOBI(CatalogPlugin): books_by_letter = [] if single_article_per_section: # Create a single article for all books in this section + # THIS CODE NEEDS TO BE REVIEWED FOR .upper() single_list = [] for book in self.booksByTitle: single_list.append(book) @@ -1726,19 +1741,19 @@ class EPUB_MOBI(CatalogPlugin): else: # Loop over the titles, find start of each letter, add description_preview_count books - current_letter = self.booksByTitle[0]['title_sort'][0] + current_letter = self.booksByTitle[0]['title_sort'][0].upper() title_letters = [current_letter] current_book_list = [] current_book = "" for book in self.booksByTitle: - if book['title_sort'][0] != current_letter: + if book['title_sort'][0].upper() != current_letter: # Save the old list book_list = " • ".join(current_book_list) short_description = self.generateShortDescription(self.formatNCXText(book_list)) books_by_letter.append(short_description) # Start the new list - current_letter = book['title_sort'][0] + current_letter = book['title_sort'][0].upper() title_letters.append(current_letter) current_book = book['title'] current_book_list = [book['title']] @@ -1827,7 +1842,8 @@ class EPUB_MOBI(CatalogPlugin): if single_article_per_section: # Create a single article for all authors in this section - + # THIS CODE NEEDS TO BE REVIEWED FOR .upper() + # Build a formatted author range for article preview single_list = [] for author in self.authors: @@ -1844,7 +1860,7 @@ class EPUB_MOBI(CatalogPlugin): # Loop over the sorted_authors list, find start of each letter, add description_preview_count artists # sorted_authors[0]:friendly [1]:author_sort [2]:book_count master_author_list = [] - current_letter = self.authors[0][1][0] + current_letter = self.authors[0][1][0].upper() current_author_list = [] for author in self.authors: if author[1][0] != current_letter: @@ -1857,7 +1873,7 @@ class EPUB_MOBI(CatalogPlugin): master_author_list.append((author_list, current_letter)) # Start the new list - current_letter = author[1][0] + current_letter = author[1][0].upper() current_author_list = [author[0]] else: if len(current_author_list) < self.descriptionClip: @@ -1875,7 +1891,7 @@ class EPUB_MOBI(CatalogPlugin): for authors in master_author_list: navPointByLetterTag = Tag(soup, 'navPoint') navPointByLetterTag['class'] = "article" - navPointByLetterTag['id'] = "%sauthors-ID" % (authors[1]) + navPointByLetterTag['id'] = "%sauthors-ID" % (authors[1].upper()) navPointTag['playOrder'] = self.playOrder self.playOrder += 1 navLabelTag = Tag(soup, 'navLabel') @@ -1883,7 +1899,7 @@ class EPUB_MOBI(CatalogPlugin): if single_article_per_section: textTag.insert(0, NavigableString("All books sorted by author")) else: - textTag.insert(0, NavigableString("Authors beginning with '%s'" % (authors[1]))) + textTag.insert(0, NavigableString("Authors beginning with '%s'" % (authors[1].upper()))) navLabelTag.insert(0, textTag) navPointByLetterTag.insert(0,navLabelTag) contentTag = Tag(soup, 'content') @@ -1891,7 +1907,7 @@ class EPUB_MOBI(CatalogPlugin): if single_article_per_section: contentTag['src'] = "%s#byauthor" % HTML_file else: - contentTag['src'] = "%s#%sauthors" % (HTML_file, authors[1]) + contentTag['src'] = "%s#%sauthors" % (HTML_file, authors[1].upper()) navPointByLetterTag.insert(1,contentTag) cmTag = Tag(soup, '%s' % 'mbp:meta' if self.generateForMobigen else 'calibre:meta') @@ -2509,16 +2525,18 @@ class EPUB_MOBI(CatalogPlugin): self.current_step += 1 self.progressString = description - self.progressInt = ((self.current_step-1)*100)/self.total_steps + self.progressInt = float((self.current_step-1)/self.total_steps) self.reporter(self.progressInt/100., self.progressString) - return "%d%% %s" % (self.progressInt, self.progressString) + return "%.2f%% %s" % (self.progressInt, self.progressString) def updateProgressMicroStep(self, description, micro_step_pct): step_range = 100/self.total_steps self.progressString = description - self.progressInt = ((self.current_step-1)*100)/self.total_steps + (micro_step_pct*step_range)/100 + coarse_progress = float((self.current_step-1)/self.total_steps) + fine_progress = float((micro_step_pct*step_range)/100) + self.progressInt = coarse_progress + fine_progress self.reporter(self.progressInt/100., self.progressString) - return "%d%% %s" % (self.progressInt, self.progressString) + return "%.2f%% %s" % (self.progressInt, self.progressString) def run(self, path_to_output, opts, db, notification=DummyReporter()): from calibre.utils.logging import Log @@ -2528,23 +2546,24 @@ class EPUB_MOBI(CatalogPlugin): opts.fmt = self.fmt = path_to_output.rpartition('.')[2] # Add local options - opts.creator = "Calibre" + opts.creator = "calibre" opts.dbs_fname = "CatalogSnapshot.dat" opts.descriptionClip = 250 opts.basename = "Catalog" opts.plugin_path = self.plugin_path if opts.verbose: + opts_dict = vars(opts) log("%s:run" % self.name) log(" path_to_output: %s" % path_to_output) log(" Output format: %s" % self.fmt) - + log(" Book count: %d" % len(opts_dict['ids'])) # Display opts - opts_dict = vars(opts) keys = opts_dict.keys() keys.sort() log(" opts:") for key in keys: + if key == 'ids': continue log(" %s: %s" % (key, opts_dict[key])) # Launch the Catalog builder From 74a4e630fcecde5c9686e595f50985435b5367cc Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 23 Jan 2010 08:05:30 -0700 Subject: [PATCH 10/25] New recipe for The National Review Online by Walt Anthony --- .../images/news/nationalreviewonline.png | Bin 0 -> 815 bytes resources/recipes/nationalreviewonline.recipe | 50 ++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 resources/images/news/nationalreviewonline.png create mode 100644 resources/recipes/nationalreviewonline.recipe diff --git a/resources/images/news/nationalreviewonline.png b/resources/images/news/nationalreviewonline.png new file mode 100644 index 0000000000000000000000000000000000000000..9070b3c71dc31f50a3f98a029524a94bc682185a GIT binary patch literal 815 zcmV+~1JL}5P)kzTH$m6|3@fdMfV-aJex4)-x z{`?1d9vI&}$h|x7ByJ{rdwQ8H&C#Bo3Wr~qp|8J}xY=aKJ!3>s#MrLwG#fEf`zF}6 zV+)g$<2*h!N|q%&@z@Zrzchx`fTl@Gsc4yb=4ndh5^)^UZf7(bIhQV9W8wM=)oL$8 z!&N^0{1jiz{>JflzGrl6iM@L&XrbUackTx+{CJ6H56w_6mk0#bl9cJ`X&Q0H`Jb-R zN?^5-P>d|~C+w?jl*Lgmy%2;=aq8wrMUe z-|CD}<1v{e69Z8KWDB6GQ|N?Q}p@fzX)+keooy z;O6c{egBQ;J`m)8_=;>qI{X7F+`bioCnxzxLI`1Qo@2*PoP7S~twxu3KB%*Zc3kIg tyV0n}s6~yHZQF+H2cH^vcj^H?{u?wQ4K}ND5sCl+002ovPDHLkV1hdQbY}nn literal 0 HcmV?d00001 diff --git a/resources/recipes/nationalreviewonline.recipe b/resources/recipes/nationalreviewonline.recipe new file mode 100644 index 0000000000..5f002019d9 --- /dev/null +++ b/resources/recipes/nationalreviewonline.recipe @@ -0,0 +1,50 @@ +__license__ = 'GPL v3' +__copyright__ = '2010, Walt Anthony ' +''' +www.nationalreview.com +''' + +from calibre.web.feeds.news import BasicNewsRecipe + +class NRO(BasicNewsRecipe): + title = u'National Review Online' + __author__ = 'Walt Anthony' + description = "National Review is America's most widely read and influential magazine and web site for Republican/conservative news, commentary, and opinion." + publisher = 'National Review, Inc.' + category = 'news, politics, USA' + oldest_article = 3 + max_articles_per_feed = 100 + summary_length = 150 + language = 'en' + encoding = 'utf-8' + use_embedded_content = True + remove_javascript = True + + + conversion_options = { + 'comment' : description + , 'tags' : category + , 'publisher' : publisher + , 'language' : language + } + + remove_tags = [ + dict(name=['embed','object','iframe']), + + ] + + feeds = [ + + (u'National Review', u'http://www.nationalreview.com/index.xml'), + (u'The Corner', u'http://corner.nationalreview.com/corner.xml'), + (u'The Agenda', u'http://agenda.nationalreview.com/agenda.xml'), + (u'Bench Memos', u'http://bench.nationalreview.com/bench.xml'), + (u'Campaign Spot', u'http://campaignspot.nationalreview.com/campaignspot.xml'), + (u'Critical Care', u'http://healthcare.nationalreview.com/healthcare.xml'), + (u'Doctor, Doctor', u'http://www.nationalreview.com/doctor/doctor.xml'), + (u"Kudlow's Money Politic$", u'http://kudlow.nationalreview.com/kudlow.xml'), + (u'Media Blog', u'http://media.nationalreview.com/media.xml'), + (u'Phi Beta Cons', u'http://phibetacons.nationalreview.com/phibetacons.xml'), + (u'Planet Gore', u'http://planetgore.nationalreview.com/planetgore.xml') + + ] From 0159adc585344176bcba76b8ed21935fada27aad Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 23 Jan 2010 08:11:28 -0700 Subject: [PATCH 11/25] Fix Barrons to work with new get_article_url --- resources/recipes/barrons.recipe | 3 +++ 1 file changed, 3 insertions(+) diff --git a/resources/recipes/barrons.recipe b/resources/recipes/barrons.recipe index 8106243cc0..9d79aed728 100644 --- a/resources/recipes/barrons.recipe +++ b/resources/recipes/barrons.recipe @@ -98,6 +98,9 @@ class Barrons(BasicNewsRecipe): ('Funds/Q&A', 'http://online.barrons.com/xml/rss/3_7519.xml'), ] + def get_article_url(self, article): + return article.get('link', None) + def get_cover_url(self): cover_url = None From 065a091c23c9201c439914f7b9c3344a64d419a6 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 23 Jan 2010 08:35:33 -0700 Subject: [PATCH 12/25] New recipe for ionline by Darko Miletic --- resources/images/news/ionline_pt.png | Bin 0 -> 647 bytes resources/recipes/ionline_pt.recipe | 58 +++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 resources/images/news/ionline_pt.png create mode 100644 resources/recipes/ionline_pt.recipe diff --git a/resources/images/news/ionline_pt.png b/resources/images/news/ionline_pt.png new file mode 100644 index 0000000000000000000000000000000000000000..f66d4aa797fd946da7e25c539cefa352732d932f GIT binary patch literal 647 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b zK-vS0-A-oPfdtD69Mgd`SU*F|v9*U87#KHrx;TbdoPIlTZ&pa5z|nf+|NramtkLV- z;gO_}sZ_?vA-3|((eMr1J~8I#UOC3T;j7{np{;@&O%oJ70s;ifH)qFue|FFM_@i~V zZr-R$=(22|X)OQkNAlA2$5NHd6AiPTa871i^!=0Izi*-!-%j$=I@LYB^RBkZ&husW zPxv1haWOFvwwdnx931tQwP`6rk8u4Z`gPC->Qip*?cV8f)rA9 zm@J>HQZiSa=lE_%`G%WrIFQlptJIcla#(QgWVRX3!NIXNl-XF7 z1Sa^JZYYVHG-L6mme1BY>+T*o@#FjYBd4@JzutavrfvpPfstn8(y})$)i#ZH5d8Vh_nEVqWOv@Ze9pf${h~vE-+4x0M5>m!MwFx^mZVxG7o`Fz1|tJQ16>0{T_fWV z0}Cr-BP&xAT?2C~1A~O9d<7H@x%nxXX_Y7%EUgTUt&D;CK^i>eKNbNsFnGH9xvX Date: Sat, 23 Jan 2010 08:46:10 -0700 Subject: [PATCH 13/25] Fix CLI bug with opts.search_text = None --- src/calibre/library/catalog.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/calibre/library/catalog.py b/src/calibre/library/catalog.py index 8a5072d622..a8755cf15b 100644 --- a/src/calibre/library/catalog.py +++ b/src/calibre/library/catalog.py @@ -758,7 +758,10 @@ class EPUB_MOBI(CatalogPlugin): if self.opts.ids: self.opts.search_text = search_phrase else: - self.opts.search_text = self.opts.search_text + " " + search_phrase + if self.opts.search_text: + self.opts.search_text += " " + search_phrase + else: + self.opts.search_text = search_phrase # Fetch the database as a dictionary data = self.plugin.search_sort_db(self.db, self.opts) From 916a780ebfed7a66e1e6dd3dcfb23e8ac529a2c2 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 23 Jan 2010 08:54:47 -0700 Subject: [PATCH 14/25] Save templates: Handle user specifying author instead of authors --- src/calibre/library/save_to_disk.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/calibre/library/save_to_disk.py b/src/calibre/library/save_to_disk.py index 5076f10d86..0404289cb3 100644 --- a/src/calibre/library/save_to_disk.py +++ b/src/calibre/library/save_to_disk.py @@ -112,6 +112,7 @@ def get_components(template, mi, id, timefmt='%b %Y', length=250, format_args['title'] = mi.title if mi.authors: format_args['authors'] = mi.format_authors() + format_args['author'] = format_args['authors'] if mi.author_sort: format_args['author_sort'] = mi.author_sort if mi.tags: From 20d7986126be326e29c655410220f23c826dffd4 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 23 Jan 2010 08:56:37 -0700 Subject: [PATCH 15/25] New recipe for HotAir by Walt Anthony --- resources/images/news/hotair.png | Bin 0 -> 363 bytes resources/recipes/hotair.recipe | 41 +++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 resources/images/news/hotair.png create mode 100644 resources/recipes/hotair.recipe diff --git a/resources/images/news/hotair.png b/resources/images/news/hotair.png new file mode 100644 index 0000000000000000000000000000000000000000..f6b391ce3fe6bf0d574e594eb92461de359897f1 GIT binary patch literal 363 zcmV-x0hIoUP)J#NB45Jq3plXNID6-8PrM?lI6_6oiTLTM;mrZp7}1>yow z2w*n* zAK+s=PJ?c@yhtjnuavAjPXt7!Q)|s(3B6u=4hF|b*lNwiXheONSS*eM#6iGyKB;xF z(57pXB(iawRJ-xm^F%yPBuO&0R=~GXndZp2ZI}f>G#qA{A3;`s?s-6A22rQ8kDq|L z@iHp_-skgu`~qA86X0`~Y&5C?KftSr&w)4K88`!Q-NS&UQrrPwz!h*0G!1OqZWlG= zhqw$w@f}BekQl@_8+d57tY6u>#$_1Ft?SB-0rZuU&3bJG`~sG7Wa@9Z2J!#^002ov JPDHLkV1n%7lCuB+ literal 0 HcmV?d00001 diff --git a/resources/recipes/hotair.recipe b/resources/recipes/hotair.recipe new file mode 100644 index 0000000000..96ba213b94 --- /dev/null +++ b/resources/recipes/hotair.recipe @@ -0,0 +1,41 @@ +__license__ = 'GPL v3' +__copyright__ = '2010, Walt Anthony ' +''' +www.hotair.com +''' + +from calibre.web.feeds.news import BasicNewsRecipe + +class hotair(BasicNewsRecipe): + title = u'Hot Air' + __author__ = 'Walt Anthony' + description = "The world's first, full-service conservative Internet broadcast network" + publisher = 'Hot Air' + category = 'news, politics, USA' + oldest_article = 3 + max_articles_per_feed = 100 + summary_length = 150 + language = 'en' + encoding = 'utf-8' + use_embedded_content = False + remove_javascript = True + + + conversion_options = { + 'comment' : description + , 'tags' : category + , 'publisher' : publisher + , 'language' : language + } + + + + + keep_only_tags = [dict(name='div', attrs={'id':'page-post'})] + + remove_tags = [dict(name=['iframe', 'small', 'embed', 'object','link','script','form'])] + + feeds = [ + ('Hot Air', 'http://feeds.feedburner.com/hotair/main'), + ('The Greenroom', 'http://feeds2.feedburner.com/hotair/greenroom') + ] From 57d3d606b10b764d209c056500e5c9eecab9e486 Mon Sep 17 00:00:00 2001 From: GRiker Date: Sat, 23 Jan 2010 09:03:29 -0700 Subject: [PATCH 16/25] Added 'Catalog' to default exclude_tags --- src/calibre/gui2/catalog/catalog_epub_mobi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/gui2/catalog/catalog_epub_mobi.py b/src/calibre/gui2/catalog/catalog_epub_mobi.py index 841ba5f6ad..50072451a0 100644 --- a/src/calibre/gui2/catalog/catalog_epub_mobi.py +++ b/src/calibre/gui2/catalog/catalog_epub_mobi.py @@ -17,7 +17,7 @@ class PluginWidget(QWidget,Ui_Form): TITLE = _('E-book Options') HELP = _('Options specific to')+' EPUB/MOBI '+_('output') OPTION_FIELDS = [('exclude_genre','\[[\w ]*\]'), - ('exclude_tags','~'), + ('exclude_tags','~,Catalog'), ('read_tag','+'), ('note_tag','*')] From b16465c62089d12c201a572b38be44fa0e64ef36 Mon Sep 17 00:00:00 2001 From: GRiker Date: Sat, 23 Jan 2010 09:20:29 -0700 Subject: [PATCH 17/25] Added 'Catalog' to default exclude_tags --- src/calibre/library/catalog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/library/catalog.py b/src/calibre/library/catalog.py index a459653cea..d65c8cb5f9 100644 --- a/src/calibre/library/catalog.py +++ b/src/calibre/library/catalog.py @@ -247,7 +247,7 @@ class EPUB_MOBI(CatalogPlugin): help=_("Regex describing tags to exclude as genres.\n" "Default: '%default' excludes bracketed tags, e.g. '[]'\n" "Applies to: ePub, MOBI output formats")), Option('--exclude-tags', - default='~', + default='~,Catalog', dest='exclude_tags', help=_("Comma-separated list of tag words indicating book should be excluded from output. Case-insensitive.\n" "--exclude-tags=skip will match 'skip this book' and 'Skip will like this'.\n" From ee5a5789dd6685315083c70d3f3a4692c9caa695 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 23 Jan 2010 09:23:15 -0700 Subject: [PATCH 18/25] Greensboro news and record by Walt Anthony --- .../news/greensboro_news_and_record.png | Bin 0 -> 480 bytes .../recipes/greensboro_news_and_record.recipe | 54 ++++++++++++++++++ src/calibre/ebooks/pdf/reflow.py | 21 +++++-- 3 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 resources/images/news/greensboro_news_and_record.png create mode 100644 resources/recipes/greensboro_news_and_record.recipe diff --git a/resources/images/news/greensboro_news_and_record.png b/resources/images/news/greensboro_news_and_record.png new file mode 100644 index 0000000000000000000000000000000000000000..91097cd15b007e73cd59c4b5640ba9bf1c2f47a4 GIT binary patch literal 480 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b zK-vS0-A-oPfdtD69Mgd`SU*F|v9*U87#KM{T^vI!PG6mLF!!*6MC*Px*#pvBZXQs! zU{+WvY?9h|M7=MtZ_XUf0wYHyLkHU?^A)=rtsSdRI6FHX zGdsX1(U|%rk;UL#m;>{a0}BGP?koN(V2W^&&sxCF^kRC|96H({O${wy;^5~ z$(r+*?OvnyhAulEhJIo3y$tfN&V+LbRxp_zNdK~MewCBlmFQE-(W`cDEn2_ahnZz3 z)A9HNYYVr{U`>gA`Ceh}f%BR#S`V#iP}_d&?RC}M-p#XlY#6d1ziG9<&M&(=>TS}a z^Sgi{q*~${QIe8al4_M)lnSI6j0_A7bPWu3jf_JKEUk Date: Sat, 23 Jan 2010 09:31:46 -0700 Subject: [PATCH 19/25] ... --- src/calibre/gui2/device.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/gui2/device.py b/src/calibre/gui2/device.py index 72229f6c19..5a977b37a6 100644 --- a/src/calibre/gui2/device.py +++ b/src/calibre/gui2/device.py @@ -932,7 +932,7 @@ class DeviceGUI(object): if isinstance(job.exception, FreeSpaceError): where = 'in main memory.' if 'memory' in str(job.exception) \ else 'on the storage card.' - titles = '\n'.join(['

  • '+mi['title']+'
  • ' \ + titles = '\n'.join(['
  • '+mi.title+'
  • ' \ for mi in metadata]) d = error_dialog(self, _('No space on device'), _('

    Cannot upload books to device there ' From f525ec57d6f3729ee600b90229c5fda22ed39564 Mon Sep 17 00:00:00 2001 From: GRiker Date: Sat, 23 Jan 2010 09:46:02 -0700 Subject: [PATCH 20/25] Experiment with gc --- src/calibre/library/catalog.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/calibre/library/catalog.py b/src/calibre/library/catalog.py index d65c8cb5f9..a099af440a 100644 --- a/src/calibre/library/catalog.py +++ b/src/calibre/library/catalog.py @@ -730,7 +730,6 @@ class EPUB_MOBI(CatalogPlugin): shutil.copy(os.path.join(catalog_resources,file[1]), os.path.join(self.catalogPath, file[0])) - def fetchBooksByTitle(self): if self.verbose: @@ -2542,11 +2541,14 @@ class EPUB_MOBI(CatalogPlugin): return "%.2f%% %s" % (self.progressInt, self.progressString) def run(self, path_to_output, opts, db, notification=DummyReporter()): + import gc from calibre.utils.logging import Log - self.opts = opts + + gc.set_debug(gc.DEBUG_LEAK) log = Log() opts.fmt = self.fmt = path_to_output.rpartition('.')[2] + self.opts = opts # Add local options opts.creator = "calibre" @@ -2592,3 +2594,4 @@ class EPUB_MOBI(CatalogPlugin): plumber.run() + print gc.garbage From 6e1fc23c47ebd487bd926049705cc82e8e0e4a46 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 23 Jan 2010 10:58:00 -0700 Subject: [PATCH 21/25] Improved recipe for Wired Magazine --- resources/recipes/wired.recipe | 123 +++++++++++++++++++++++-------- src/calibre/ebooks/pdf/reflow.py | 24 ++++++ 2 files changed, 116 insertions(+), 31 deletions(-) diff --git a/resources/recipes/wired.recipe b/resources/recipes/wired.recipe index fcc2494850..e7395a9ada 100644 --- a/resources/recipes/wired.recipe +++ b/resources/recipes/wired.recipe @@ -1,44 +1,105 @@ -#!/usr/bin/env python + __license__ = 'GPL v3' -__docformat__ = 'restructuredtext en' - +__copyright__ = '2010, Darko Miletic ' +''' +www.wired.com +''' +import re +from calibre import strftime from calibre.web.feeds.news import BasicNewsRecipe class Wired(BasicNewsRecipe): + title = 'Wired Magazine' + __author__ = 'Darko Miletic' + description = 'Gaming news' + publisher = 'Conde Nast Digital' + category = 'news, games, IT, gadgets' + oldest_article = 32 + max_articles_per_feed = 100 + no_stylesheets = True + encoding = 'utf-8' + use_embedded_content = False + language = 'en' + extra_css = ' body{font-family: sans-serif} .entryDescription li {display: inline; list-style-type: none} ' + index = 'http://www.wired.com/magazine/' - title = 'Wired.com' - __author__ = 'Kovid Goyal' - description = 'Technology news' - timefmt = ' [%Y%b%d %H%M]' - language = 'en' + preprocess_regexps = [(re.compile(r'', re.DOTALL|re.IGNORECASE),lambda match: '')] + conversion_options = { + 'comment' : description + , 'tags' : category + , 'publisher' : publisher + , 'language' : language + } - no_stylesheets = True + keep_only_tags = [dict(name='div', attrs={'class':'post'})] + remove_tags_after = dict(name='div', attrs={'class':'tweetmeme_button'}) + remove_tags = [ + dict(name=['object','embed','iframe','link']) + ,dict(name='div', attrs={'class':['podcast_storyboard','tweetmeme_button']}) + ] - remove_tags_before = dict(name='div', id='content') - remove_tags = [dict(id=['social_tools', 'outerWrapper', 'sidebar', - 'footer', 'advertisement', 'blog_subscription_unit', - 'brightcove_component']), - {'class':'entryActions'}, - dict(name=['noscript', 'script'])] - feeds = [ - ('Top News', 'http://feeds.wired.com/wired/index'), - ('Culture', 'http://feeds.wired.com/wired/culture'), - ('Software', 'http://feeds.wired.com/wired/software'), - ('Mac', 'http://feeds.feedburner.com/cultofmac/bFow'), - ('Gadgets', 'http://feeds.wired.com/wired/gadgets'), - ('Cars', 'http://feeds.wired.com/wired/cars'), - ('Entertainment', 'http://feeds.wired.com/wired/entertainment'), - ('Gaming', 'http://feeds.wired.com/wired/gaming'), - ('Science', 'http://feeds.wired.com/wired/science'), - ('Med Tech', 'http://feeds.wired.com/wired/medtech'), - ('Politics', 'http://feeds.wired.com/wired/politics'), - ('Tech Biz', 'http://feeds.wired.com/wired/techbiz'), - ('Commentary', 'http://feeds.wired.com/wired/commentary'), - ] + #feeds = [(u'Articles' , u'http://www.wired.com/magazine/feed/' )] + + def parse_index(self): + totalfeeds = [] + + soup = self.index_to_soup(self.index) + features = soup.find('div',attrs={'id':'my-glider'}) + if features: + farticles = [] + for item in features.findAll('div',attrs={'class':'section'}): + divurl = item.find('div',attrs={'class':'feature-header'}) + divdesc = item.find('div',attrs={'class':'feature-text'}) + url = 'http://www.wired.com' + divurl.a['href'] + title = self.tag_to_string(divurl.a) + description = self.tag_to_string(divdesc) + date = strftime(self.timefmt) + farticles.append({ + 'title' :title + ,'date' :date + ,'url' :url + ,'description':description + }) + totalfeeds.append(('Featured Articles', farticles)) + #department feeds + departments = ['rants','start','test','play','found'] + dept = soup.find('div',attrs={'id':'magazine-departments'}) + if dept: + for ditem in departments: + darticles = [] + department = dept.find('div',attrs={'id':'department-'+ditem}) + if department: + for item in department.findAll('div'): + description = '' + feed_link = item.find('a') + if feed_link and feed_link.has_key('href'): + url = feed_link['href'] + title = self.tag_to_string(feed_link) + date = strftime(self.timefmt) + darticles.append({ + 'title' :title + ,'date' :date + ,'url' :url + ,'description':description + }) + totalfeeds.append((ditem.capitalize(), darticles)) + return totalfeeds + + def get_cover_url(self): + cover_url = None + soup = self.index_to_soup(self.index) + cover_item = soup.find('div',attrs={'class':'spread-image'}) + if cover_item: + cover_url = 'http://www.wired.com' + cover_item.a.img['src'] + return cover_url def print_version(self, url): - return url.replace('http://www.wired.com/', 'http://www.wired.com/print/') + return url.rstrip('/') + '/all/1' + def preprocess_html(self, soup): + for item in soup.findAll(style=True): + del item['style'] + return soup diff --git a/src/calibre/ebooks/pdf/reflow.py b/src/calibre/ebooks/pdf/reflow.py index 92a0ceebe1..3fce8a41f8 100644 --- a/src/calibre/ebooks/pdf/reflow.py +++ b/src/calibre/ebooks/pdf/reflow.py @@ -28,6 +28,7 @@ class Column(object): self.left = self.right = self.top = self.bottom = 0 self.width = self.height = 0 self.elements = [] + self.average_line_separation = 0 def add(self, elem): if elem in self.elements: return @@ -49,8 +50,17 @@ class Column(object): return elem.left > self.left - self.HFUZZ*self.width and \ elem.right < self.right + self.HFUZZ*self.width + def collect_stats(self): + if len(self.elements) > 1: + gaps = [self.elements[i+1].top - self.elements[i].bottom for i in + range(len(0, len(self.elements)-1))] + self.average_line_separation = sum(gaps)/len(gaps) + class Element(object): + def __init__(self): + self.starts_paragraph = False + def __eq__(self, other): return self.id == other.id @@ -60,6 +70,7 @@ class Element(object): class Image(Element): def __init__(self, img, opts, log, idc): + Element.__init__(self) self.opts, self.log = opts, log self.id = idc.next() self.top, self.left, self.width, self.height, self.iwidth, self.iheight = \ @@ -71,6 +82,7 @@ class Image(Element): class Text(Element): def __init__(self, text, font_map, opts, log, idc): + Element.__init__(self) self.id = idc.next() self.opts, self.log = opts, log self.font_map = font_map @@ -174,6 +186,12 @@ class Region(object): def is_empty(self): return len(self.elements) == 0 + def collect_stats(self): + for column in self.column: + column.collect_stats() + self.average_line_separation = sum([x.average_line_separation for x in + self.columns])/float(len(self.columns)) + class Page(object): @@ -298,6 +316,11 @@ class Page(object): x_interval.intersection(h_interval).width <= 0: yield y + def second_pass(self): + 'Locate paragraph boundaries in each column' + for region in self.regions: + region.collect_stats() + class PDFDocument(object): @@ -327,6 +350,7 @@ class PDFDocument(object): for page in self.pages: page.document_font_stats = self.font_size_stats page.first_pass() + page.second_pass() def collect_font_statistics(self): self.font_size_stats = {} From feb58a884650e0088cb51293cdf64180af09378b Mon Sep 17 00:00:00 2001 From: Kovid Goyal <kovid@kovidgoyal.net> Date: Sat, 23 Jan 2010 11:20:34 -0700 Subject: [PATCH 22/25] ... --- src/calibre/ebooks/pdf/reflow.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/calibre/ebooks/pdf/reflow.py b/src/calibre/ebooks/pdf/reflow.py index 3fce8a41f8..73178f5621 100644 --- a/src/calibre/ebooks/pdf/reflow.py +++ b/src/calibre/ebooks/pdf/reflow.py @@ -192,6 +192,16 @@ class Region(object): self.average_line_separation = sum([x.average_line_separation for x in self.columns])/float(len(self.columns)) + def __iter__(self): + for x in self.columns: + yield x + + def detect_paragraphs(self): + first = True + for col in self: + col.detect_paragraphs(self.average_line_separation, first) + first = False + class Page(object): @@ -203,6 +213,8 @@ class Page(object): # for them to be considered to be part of the same text fragment LINE_FACTOR = 0.4 + # Multiplies the average line height when determining row height + # of a particular element to detect columns. YFUZZ = 1.5 @@ -305,7 +317,7 @@ class Page(object): def find_elements_in_row_of(self, x): interval = Interval(x.top, - x.top + self.YFUZZ*(1+self.average_text_height)) + x.top + self.YFUZZ*(self.average_text_height)) h_interval = Interval(x.left, x.right) for y in self.elements[x.idx:x.idx+15]: if y is not x: @@ -320,6 +332,7 @@ class Page(object): 'Locate paragraph boundaries in each column' for region in self.regions: region.collect_stats() + region.detect_paragraphs() class PDFDocument(object): From 44129f0d1f083988e79e532d3cac637aac3fa141 Mon Sep 17 00:00:00 2001 From: Kovid Goyal <kovid@kovidgoyal.net> Date: Sat, 23 Jan 2010 11:53:24 -0700 Subject: [PATCH 23/25] Fix #4653 (Typo in metadata for new quick start guide) and strip img tags with src=# in epub output as they cause ADE to freeze --- src/calibre/ebooks/epub/output.py | 3 ++- src/calibre/gui2/ui.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/calibre/ebooks/epub/output.py b/src/calibre/ebooks/epub/output.py index bffc24ac91..8e9c9efea9 100644 --- a/src/calibre/ebooks/epub/output.py +++ b/src/calibre/ebooks/epub/output.py @@ -268,7 +268,8 @@ class EPUBOutput(OutputFormatPlugin): # remove <img> tags with empty src elements bad = [] for x in XPath('//h:img')(body): - if not x.get('src', '').strip(): + src = x.get('src', '').strip() + if src in ('', '#'): bad.append(x) for img in bad: img.getparent().remove(img) diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index b132e368ee..714b2c3a27 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -522,7 +522,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): from calibre.ebooks.metadata import MetaInformation mi = MetaInformation(_('Calibre Quick Start Guide'), ['John Schember']) mi.author_sort = 'Schember, John' - mi.comments = "A guide to get you up an running with calibre" + mi.comments = "A guide to get you up and running with calibre" mi.publisher = 'calibre' self.library_view.model().add_books([P('quick_start.epub')], ['epub'], [mi]) From f1d81044505a97529bdf36cbd02d29c1f04bfdbb Mon Sep 17 00:00:00 2001 From: Kovid Goyal <kovid@kovidgoyal.net> Date: Sat, 23 Jan 2010 14:55:28 -0700 Subject: [PATCH 24/25] New recipe for Neowin by Darko Miletic --- resources/images/news/neowin.png | Bin 0 -> 1068 bytes resources/recipes/neowin.recipe | 40 +++++++++++ src/calibre/ebooks/pdf/reflow.py | 110 ++++++++++++++++++------------- 3 files changed, 104 insertions(+), 46 deletions(-) create mode 100644 resources/images/news/neowin.png create mode 100644 resources/recipes/neowin.recipe diff --git a/resources/images/news/neowin.png b/resources/images/news/neowin.png new file mode 100644 index 0000000000000000000000000000000000000000..5aee949c0bb7e844b4b47169f3302776087be6d4 GIT binary patch literal 1068 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b zK-vS0-A-oPfdtD69Mgd`SU*F|v9*U87??vnT^vI!PRCA;&WJ8$I9C6^*z=sH-(<Di z%S&>1<?T(`x;X1%WJ{O%9W@KrE`KE+7YRF_gW~P}zm$Rn;<=3W@U;7PnP0Q}q3~#z zw|Bbsqgy_2b9ODu-2A1isA|&WIs5rjlYiOP^4ss5E<gW4{lp-?8@u0WcWXy0XRE5O z)#&mtYn`?`XriaF#2+UP!)kr~cOv({Z@oSH-0t|l7WG+=9{Cz?&w3pCnt`QRD^@lz zu42>fUzd#8k2CH1H%;KsUTcM=R~q%}XP@tvtN$zAQ!wLL1+!D=_hYvF*9$jn&ux33 z{iyk}`|;q;7b^sk!Wj#+?^*9&XKqztaP+3JzR=5ePPsh`+m%<ewTks69G#t!>;2($ zPUFY<V)NEs{qvnML^Jh&x$x%aR=1K?WwO1<+x)`jf=?gA!G<;mMwTFr1uK5+JO9Cf zdwch6{<-$%X6v4WnZ@n>^SVeuj$3)Di`U7CcHNiHmw)`SQO@Z5_KQ<;R8m?mI4inn zoLcy=Y~7hVAz@+W@t4=dMOXQ(I%vyWC+jNM;I&`XBh4pGDA(t&;G<(somUU>z2&uP zo+-BPucMLec9S)!;@xl4G#GwZOqKc{A~H*NY73tsqjF*EvV|65cT%2Jbt-E*-nekl zWa>}*>%viM<HS8gHEr$Y-FnidEb*%IQ^BnT_gR=L3|M0KsvVD(_GGDD67T3Gzx@%X z?p2|vpV^t(Gxw$zKYYY>vEkI!KYY?NEtWP)v`e${GA#-bOcKBS(eaAr^w@7()vs-R zSCUbrSe^ai)*q>*F`R;i1>0BOn61~k==388<No7X5%1WZcC`yMWw{<Ll&P{>o2ff@ zi`~upiF41Sg`4JA&+cL~UEdeJHgMbOC!frM&$6liikT!<Vd|NAIIZ5D`S-20o4w-I zjK5#;ct0b&tia3lPu9$+qepeEb40gCoPIWQ_ogH5_t!tHN|3PHwXXO}=f3k*zm2A| zIMk)yjEU8+|NG5-dVg&Ey`>v9oemfXc5Pa|{axURe4{(*pYF|8&Y1OU^ZVcDmtLN0 zU4A|!Cf-!`x_$9Kr*BV=ES(dj^Y)Q9XG4=p5^F`thR}IcKO6mf7kqLvntAKzdFl5{ zUfpWvmYyoS|Nq{P9_tde{|f5b_Uyy0h0GgY_KAJ|+>q#d@AQ9e!=-83#i!gAfw@h! z#5JNMC9x#cD!C{XNHG{07#ipr80s1shZveznHpIcTId>>TNxOf*)TH!MMG|WN@iLm fiUw0F6H6;26Nm-@tBpT_8W=oX{an^LB{Ts5fE3tc literal 0 HcmV?d00001 diff --git a/resources/recipes/neowin.recipe b/resources/recipes/neowin.recipe new file mode 100644 index 0000000000..9f5a669a75 --- /dev/null +++ b/resources/recipes/neowin.recipe @@ -0,0 +1,40 @@ + +from calibre.web.feeds.news import BasicNewsRecipe + +class Neowin(BasicNewsRecipe): + title = u'Neowin.net' + oldest_article = 5 + language = 'en' + description = 'News from IT' + publisher = 'Neowin' + category = 'news, IT, Microsoft, Apple, hardware, software, games' + __author__ = 'Darko Miletic' + max_articles_per_feed = 100 + no_stylesheets = True + encoding = 'utf8' + + conversion_options = { + 'tags' : category + ,'language' : language + ,'comments' : description + ,'publisher' : publisher + } + + keep_only_tags = [dict(name='div', attrs={'id':'article'})] + remove_tags_after = dict(name='div', attrs={'id':'tag-bar'}) + + remove_tags = [ + dict(name=['base','object','link','iframe']) + ,dict(name='div', attrs={'id':'tag-bar'}) + ] + + feeds = [ + (u'Software' , u'http://www.neowin.net/news/rss/software' ) + ,(u'Gaming' , u'http://www.neowin.net/news/rss/gaming' ) + ,(u'Microsoft', u'http://www.neowin.net/news/rss/microsoft') + ,(u'Apple' , u'http://www.neowin.net/news/rss/apple' ) + ,(u'Editorial', u'http://www.neowin.net/news/rss/editorial') + ] + def image_url_processor(cls, baseurl, url): + return url + diff --git a/src/calibre/ebooks/pdf/reflow.py b/src/calibre/ebooks/pdf/reflow.py index 73178f5621..1a0e5e0dcb 100644 --- a/src/calibre/ebooks/pdf/reflow.py +++ b/src/calibre/ebooks/pdf/reflow.py @@ -18,48 +18,11 @@ class Font(object): self.color = spec.get('color') self.family = spec.get('family') -class Column(object): - - # A column contains an element is the element bulges out to - # the left or the right by at most HFUZZ*col width. - HFUZZ = 0.2 - - def __init__(self): - self.left = self.right = self.top = self.bottom = 0 - self.width = self.height = 0 - self.elements = [] - self.average_line_separation = 0 - - def add(self, elem): - if elem in self.elements: return - self.elements.append(elem) - self.elements.sort(cmp=lambda x,y:cmp(x.bottom,y.bottom)) - self.top = self.elements[0].top - self.bottom = self.elements[-1].bottom - self.left, self.right = sys.maxint, 0 - for x in self: - self.left = min(self.left, x.left) - self.right = max(self.right, x.right) - self.width, self.height = self.right-self.left, self.bottom-self.top - - def __iter__(self): - for x in self.elements: - yield x - - def contains(self, elem): - return elem.left > self.left - self.HFUZZ*self.width and \ - elem.right < self.right + self.HFUZZ*self.width - - def collect_stats(self): - if len(self.elements) > 1: - gaps = [self.elements[i+1].top - self.elements[i].bottom for i in - range(len(0, len(self.elements)-1))] - self.average_line_separation = sum(gaps)/len(gaps) - class Element(object): def __init__(self): - self.starts_paragraph = False + self.starts_block = None + self.block_style = None def __eq__(self, other): return self.id == other.id @@ -152,6 +115,61 @@ class Interval(object): def __hash__(self): return hash('(%f,%f)'%self.left, self.right) +class Column(object): + + # A column contains an element is the element bulges out to + # the left or the right by at most HFUZZ*col width. + HFUZZ = 0.2 + + + def __init__(self): + self.left = self.right = self.top = self.bottom = 0 + self.width = self.height = 0 + self.elements = [] + self.average_line_separation = 0 + + def add(self, elem): + if elem in self.elements: return + self.elements.append(elem) + self.elements.sort(cmp=lambda x,y:cmp(x.bottom,y.bottom)) + self.top = self.elements[0].top + self.bottom = self.elements[-1].bottom + self.left, self.right = sys.maxint, 0 + for x in self: + self.left = min(self.left, x.left) + self.right = max(self.right, x.right) + self.width, self.height = self.right-self.left, self.bottom-self.top + + def __iter__(self): + for x in self.elements: + yield x + + def contains(self, elem): + return elem.left > self.left - self.HFUZZ*self.width and \ + elem.right < self.right + self.HFUZZ*self.width + + def collect_stats(self): + if len(self.elements) > 1: + gaps = [self.elements[i+1].top - self.elements[i].bottom for i in + range(len(0, len(self.elements)-1))] + self.average_line_separation = sum(gaps)/len(gaps) + for i, elem in enumerate(self.elements): + left_margin = elem.left - self.left + elem.indent_fraction = left_margin/self.width + elem.width_fraction = elem.width/self.width + if i == 0: + elem.top_gap = None + else: + elem.top_gap = self.elements[i-1].bottom - elem.top + + def previous_element(self, idx): + if idx == 0: + return None + return self.elements[idx-1] + + + + class Region(object): def __init__(self): @@ -168,6 +186,7 @@ class Region(object): self.columns[i].add(elem) def contains(self, columns): + # TODO: handle unbalanced columns if not self.columns: return True if len(columns) != len(self.columns): @@ -187,7 +206,7 @@ class Region(object): return len(self.elements) == 0 def collect_stats(self): - for column in self.column: + for column in self.columns: column.collect_stats() self.average_line_separation = sum([x.average_line_separation for x in self.columns])/float(len(self.columns)) @@ -196,11 +215,10 @@ class Region(object): for x in self.columns: yield x - def detect_paragraphs(self): - first = True - for col in self: - col.detect_paragraphs(self.average_line_separation, first) - first = False + def linearize(self): + self.elements = [] + for x in self.columns: + self.elements.extend(x) class Page(object): @@ -332,7 +350,7 @@ class Page(object): 'Locate paragraph boundaries in each column' for region in self.regions: region.collect_stats() - region.detect_paragraphs() + region.linearize() class PDFDocument(object): From 839b5618cbe69d148e368b80304d6e35dbea1970 Mon Sep 17 00:00:00 2001 From: Kovid Goyal <kovid@kovidgoyal.net> Date: Sat, 23 Jan 2010 17:41:11 -0700 Subject: [PATCH 25/25] Improved recipe for Common Dreams --- resources/recipes/common_dreams.recipe | 32 +++++++++++++++++++++----- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/resources/recipes/common_dreams.recipe b/resources/recipes/common_dreams.recipe index b662cc3ee0..5443b5890b 100644 --- a/resources/recipes/common_dreams.recipe +++ b/resources/recipes/common_dreams.recipe @@ -2,17 +2,37 @@ from calibre.web.feeds.news import BasicNewsRecipe class CommonDreams(BasicNewsRecipe): + # Identify the recipe + title = u'Common Dreams' description = u'Progressive news and views' __author__ = u'XanthanGum' language = 'en' + + # Format the text + + extra_css = ''' + body{font-family:verdana,arial,helvetica,geneva,sans-serif ;} + h1{font-size: xx-large;} + h2{font-size: large;} + ''' + # Pick no article older than seven days and limit the number of articles per feed to 100 + oldest_article = 7 max_articles_per_feed = 100 - feeds = [ - (u'Common Dreams Headlines', - u'http://www.commondreams.org/feed/headlines_rss'), - (u'Common Dreams Views', u'http://www.commondreams.org/feed/views_rss'), - (u'Common Dreams Newswire', u'http://www.commondreams.org/feed/newswire_rss') - ] + # Remove everything before the article + + remove_tags_before = dict(name = 'div', attrs = {'id':'node-header'}) + + # Remove everything after the article + + remove_tags_after = dict(name = 'div', attrs = {'class':'copyright-info'}) + + # Identify the news feeds + + feeds = [(u'Headlines', u'http://www.commondreams.org/feed/headlines_rss'), + (u'Further News Articles', u'http://www.commondreams.org/feed/further_rss'), + (u'Views', u'http://www.commondreams.org/feed/views_rss'), + (u'Progressive Newswire', u'http://www.commondreams.org/feed/newswire_rss')]