Merge from trunk

This commit is contained in:
Charles Haley 2011-04-26 09:46:30 +01:00
commit ffbc7931f2
16 changed files with 94 additions and 34 deletions

View File

@ -69,7 +69,24 @@ nmake -f ms\ntdll.mak install
Qt 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 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

View File

@ -11,7 +11,10 @@
SummaryCodepage='1252' /> SummaryCodepage='1252' />
<Media Id="1" Cabinet="{app}.cab" CompressionLevel="{compression}" EmbedCab="yes" /> <Media Id="1" Cabinet="{app}.cab" CompressionLevel="{compression}" EmbedCab="yes" />
<!-- The following line is needed because of the patch to QtCore4.dll. You can remove this line
after you update Qt beyond 4.7.2. 'emus' means re-install even if version is the same not just if it is older. -->
<Property Id='REINSTALLMODE' Value='emus'/>
<Upgrade Id="{upgrade_code}"> <Upgrade Id="{upgrade_code}">
<UpgradeVersion Maximum="{version}" <UpgradeVersion Maximum="{version}"
IncludeMaximum="yes" IncludeMaximum="yes"

View File

@ -347,9 +347,10 @@ class UploadUserManual(Command): # {{{
with NamedTemporaryFile(suffix='.zip') as f: with NamedTemporaryFile(suffix='.zip') as f:
os.fchmod(f.fileno(), os.fchmod(f.fileno(),
stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH|stat.S_IWRITE) 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: with ZipFile(f, 'w') as zf:
for x in os.listdir('.'): for x in os.listdir('.'):
if x.endswith('.swp'): continue
zf.write(x) zf.write(x)
if os.path.isdir(x): if os.path.isdir(x):
for y in os.listdir(x): for y in os.listdir(x):

View File

@ -388,7 +388,11 @@ class CurrentDir(object):
return self.cwd return self.cwd
def __exit__(self, *args): def __exit__(self, *args):
os.chdir(self.cwd) try:
os.chdir(self.cwd)
except:
# The previous CWD no longer exists
pass
class StreamReadWrapper(object): class StreamReadWrapper(object):

View File

@ -402,7 +402,7 @@ class HTMLPreProcessor(object):
(re.compile(r'((?<=</a>)\s*file:/{2,4}[A-Z].*<br>|file:////?[A-Z].*<br>(?=\s*<hr>))', re.IGNORECASE), lambda match: ''), (re.compile(r'((?<=</a>)\s*file:/{2,4}[A-Z].*<br>|file:////?[A-Z].*<br>(?=\s*<hr>))', re.IGNORECASE), lambda match: ''),
# Center separator lines # Center separator lines
(re.compile(u'<br>\s*(?P<break>([*#•✦=]+\s*)+)\s*<br>'), lambda match: '<p>\n<p style="text-align:center">' + match.group(1) + '</p>'), (re.compile(u'<br>\s*(?P<break>([*#•✦=] *){3,})\s*<br>'), lambda match: '<p>\n<p style="text-align:center">' + match.group('break') + '</p>'),
# Remove page links # Remove page links
(re.compile(r'<a name=\d+></a>', re.IGNORECASE), lambda match: ''), (re.compile(r'<a name=\d+></a>', re.IGNORECASE), lambda match: ''),

View File

@ -174,11 +174,6 @@ class Metadata(object):
try: try:
return self.__getattribute__(field) return self.__getattribute__(field)
except AttributeError: except AttributeError:
if field.startswith('#') and field.endswith('_index'):
try:
return self.get_extra(field[:-6])
except:
pass
return default return default
def get_extra(self, field, default=None): def get_extra(self, field, default=None):

View File

@ -301,7 +301,7 @@ class Amazon(Source):
if asin is None: if asin is None:
asin = identifiers.get('asin', None) asin = identifiers.get('asin', None)
if asin: 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={}): # {{{ def create_query(self, log, title=None, authors=None, identifiers={}): # {{{

View File

@ -56,7 +56,8 @@ class InternalMetadataCompareKeyGen(object):
''' '''
Generate a sort key for comparison of the relevance of Metadata objects, 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 The sort key ensures that an ascending order sort is a sort by order of
decreasing relevance. decreasing relevance.
@ -374,7 +375,11 @@ class Source(Plugin):
def get_book_url(self, identifiers): 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 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 to provide a clickable link for the user to easily visit the books page
at this source. at this source.

