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
2ac4403254
@ -4,6 +4,74 @@
|
||||
# for important features/bug fixes.
|
||||
# Also, each release can have new and improved recipes.
|
||||
|
||||
- version: 0.7.8
|
||||
date: 2010-07-09
|
||||
|
||||
new features:
|
||||
- title: "New tool to help prepare EPUBs for publication"
|
||||
type: major
|
||||
description: >
|
||||
"calibre now contains a new command line tool called epub-fix that can automatically fix
|
||||
common problems in EPUB files that cause them to be rejected by poorly designed publishing services.
|
||||
The tool is plugin based for extensible functionality in the future. Currently, it can fix unmanifested files
|
||||
and workaround the date and svg preserveaspectratio bugs of epubcheck."
|
||||
|
||||
- title: "New icons for the toolbar buttons by Kamil Tatara"
|
||||
|
||||
- title: "Display rating (when available) in cover browser"
|
||||
|
||||
- title: "Clicking on the central cover int the cover browser now opens that book in the viewer"
|
||||
|
||||
- title: "Use the status bar instead of the area to the right of the location view to display status information"
|
||||
|
||||
- title: "Driver for the Pandigital Novel e-book reader"
|
||||
|
||||
bug fixes:
|
||||
- title: "News download: Don not specify a font family for article descriptions"
|
||||
|
||||
- title: "News download: Fix regression introduced in 0.7.0 that broke download of some embedded content feeds"
|
||||
|
||||
- title: "MOBI Output: Partial support for nested superscript and subscripts."
|
||||
tickets: [6132]
|
||||
|
||||
- title: "CHM Input: Fix handling of buggy CHM files with no .hhc"
|
||||
tickets: [6087]
|
||||
|
||||
- title: "EPUB Input: Fix bug in unzipping EPUB files that have been zipped in depth first order."
|
||||
tickets: [6127]
|
||||
|
||||
- title: "TXT Input: Convert HTML entities to characters."
|
||||
tickets: [6114]
|
||||
|
||||
- title: "LRF Input: Handle LRF files with random null bytes in the text"
|
||||
tickets: [6097]
|
||||
|
||||
- title: "Kobo driver: Fix detection of txt/html files on the device"
|
||||
|
||||
- title: "Fix opening of books when calibre library is on an unmapped network share in windows"
|
||||
|
||||
- title: "SONY driver: Only update the timestamp in the XML db for newly added books"
|
||||
|
||||
- title: "Cover browser: Fix rendering of center cover when width of cover browser is less than the width of a single cover"
|
||||
|
||||
- title: "Cover browser: Correct fix for setPixel out of bounds warning causing UI slowdown in calibre"
|
||||
|
||||
new recipes:
|
||||
- title: "evz.ro"
|
||||
author: Darko Miletic
|
||||
|
||||
- title: "Anchorage Daily News, China Economic Net, BBC Chinese and Singtao Daily"
|
||||
author: rty
|
||||
|
||||
- title: Big Oven
|
||||
author: Starson17
|
||||
|
||||
improved recipes:
|
||||
- Haaretz
|
||||
- Editor and Publisher
|
||||
- Estadao
|
||||
|
||||
|
||||
- version: 0.7.7
|
||||
date: 2010-07-02
|
||||
|
||||
|
@ -2,7 +2,7 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
__appname__ = 'calibre'
|
||||
__version__ = '0.7.7'
|
||||
__version__ = '0.7.8'
|
||||
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
||||
|
||||
import re
|
||||
|
@ -460,7 +460,7 @@ from calibre.devices.hanvon.driver import N516, EB511, ALEX, AZBOOKA, THEBOOK
|
||||
from calibre.devices.edge.driver import EDGE
|
||||
from calibre.devices.teclast.driver import TECLAST_K3, NEWSMY, IPAPYRUS
|
||||
from calibre.devices.sne.driver import SNE
|
||||
from calibre.devices.misc import PALMPRE, AVANT, SWEEX
|
||||
from calibre.devices.misc import PALMPRE, AVANT, SWEEX, PDNOVEL
|
||||
from calibre.devices.folder_device.driver import FOLDER_DEVICE_FOR_CONFIG
|
||||
from calibre.devices.kobo.driver import KOBO
|
||||
|
||||
@ -562,6 +562,7 @@ plugins += [
|
||||
AVANT,
|
||||
MENTOR,
|
||||
SWEEX,
|
||||
PDNOVEL,
|
||||
ITUNES,
|
||||
]
|
||||
plugins += [x for x in list(locals().values()) if isinstance(x, type) and \
|
||||
|
@ -213,7 +213,7 @@ class KINDLE_DX(KINDLE2):
|
||||
PRODUCT_ID = [0x0003]
|
||||
BCD = [0x0100]
|
||||
|
||||
class Bookmark():
|
||||
class Bookmark(): # {{{
|
||||
'''
|
||||
A simple class fetching bookmark data
|
||||
Kindle-specific
|
||||
@ -517,3 +517,6 @@ class Bookmark():
|
||||
|
||||
else:
|
||||
print "unsupported bookmark_extension: %s" % self.bookmark_extension
|
||||
|
||||
# }}}
|
||||
|
||||
|
@ -176,23 +176,22 @@ class KOBO(USBMS):
|
||||
ImageID = row[0]
|
||||
cursor.close()
|
||||
|
||||
cursor = connection.cursor()
|
||||
if ContentType == 6:
|
||||
# Delete the shortcover_pages first
|
||||
cursor.execute('delete from shortcover_page where shortcoverid in (select ContentID from content where BookID = ?)', t)
|
||||
|
||||
#Delete the volume_shortcovers second
|
||||
cursor.execute('delete from volume_shortcovers where volumeid = ?', t)
|
||||
|
||||
# Delete the chapters associated with the book next
|
||||
t = (ContentID,ContentID,)
|
||||
cursor.execute('delete from content where BookID = ? or ContentID = ?', t)
|
||||
|
||||
connection.commit()
|
||||
|
||||
cursor.close()
|
||||
if ImageID != None:
|
||||
cursor = connection.cursor()
|
||||
if ContentType == 6:
|
||||
# Delete the shortcover_pages first
|
||||
cursor.execute('delete from shortcover_page where shortcoverid in (select ContentID from content where BookID = ?)', t)
|
||||
|
||||
#Delete the volume_shortcovers second
|
||||
cursor.execute('delete from volume_shortcovers where volumeid = ?', t)
|
||||
|
||||
# Delete the chapters associated with the book next
|
||||
t = (ContentID,ContentID,)
|
||||
cursor.execute('delete from content where BookID = ? or ContentID = ?', t)
|
||||
|
||||
connection.commit()
|
||||
|
||||
cursor.close()
|
||||
else:
|
||||
print "Error condition ImageID was not found"
|
||||
print "You likely tried to delete a book that the kobo has not yet added to the database"
|
||||
|
||||
@ -227,12 +226,16 @@ class KOBO(USBMS):
|
||||
#print "kobo book"
|
||||
ContentType = 6
|
||||
ContentID = self.contentid_from_path(path, ContentType)
|
||||
if extension == '.pdf' or extension == '.epub':
|
||||
elif extension == '.pdf' or extension == '.epub':
|
||||
# print "ePub or pdf"
|
||||
ContentType = 16
|
||||
#print "Path: " + path
|
||||
ContentID = self.contentid_from_path(path, ContentType)
|
||||
# print "ContentID: " + ContentID
|
||||
else: # if extension == '.html' or extension == '.txt':
|
||||
ContentType = 999 # Yet another hack: to get around Kobo changing how ContentID is stored
|
||||
ContentID = self.contentid_from_path(path, ContentType)
|
||||
|
||||
ImageID = self.delete_via_sql(ContentID, ContentType)
|
||||
#print " We would now delete the Images for" + ImageID
|
||||
self.delete_images(ImageID)
|
||||
@ -316,6 +319,11 @@ class KOBO(USBMS):
|
||||
ContentID = ContentID.replace(self._main_prefix, '')
|
||||
if self._card_a_prefix is not None:
|
||||
ContentID = ContentID.replace(self._card_a_prefix, '')
|
||||
elif ContentType == 999: # HTML Files
|
||||
ContentID = path
|
||||
ContentID = ContentID.replace(self._main_prefix, "/mnt/onboard/")
|
||||
if self._card_a_prefix is not None:
|
||||
ContentID = ContentID.replace(self._card_a_prefix, "/mnt/sd/")
|
||||
else: # ContentType = 16
|
||||
ContentID = path
|
||||
ContentID = ContentID.replace(self._main_prefix, "file:///mnt/onboard/")
|
||||
|
@ -69,3 +69,21 @@ class SWEEX(USBMS):
|
||||
EBOOK_DIR_MAIN = ''
|
||||
SUPPORTS_SUB_DIRS = True
|
||||
|
||||
class PDNOVEL(USBMS):
|
||||
name = 'Pandigital Novel device interface'
|
||||
gui_name = 'PD Novel'
|
||||
description = _('Communicate with the Pandigital Novel')
|
||||
author = 'Kovid Goyal'
|
||||
supported_platforms = ['windows', 'linux', 'osx']
|
||||
FORMATS = ['epub', 'pdf']
|
||||
|
||||
VENDOR_ID = [0x18d1]
|
||||
PRODUCT_ID = [0xb004]
|
||||
BCD = [0x224]
|
||||
|
||||
VENDOR_NAME = 'ANDROID'
|
||||
WINDOWS_MAIN_MEM = WINDOWS_CARD_A_MEM = '__UMS_COMPOSITE'
|
||||
|
||||
EBOOK_DIR_MAIN = 'eBooks'
|
||||
SUPPORTS_SUB_DIRS = False
|
||||
|
||||
|
@ -49,7 +49,6 @@ class CHMInput(InputFormatPlugin):
|
||||
log.debug('stream.name=%s' % stream.name)
|
||||
mainname = self._chmtohtml(tdir, chm_name, no_images, log)
|
||||
mainpath = os.path.join(tdir, mainname)
|
||||
#raw_input()
|
||||
|
||||
metadata = get_metadata_from_reader(self._chm_reader)
|
||||
|
||||
@ -141,10 +140,9 @@ class CHMInput(InputFormatPlugin):
|
||||
log.debug('Found %d section nodes' % len(chapters))
|
||||
htmlpath = os.path.splitext(hhcpath)[0] + ".html"
|
||||
f = open(htmlpath, 'wb')
|
||||
f.write('<html><head><meta http-equiv="Content-type"'
|
||||
' content="text/html;charset=UTF-8" /></head><body>\n')
|
||||
|
||||
if chapters:
|
||||
f.write('<html><head><meta http-equiv="Content-type"'
|
||||
' content="text/html;charset=UTF-8" /></head><body>\n')
|
||||
path0 = chapters[0][1]
|
||||
subpath = os.path.dirname(path0)
|
||||
|
||||
@ -158,7 +156,9 @@ class CHMInput(InputFormatPlugin):
|
||||
url = url.encode('utf-8')
|
||||
f.write(url)
|
||||
|
||||
f.write("</body></html>")
|
||||
f.write("</body></html>")
|
||||
else:
|
||||
f.write(hhcdata)
|
||||
f.close()
|
||||
return htmlpath
|
||||
|
||||
|
@ -8,7 +8,7 @@ import os, re
|
||||
from mimetypes import guess_type as guess_mimetype
|
||||
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, NavigableString
|
||||
from calibre.constants import iswindows
|
||||
from calibre.constants import iswindows, filesystem_encoding
|
||||
from calibre.utils.chm.chm import CHMFile
|
||||
from calibre.utils.chm.chmlib import (
|
||||
CHM_RESOLVE_SUCCESS, CHM_ENUMERATE_NORMAL,
|
||||
@ -78,6 +78,8 @@ class CHMError(Exception):
|
||||
class CHMReader(CHMFile):
|
||||
def __init__(self, input, log):
|
||||
CHMFile.__init__(self)
|
||||
if isinstance(input, unicode):
|
||||
input = input.encode(filesystem_encoding)
|
||||
if not self.LoadCHM(input):
|
||||
raise CHMError("Unable to open CHM file '%s'"%(input,))
|
||||
self.log = log
|
||||
@ -91,7 +93,6 @@ class CHMReader(CHMFile):
|
||||
self.root, ext = os.path.splitext(self.topics.lstrip('/'))
|
||||
self.hhc_path = self.root + ".hhc"
|
||||
|
||||
|
||||
def _parse_toc(self, ul, basedir=os.getcwdu()):
|
||||
toc = TOC(play_order=self._playorder, base_path=basedir, text='')
|
||||
self._playorder += 1
|
||||
@ -152,6 +153,8 @@ class CHMReader(CHMFile):
|
||||
if f.lower() == self.hhc_path.lower():
|
||||
self.hhc_path = f
|
||||
break
|
||||
if self.hhc_path not in files and files:
|
||||
self.hhc_path = files[0]
|
||||
|
||||
def _reformat(self, data):
|
||||
try:
|
||||
@ -159,7 +162,7 @@ class CHMReader(CHMFile):
|
||||
soup = BeautifulSoup(data)
|
||||
except ValueError:
|
||||
# hit some strange encoding problems...
|
||||
print "Unable to parse html for cleaning, leaving it :("
|
||||
self.log.exception("Unable to parse html for cleaning, leaving it")
|
||||
return data
|
||||
# nuke javascript...
|
||||
[s.extract() for s in soup('script')]
|
||||
|
@ -58,6 +58,7 @@ class FormatState(object):
|
||||
self.fsize = 3
|
||||
self.ids = set()
|
||||
self.valign = 'baseline'
|
||||
self.nest = False
|
||||
self.italic = False
|
||||
self.bold = False
|
||||
self.strikethrough = False
|
||||
@ -233,9 +234,17 @@ class MobiMLizer(object):
|
||||
inline = etree.SubElement(inline, XHTML('a'), href=href)
|
||||
bstate.anchor = inline
|
||||
if valign == 'super':
|
||||
inline = etree.SubElement(inline, XHTML('sup'))
|
||||
parent = inline
|
||||
if istate.nest and bstate.inline is not None:
|
||||
parent = bstate.inline
|
||||
istate.nest = False
|
||||
inline = etree.SubElement(parent, XHTML('sup'))
|
||||
elif valign == 'sub':
|
||||
inline = etree.SubElement(inline, XHTML('sub'))
|
||||
parent = inline
|
||||
if istate.nest and bstate.inline is not None:
|
||||
parent = bstate.inline
|
||||
istate.nest = False
|
||||
inline = etree.SubElement(parent, XHTML('sub'))
|
||||
elif fsize != 3:
|
||||
inline = etree.SubElement(inline, XHTML('font'),
|
||||
size=str(fsize))
|
||||
@ -343,8 +352,10 @@ class MobiMLizer(object):
|
||||
istate.family = 'serif'
|
||||
valign = style['vertical-align']
|
||||
if valign in ('super', 'text-top') or asfloat(valign) > 0:
|
||||
istate.nest = istate.valign in ('sub', 'super')
|
||||
istate.valign = 'super'
|
||||
elif valign == 'sub' or asfloat(valign) < 0:
|
||||
istate.nest = istate.valign in ('sub', 'super')
|
||||
istate.valign = 'sub'
|
||||
else:
|
||||
istate.valign = 'baseline'
|
||||
|
@ -66,7 +66,7 @@ class DeleteMatchingFromDeviceDialog(QDialog, Ui_DeleteMatchingFromDeviceDialog)
|
||||
|
||||
self.explanation.setText('<p>'+_('All checked books will be '
|
||||
'<b>permanently deleted</b> from your '
|
||||
'device. Please verify the list.'+'</p>'))
|
||||
'device. Please verify the list.')+'</p>')
|
||||
self.buttonBox.accepted.connect(self.accepted)
|
||||
self.table.cellClicked.connect(self.cell_clicked)
|
||||
self.table.setSelectionMode(QAbstractItemView.NoSelection)
|
||||
|
@ -17,7 +17,7 @@ class ListWidgetItem(QListWidgetItem):
|
||||
def data(self, role):
|
||||
if role == Qt.DisplayRole:
|
||||
if self.old_value != self.cur_value:
|
||||
return _('%s (was %s)'%(self.cur_value, self.old_value))
|
||||
return _('%s (was %s)')%(self.cur_value, self.old_value)
|
||||
else:
|
||||
return self.cur_value
|
||||
elif role == Qt.EditRole:
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1071,8 +1071,13 @@ class ZipFile:
|
||||
|
||||
# Create all upper directories if necessary.
|
||||
upperdirs = os.path.dirname(targetpath)
|
||||
if upperdirs and os.path.exists(upperdirs) and not os.path.isdir(upperdirs):
|
||||
os.unlink(upperdirs)
|
||||
while upperdirs:
|
||||
if os.path.exists(upperdirs):
|
||||
if os.path.isdir(upperdirs):
|
||||
break
|
||||
os.remove(upperdirs)
|
||||
upperdirs = os.path.dirname(upperdirs)
|
||||
upperdirs = os.path.dirname(targetpath)
|
||||
if upperdirs and not os.path.exists(upperdirs):
|
||||
os.makedirs(upperdirs)
|
||||
|
||||
|
@ -264,7 +264,7 @@ class BasicNewsRecipe(Recipe):
|
||||
}
|
||||
|
||||
.article_description {
|
||||
font-family: sans; text-indent: 0pt;
|
||||
text-indent: 0pt;
|
||||
}
|
||||
|
||||
a.article {
|
||||
|
@ -70,7 +70,10 @@ class EmbeddedContent(Template):
|
||||
div.text = elements[0]
|
||||
elements = list(elements)[1:]
|
||||
for elem in elements:
|
||||
elem.getparent().remove(elem)
|
||||
if hasattr(elem, 'getparent'):
|
||||
elem.getparent().remove(elem)
|
||||
else:
|
||||
elem = SPAN(elem)
|
||||
div.append(elem)
|
||||
|
||||
class IndexTemplate(Template):
|
||||
|
Loading…
x
Reference in New Issue
Block a user