mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Merge from trunk
This commit is contained in:
commit
ffbc7931f2
@ -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
|
||||||
|
|
||||||
|
@ -11,6 +11,9 @@
|
|||||||
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}"
|
||||||
|
@ -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):
|
||||||
|
@ -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):
|
||||||
|
@ -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: ''),
|
||||||
|
@ -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):
|
||||||
|
@ -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={}): # {{{
|
||||||
|
@ -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.
|
||||||
|
@ -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={}): # {{{
|
||||||
|
@ -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
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
@ -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:
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -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:
|
||||||
|
@ -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:
|
||||||
|
|
||||||
|
@ -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
|
||||||
--------------------
|
--------------------
|
||||||
|
Loading…
x
Reference in New Issue
Block a user