View File

@ -173,7 +173,7 @@ class GoogleBooks(Source):
def get_book_url(self, identifiers): # {{{ def get_book_url(self, identifiers): # {{{
goog = identifiers.get('google', None) goog = identifiers.get('google', None)
if goog is not 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={}): # {{{ def create_query(self, log, title=None, authors=None, identifiers={}): # {{{

View File

@ -435,18 +435,30 @@ def identify(log, abort, # {{{
# }}} # }}}
def urls_from_identifiers(identifiers): # {{{ def urls_from_identifiers(identifiers): # {{{
identifiers = dict([(k.lower(), v) for k, v in identifiers.iteritems()])
ans = [] ans = []
for plugin in all_metadata_plugins(): for plugin in all_metadata_plugins():
try: try:
url = plugin.get_book_url(identifiers) id_type, id_val, url = plugin.get_book_url(identifiers)
if url is not None: ans.append((plugin.name, id_type, id_val, url))
ans.append((plugin.name, url))
except: except:
pass pass
isbn = identifiers.get('isbn', None) isbn = identifiers.get('isbn', None)
if isbn: if isbn:
ans.append((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,
'http://dx.doi.org/'+doi))
arxiv = identifiers.get('arxiv', None)
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 return ans
# }}} # }}}

View File

@ -265,7 +265,7 @@ class OverDrive(Source):
if creators: if creators:
creators = creators.split(', ') creators = creators.split(', ')
# if an exact match in a preferred format occurs # 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, return self.format_results(reserveid, od_title, subtitle, series, publisher,
creators, thumbimage, worldcatlink, formatid) creators, thumbimage, worldcatlink, formatid)
else: 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)) close_matches.insert(0, self.format_results(reserveid, od_title, subtitle, series, publisher, creators, thumbimage, worldcatlink, formatid))
else: else:
close_matches.append(self.format_results(reserveid, od_title, subtitle, series, publisher, creators, thumbimage, worldcatlink, formatid)) 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]: 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)) close_matches.append(self.format_results(reserveid, od_title, subtitle, series, publisher, creators, thumbimage, worldcatlink, formatid))

View File

