From d7a124178c4ac36bcc61e4e40234fc025919744c Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 25 Apr 2011 10:49:07 -0600 Subject: [PATCH 01/14] ... --- src/calibre/gui2/book_details.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/calibre/gui2/book_details.py b/src/calibre/gui2/book_details.py index 2eefe3cb54..f1fd2c1575 100644 --- a/src/calibre/gui2/book_details.py +++ b/src/calibre/gui2/book_details.py @@ -23,7 +23,6 @@ from calibre.gui2 import (config, open_local_file, open_url, pixmap_to_data, gprefs) from calibre.utils.icu import sort_key - def render_html(mi, css, vertical, widget, all_fields=False): # {{{ table = render_data(mi, all_fields=all_fields, use_roman_numbers=config['use_roman_numerals_for_series_number']) @@ -121,7 +120,7 @@ def render_data(mi, use_roman_numbers=True, all_fields=False): continue val = prepare_string_for_xml(val) if metadata['datatype'] == 'series': - sidx = getattr(mi, field+'_index') + sidx = getattr(mi, field+'_index', None) if sidx is None: sidx = 1.0 val = _('Book %s of %s')%(fmt_sidx(sidx, From 90326b1baaba9e8b43c7131e006982fa19c0ad91 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 25 Apr 2011 11:01:21 -0600 Subject: [PATCH 02/14] ... --- src/calibre/gui2/book_details.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/gui2/book_details.py b/src/calibre/gui2/book_details.py index f1fd2c1575..6b15df9a76 100644 --- a/src/calibre/gui2/book_details.py +++ b/src/calibre/gui2/book_details.py @@ -120,7 +120,7 @@ def render_data(mi, use_roman_numbers=True, all_fields=False): continue val = prepare_string_for_xml(val) if metadata['datatype'] == 'series': - sidx = getattr(mi, field+'_index', None) + sidx = mi.get(field+'_index') if sidx is None: sidx = 1.0 val = _('Book %s of %s')%(fmt_sidx(sidx, From da057256123814a4c3b622a9fbfcbc2c6945ce43 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 25 Apr 2011 11:12:47 -0600 Subject: [PATCH 03/14] Small change to the API for medata source plugins. get_book_url must now return a tuple --- src/calibre/ebooks/metadata/sources/amazon.py | 2 +- src/calibre/ebooks/metadata/sources/base.py | 6 +++++- src/calibre/ebooks/metadata/sources/google.py | 2 +- src/calibre/ebooks/metadata/sources/identify.py | 7 +++---- src/calibre/gui2/metadata/single_download.py | 2 +- 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/calibre/ebooks/metadata/sources/amazon.py b/src/calibre/ebooks/metadata/sources/amazon.py index 24df68e51d..8483698e28 100644 --- a/src/calibre/ebooks/metadata/sources/amazon.py +++ b/src/calibre/ebooks/metadata/sources/amazon.py @@ -301,7 +301,7 @@ class Amazon(Source): if asin is None: asin = identifiers.get('asin', None) if asin: - return 'http://amzn.com/%s'%asin + return ('amazon', asin, 'http://amzn.com/%s'%asin) # }}} def create_query(self, log, title=None, authors=None, identifiers={}): # {{{ diff --git a/src/calibre/ebooks/metadata/sources/base.py b/src/calibre/ebooks/metadata/sources/base.py index eb0277bd3f..f386489fcd 100644 --- a/src/calibre/ebooks/metadata/sources/base.py +++ b/src/calibre/ebooks/metadata/sources/base.py @@ -374,7 +374,11 @@ class Source(Plugin): def get_book_url(self, identifiers): ''' - Return the URL for the book identified by identifiers at this source. + Return a 3-tuple or None. The 3-tuple is of the form: + (identifier_type, identifier_value, URL). + The URL is the URL for the book identified by identifiers at this + source. identifier_type, identifier_value specify the identifier + corresponding to the URL. This URL must be browseable to by a human using a browser. It is meant to provide a clickable link for the user to easily visit the books page at this source. diff --git a/src/calibre/ebooks/metadata/sources/google.py b/src/calibre/ebooks/metadata/sources/google.py index 4133d4d527..b479368bac 100644 --- a/src/calibre/ebooks/metadata/sources/google.py +++ b/src/calibre/ebooks/metadata/sources/google.py @@ -173,7 +173,7 @@ class GoogleBooks(Source): def get_book_url(self, identifiers): # {{{ goog = identifiers.get('google', None) if goog is not None: - return 'http://books.google.com/books?id=%s'%goog + return ('google', goog, 'http://books.google.com/books?id=%s'%goog) # }}} def create_query(self, log, title=None, authors=None, identifiers={}): # {{{ diff --git a/src/calibre/ebooks/metadata/sources/identify.py b/src/calibre/ebooks/metadata/sources/identify.py index 8771274f92..335d741fd2 100644 --- a/src/calibre/ebooks/metadata/sources/identify.py +++ b/src/calibre/ebooks/metadata/sources/identify.py @@ -438,14 +438,13 @@ def urls_from_identifiers(identifiers): # {{{ ans = [] for plugin in all_metadata_plugins(): try: - url = plugin.get_book_url(identifiers) - if url is not None: - ans.append((plugin.name, url)) + id_type, id_val, url = plugin.get_book_url(identifiers) + ans.append((plugin.name, id_type, id_val, url)) except: pass isbn = identifiers.get('isbn', None) if isbn: - ans.append((isbn, + ans.append((isbn, 'isbn', isbn, 'http://www.worldcat.org/search?q=bn%%3A%s&qt=advanced'%isbn)) return ans # }}} diff --git a/src/calibre/gui2/metadata/single_download.py b/src/calibre/gui2/metadata/single_download.py index 06ea8cf76a..cc89ef2259 100644 --- a/src/calibre/gui2/metadata/single_download.py +++ b/src/calibre/gui2/metadata/single_download.py @@ -253,7 +253,7 @@ class ResultsView(QTableView): # {{{ parts.append('') if book.identifiers: urls = urls_from_identifiers(book.identifiers) - ids = ['%s'%(url, name) for name, url in urls] + ids = ['%s'%(url, name) for name, ign, ign, url in urls] if ids: parts.append('
%s: %s