@ -17,13 +17,13 @@ from calibre.gui2.dnd import (dnd_has_image, dnd_get_image, dnd_get_files,
from calibre.ebooks import BOOK_EXTENSIONS from calibre.ebooks import BOOK_EXTENSIONS
from calibre.ebooks.metadata.book.base import (field_metadata, Metadata) from calibre.ebooks.metadata.book.base import (field_metadata, Metadata)
from calibre.ebooks.metadata import fmt_sidx 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.constants import filesystem_encoding
from calibre.library.comments import comments_to_html from calibre.library.comments import comments_to_html
from calibre.gui2 import (config, open_local_file, open_url, pixmap_to_data, from calibre.gui2 import (config, open_local_file, open_url, pixmap_to_data,
gprefs) gprefs)
from calibre.utils.icu import sort_key from calibre.utils.icu import sort_key
def render_html(mi, css, vertical, widget, all_fields=False): # {{{ def render_html(mi, css, vertical, widget, all_fields=False): # {{{
table = render_data(mi, all_fields=all_fields, table = render_data(mi, all_fields=all_fields,
use_roman_numbers=config['use_roman_numerals_for_series_number']) use_roman_numbers=config['use_roman_numerals_for_series_number'])
@ -114,14 +114,19 @@ def render_data(mi, use_roman_numbers=True, all_fields=False):
ans.append((field, u'<td class="title">%s</td><td>%s</td>'%(name, ans.append((field, u'<td class="title">%s</td><td>%s</td>'%(name,
u', '.join(fmts)))) u', '.join(fmts))))
elif field == 'identifiers': elif field == 'identifiers':
pass # TODO urls = urls_from_identifiers(mi.identifiers)
links = [u'<a href="%s" title="%s:%s">%s</a>' % (url, id_typ, id_val, name)
for name, id_typ, id_val, url in urls]
links = u', '.join(links)
ans.append((field, u'<td class="title">%s</td><td>%s</td>'%(
_('Ids')+':', links)))
else: else:
val = mi.format_field(field)[-1] val = mi.format_field(field)[-1]
if val is None: if val is None:
continue continue
val = prepare_string_for_xml(val) val = prepare_string_for_xml(val)
if metadata['datatype'] == 'series': if metadata['datatype'] == 'series':
sidx = getattr(mi, field+'_index') sidx = mi.get(field+'_index')
if sidx is None: if sidx is None:
sidx = 1.0 sidx = 1.0
val = _('Book %s of <span class="series_name">%s</span>')%(fmt_sidx(sidx, val = _('Book %s of <span class="series_name">%s</span>')%(fmt_sidx(sidx,
@ -289,6 +294,8 @@ class BookInfo(QWebView):
def link_activated(self, link): def link_activated(self, link):
self._link_clicked = True self._link_clicked = True
if unicode(link.scheme()) in ('http', 'https'):
return open_url(link)
link = unicode(link.toString()) link = unicode(link.toString())
self.link_clicked.emit(link) self.link_clicked.emit(link)

View File

@ -22,6 +22,12 @@
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<item> <item>
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="pixmap"> <property name="pixmap">
<pixmap resource="../../../../resources/images.qrc">:/images/dialog_warning.png</pixmap> <pixmap resource="../../../../resources/images.qrc">:/images/dialog_warning.png</pixmap>
</property> </property>
@ -46,6 +52,10 @@
<property name="text"> <property name="text">
<string>Library</string> <string>Library</string>
</property> </property>
<property name="icon">
<iconset resource="../../../../resources/images.qrc">
<normaloff>:/images/library.png</normaloff>:/images/library.png</iconset>
</property>
</widget> </widget>
</item> </item>
<item> <item>
@ -53,6 +63,10 @@
<property name="text"> <property name="text">
<string>Device</string> <string>Device</string>
</property> </property>
<property name="icon">
<iconset resource="../../../../resources/images.qrc">
<normaloff>:/images/reader.png</normaloff>:/images/reader.png</iconset>
</property>
</widget> </widget>
</item> </item>
<item> <item>
@ -60,6 +74,10 @@
<property name="text"> <property name="text">
<string>Library and Device</string> <string>Library and Device</string>
</property> </property>
<property name="icon">
<iconset resource="../../../../resources/images.qrc">
<normaloff>:/images/trash.png</normaloff>:/images/trash.png</iconset>
</property>
</widget> </widget>
</item> </item>
<item> <item>

View File

@ -253,7 +253,7 @@ class ResultsView(QTableView): # {{{
parts.append('</center>') parts.append('</center>')
if book.identifiers: if book.identifiers:
urls = urls_from_identifiers(book.identifiers) urls = urls_from_identifiers(book.identifiers)
ids = ['<a href="%s">%s</a>'%(url, name) for name, url in urls] ids = ['<a href="%s">%s</a>'%(url, name) for name, ign, ign, url in urls]
if ids: if ids:
parts.append('<div><b>%s:</b> %s</div><br>'%(_('See at'), ', '.join(ids))) parts.append('<div><b>%s:</b> %s</div><br>'%(_('See at'), ', '.join(ids)))
if book.tags: if book.tags:

View File

@ -20,13 +20,14 @@ What formats does |app| support conversion to/from?
|app| supports the conversion of many input formats to many output formats. |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. 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 *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: .. _best-source-formats:

View File

@ -65,17 +65,14 @@ Catalog plugins
Metadata download plugins Metadata download plugins
-------------------------- --------------------------
.. module:: calibre.ebooks.metadata.fetch .. module:: calibre.ebooks.metadata.sources.base
.. autoclass:: MetadataSource .. autoclass:: Source
:show-inheritance: :show-inheritance:
:members: :members:
:member-order: bysource :member-order: bysource
.. autoclass:: calibre.ebooks.metadata.covers.CoverDownload .. autoclass:: InternalMetadataCompareKeyGen
:show-inheritance:
:members:
:member-order: bysource
Conversion plugins Conversion plugins
-------------------- --------------------