'%(_('See at'), ', '.join(ids))) if book.tags: From 262d1a9e931c120b290dca8195ebf7fd57abda0e Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 25 Apr 2011 11:33:26 -0600 Subject: [PATCH 04/14] Show identifiers in books details --- src/calibre/gui2/book_details.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/calibre/gui2/book_details.py b/src/calibre/gui2/book_details.py index 6b15df9a76..80d3c1636e 100644 --- a/src/calibre/gui2/book_details.py +++ b/src/calibre/gui2/book_details.py @@ -17,6 +17,7 @@ from calibre.gui2.dnd import (dnd_has_image, dnd_get_image, dnd_get_files, from calibre.ebooks import BOOK_EXTENSIONS from calibre.ebooks.metadata.book.base import (field_metadata, Metadata) from calibre.ebooks.metadata import fmt_sidx +from calibre.ebooks.metadata.sources.identify import urls_from_identifiers from calibre.constants import filesystem_encoding from calibre.library.comments import comments_to_html from calibre.gui2 import (config, open_local_file, open_url, pixmap_to_data, @@ -113,7 +114,12 @@ def render_data(mi, use_roman_numbers=True, all_fields=False): ans.append((field, u'%s%s'%(name, u', '.join(fmts)))) elif field == 'identifiers': - pass # TODO + urls = urls_from_identifiers(mi.identifiers) + links = [u'%s' % (url, id_typ, id_val, name) + for name, id_typ, id_val, url in urls] + links = u', '.join(links) + ans.append((field, u'%s%s'%( + _('Ids')+':', links))) else: val = mi.format_field(field)[-1] if val is None: @@ -288,6 +294,8 @@ class BookInfo(QWebView): def link_activated(self, link): self._link_clicked = True + if unicode(link.scheme()) in ('http', 'https'): + return open_url(link) link = unicode(link.toString()) self.link_clicked.emit(link) From e1c950b7bb883ae6ab00c84ff7cecc49b8b0524a Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 25 Apr 2011 11:42:56 -0600 Subject: [PATCH 05/14] Add support for DOI and arXiv identifiers --- src/calibre/ebooks/metadata/sources/identify.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/calibre/ebooks/metadata/sources/identify.py b/src/calibre/ebooks/metadata/sources/identify.py index 335d741fd2..fd71e650a0 100644 --- a/src/calibre/ebooks/metadata/sources/identify.py +++ b/src/calibre/ebooks/metadata/sources/identify.py @@ -435,6 +435,7 @@ def identify(log, abort, # {{{ # }}} def urls_from_identifiers(identifiers): # {{{ + identifiers = dict([(k.lower(), v) for k, v in identifiers.iteritems()]) ans = [] for plugin in all_metadata_plugins(): try: @@ -446,6 +447,14 @@ def urls_from_identifiers(identifiers): # {{{ if isbn: ans.append((isbn, 'isbn', isbn, 'http://www.worldcat.org/search?q=bn%%3A%s&qt=advanced'%isbn)) + doi = identifiers.get('doi', None) + if doi: + ans.append(('DOI', 'doi', doi, + 'http://dx.doi.org/'+doi)) + arxiv = identifiers.get('arxiv', None) + if arxiv: + ans.append(('arXiv', 'arxiv', arxiv, + 'http://arxiv.org/abs/'+arxiv)) return ans # }}} From 31341a16aad3c25439b3c3d076bcc01d8a51b050 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 25 Apr 2011 13:54:32 -0600 Subject: [PATCH 06/14] ... --- src/calibre/ebooks/metadata/sources/overdrive.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/calibre/ebooks/metadata/sources/overdrive.py b/src/calibre/ebooks/metadata/sources/overdrive.py index 759da45610..ad570a8b28 100755 --- a/src/calibre/ebooks/metadata/sources/overdrive.py +++ b/src/calibre/ebooks/metadata/sources/overdrive.py @@ -265,7 +265,7 @@ class OverDrive(Source): if creators: creators = creators.split(', ') # if an exact match in a preferred format occurs - if ((author and creators[0] == author[0]) or (not author and not creators)) and od_title.lower() == title.lower() and int(formatid) in [1, 50, 410, 900] and thumbimage: + if ((author and creators and creators[0] == author[0]) or (not author and not creators)) and od_title.lower() == title.lower() and int(formatid) in [1, 50, 410, 900] and thumbimage: return self.format_results(reserveid, od_title, subtitle, series, publisher, creators, thumbimage, worldcatlink, formatid) else: @@ -291,7 +291,7 @@ class OverDrive(Source): close_matches.insert(0, self.format_results(reserveid, od_title, subtitle, series, publisher, creators, thumbimage, worldcatlink, formatid)) else: close_matches.append(self.format_results(reserveid, od_title, subtitle, series, publisher, creators, thumbimage, worldcatlink, formatid)) - + elif close_title_match and close_author_match and int(formatid) in [1, 50, 410, 900]: close_matches.append(self.format_results(reserveid, od_title, subtitle, series, publisher, creators, thumbimage, worldcatlink, formatid)) From 1ec25e442bcae43a1431064e3616681e5dd36930 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 25 Apr 2011 13:58:38 -0600 Subject: [PATCH 07/14] Spruce up the confirm delete dialog --- .../gui2/dialogs/confirm_delete_location.ui | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/calibre/gui2/dialogs/confirm_delete_location.ui b/src/calibre/gui2/dialogs/confirm_delete_location.ui index 9d70388627..212d96584f 100644 --- a/src/calibre/gui2/dialogs/confirm_delete_location.ui +++ b/src/calibre/gui2/dialogs/confirm_delete_location.ui @@ -22,6 +22,12 @@ + + + 0 + 0 + + :/images/dialog_warning.png @@ -46,6 +52,10 @@ Library + + + :/images/library.png:/images/library.png + @@ -53,6 +63,10 @@ Device + + + :/images/reader.png:/images/reader.png + @@ -60,6 +74,10 @@ Library and Device + + + :/images/trash.png:/images/trash.png + From b76159f31cf2b45fd4a75c65ec8f1cd6627a422e Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 25 Apr 2011 15:06:06 -0600 Subject: [PATCH 08/14] CurrentDir context now ignores the case when the original working dir no longer exists --- src/calibre/__init__.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/calibre/__init__.py b/src/calibre/__init__.py index 29c69a6799..bc99947345 100644 --- a/src/calibre/__init__.py +++ b/src/calibre/__init__.py @@ -388,7 +388,11 @@ class CurrentDir(object): return self.cwd def __exit__(self, *args): - os.chdir(self.cwd) + try: + os.chdir(self.cwd) + except: + # The previous CWD no longer exists + pass class StreamReadWrapper(object): From aced39619e9dfea8c3a58fe48eaa396039f4052f Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 25 Apr 2011 15:47:50 -0600 Subject: [PATCH 09/14] Add OCLC identifier to URL and use the direct ISBN link instead of worldcat search of isbn->URL --- src/calibre/ebooks/metadata/sources/identify.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/calibre/ebooks/metadata/sources/identify.py b/src/calibre/ebooks/metadata/sources/identify.py index fd71e650a0..9a9e5aa164 100644 --- a/src/calibre/ebooks/metadata/sources/identify.py +++ b/src/calibre/ebooks/metadata/sources/identify.py @@ -446,7 +446,7 @@ def urls_from_identifiers(identifiers): # {{{ isbn = identifiers.get('isbn', None) if isbn: ans.append((isbn, 'isbn', isbn, - 'http://www.worldcat.org/search?q=bn%%3A%s&qt=advanced'%isbn)) + 'http://www.worldcat.org/isbn/'+isbn)) doi = identifiers.get('doi', None) if doi: ans.append(('DOI', 'doi', doi, @@ -455,6 +455,10 @@ def urls_from_identifiers(identifiers): # {{{ if arxiv: ans.append(('arXiv', 'arxiv', arxiv, 'http://arxiv.org/abs/'+arxiv)) + oclc = identifiers.get('oclc', None) + if oclc: + ans.append(('OCLC', 'oclc', oclc, + 'http://www.worldcat.org/oclc/'+oclc)) return ans # }}} From 50334bf1a5d5ce6579848f875a7a4063181ac10d Mon Sep 17 00:00:00 2001 From: John Schember Date: Mon, 25 Apr 2011 21:27:52 -0400 Subject: [PATCH 10/14] Fix bug #770534: Problem converting pdf containing the string ******************/ --- src/calibre/ebooks/conversion/preprocess.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/ebooks/conversion/preprocess.py b/src/calibre/ebooks/conversion/preprocess.py index 8822a39b87..885d0621e0 100644 --- a/src/calibre/ebooks/conversion/preprocess.py +++ b/src/calibre/ebooks/conversion/preprocess.py @@ -402,7 +402,7 @@ class HTMLPreProcessor(object): (re.compile(r'((?<=)\s*file:/{2,4}[A-Z].*
|file:////?[A-Z].*
(?=\s*
))', re.IGNORECASE), lambda match: ''), # Center separator lines - (re.compile(u'
\s*(?P([*#•✦=]+\s*)+)\s*
'), lambda match: '

\n

' + match.group(1) + '

'), + (re.compile(u'
\s*(?P([*#•✦=] *){3,})\s*
'), lambda match: '

\n

' + match.group('break') + '

'), # Remove page links (re.compile(r'', re.IGNORECASE), lambda match: ''), From 16a1048522bc4ec7ff28907ec1aa3d7663e8c98f Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 25 Apr 2011 21:00:11 -0600 Subject: [PATCH 11/14] Document patch used on Qt for the calibre windows build to enable loading of OpenSSL dlls from the Dlls subdirectory --- setup/installer/windows/notes.rst | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/setup/installer/windows/notes.rst b/setup/installer/windows/notes.rst index ce6ca650a4..11b5bccf79 100644 --- a/setup/installer/windows/notes.rst +++ b/setup/installer/windows/notes.rst @@ -69,7 +69,24 @@ nmake -f ms\ntdll.mak install Qt -------- -Extract Qt sourcecode to C:\Qt\4.x.x. Run configure and make:: +Extract Qt sourcecode to C:\Qt\4.x.x. + +Qt uses its own routine to locate and load "system libraries" including the openssl libraries needed for "Get Books". This means that we have to apply the following patch to have Qt load the openssl libraries bundled with calibre: + + +--- src/corelib/plugin/qsystemlibrary.cpp 2011-02-22 05:04:00.000000000 -0700 ++++ src/corelib/plugin/qsystemlibrary.cpp 2011-04-25 20:53:13.635247466 -0600 +@@ -110,7 +110,7 @@ HINSTANCE QSystemLibrary::load(const wch + + #if !defined(QT_BOOTSTRAPPED) + if (!onlySystemDirectory) +- searchOrder << QFileInfo(qAppFileName()).path(); ++ searchOrder << (QFileInfo(qAppFileName()).path().replace(QLatin1Char('/'), QLatin1Char('\\')) + QString::fromLatin1("\\DLLs\\")); + #endif + searchOrder << qSystemDirectory(); + + +Now, run configure and make:: configure -opensource -release -qt-zlib -qt-gif -qt-libmng -qt-libpng -qt-libtiff -qt-libjpeg -release -platform win32-msvc2008 -no-qt3support -webkit -xmlpatterns -no-phonon -no-style-plastique -no-style-cleanlooks -no-style-motif -no-style-cde -no-declarative -no-scripttools -no-audio-backend -no-multimedia -no-dbus -no-openvg -no-opengl -no-qt3support -confirm-license -nomake examples -nomake demos -nomake docs -openssl -I Q:\openssl\include -L Q:\openssl\lib && nmake From 98b2dba03ff4b2a107e7f7b048bd62e46a3be60a Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 25 Apr 2011 22:09:37 -0600 Subject: [PATCH 12/14] Windows build: Have the installer overwrite dlls even if their version is the same to ensure the patched QtCore4.dll is installed --- setup/installer/windows/wix-template.xml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/setup/installer/windows/wix-template.xml b/setup/installer/windows/wix-template.xml index 37dd8b25a8..b5d2f4b292 100644 --- a/setup/installer/windows/wix-template.xml +++ b/setup/installer/windows/wix-template.xml @@ -11,7 +11,10 @@ SummaryCodepage='1252' /> - + + + Date: Mon, 25 Apr 2011 22:19:09 -0600 Subject: [PATCH 13/14] Fix the example plugin upload script --- setup/upload.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup/upload.py b/setup/upload.py index 57c8e4cd54..e448bc11e4 100644 --- a/setup/upload.py +++ b/setup/upload.py @@ -347,9 +347,10 @@ class UploadUserManual(Command): # {{{ with NamedTemporaryFile(suffix='.zip') as f: os.fchmod(f.fileno(), stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH|stat.S_IWRITE) - with CurrentDir(self.d(path)): + with CurrentDir(path): with ZipFile(f, 'w') as zf: for x in os.listdir('.'): + if x.endswith('.swp'): continue zf.write(x) if os.path.isdir(x): for y in os.listdir(x): From 80878bf7cf5379d768f514b4f3a5d665d6a44812 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 25 Apr 2011 23:48:40 -0600 Subject: [PATCH 14/14] ... --- src/calibre/ebooks/metadata/sources/base.py | 3 ++- src/calibre/manual/faq.rst | 7 ++++--- src/calibre/manual/plugins.rst | 9 +++------ 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/calibre/ebooks/metadata/sources/base.py b/src/calibre/ebooks/metadata/sources/base.py index f386489fcd..e67b87efbd 100644 --- a/src/calibre/ebooks/metadata/sources/base.py +++ b/src/calibre/ebooks/metadata/sources/base.py @@ -56,7 +56,8 @@ class InternalMetadataCompareKeyGen(object): ''' Generate a sort key for comparison of the relevance of Metadata objects, - given a search query. + given a search query. This is used only to compare results from the same + metadata source, not across different sources. The sort key ensures that an ascending order sort is a sort by order of decreasing relevance. diff --git a/src/calibre/manual/faq.rst b/src/calibre/manual/faq.rst index c281773660..56d1832440 100644 --- a/src/calibre/manual/faq.rst +++ b/src/calibre/manual/faq.rst @@ -20,13 +20,14 @@ What formats does |app| support conversion to/from? |app| supports the conversion of many input formats to many output formats. It can convert every input format in the following list, to every output format. -*Input Formats:* CBZ, CBR, CBC, CHM, EPUB, FB2, HTML, HTMLZ, LIT, LRF, MOBI, ODT, PDF, PRC**, PDB***, PML, RB, RTF, SNB, TCR, TXT, TXTZ +*Input Formats:* CBZ, CBR, CBC, CHM, EPUB, FB2, HTML, HTMLZ, LIT, LRF, MOBI, ODT, PDF, PRC, PDB, PML, RB, RTF, SNB, TCR, TXT, TXTZ *Output Formats:* EPUB, FB2, OEB, LIT, LRF, MOBI, HTMLZ, PDB, PML, RB, PDF, SNB, TCR, TXT, TXTZ -** PRC is a generic format, |app| supports PRC files with TextRead and MOBIBook headers +.. note :: -*** PDB is also a generic format. |app| supports eReder, Plucker, PML and zTxt PDB files. + PRC is a generic format, |app| supports PRC files with TextRead and MOBIBook headers. + PDB is also a generic format. |app| supports eReder, Plucker, PML and zTxt PDB files. .. _best-source-formats: diff --git a/src/calibre/manual/plugins.rst b/src/calibre/manual/plugins.rst index 0a62218fb9..1ebb180d46 100644 --- a/src/calibre/manual/plugins.rst +++ b/src/calibre/manual/plugins.rst @@ -65,17 +65,14 @@ Catalog plugins Metadata download plugins -------------------------- -.. module:: calibre.ebooks.metadata.fetch +.. module:: calibre.ebooks.metadata.sources.base -.. autoclass:: MetadataSource +.. autoclass:: Source :show-inheritance: :members: :member-order: bysource -.. autoclass:: calibre.ebooks.metadata.covers.CoverDownload - :show-inheritance: - :members: - :member-order: bysource +.. autoclass:: InternalMetadataCompareKeyGen Conversion plugins --------------------