From 4bdb5366717a673bfdff490a554f6ed677bcf07c Mon Sep 17 00:00:00 2001
From: John Schember
Date: Fri, 16 Jan 2009 20:43:36 -0500
Subject: [PATCH 01/21] Usbms cli support
---
src/calibre/devices/usbms/driver.py | 52 +++++++++++++++++++++++++----
1 file changed, 45 insertions(+), 7 deletions(-)
diff --git a/src/calibre/devices/usbms/driver.py b/src/calibre/devices/usbms/driver.py
index 187a4c1a50..75f04219e7 100644
--- a/src/calibre/devices/usbms/driver.py
+++ b/src/calibre/devices/usbms/driver.py
@@ -125,10 +125,11 @@ class USBMS(Device):
if os.path.exists(path):
# Delete the ebook
os.unlink(path)
- try:
- os.removedirs(os.path.dirname(path))
- except:
- pass
+ if self.SUPPORTS_SUB_DIRS:
+ try:
+ os.removedirs(os.path.dirname(path))
+ except:
+ pass
@classmethod
def remove_books_from_metadata(cls, paths, booklists):
@@ -148,7 +149,18 @@ class USBMS(Device):
path = self.munge_path(path)
src = open(path, 'rb')
shutil.copyfileobj(src, outfile, 10*1024*1024)
-
+
+ def put_file(self, infile, path, replace_file=False, end_session=True):
+ path = self.munge_path(path)
+ if os.path.isdir(path):
+ path = os.path.join(path, infile.name)
+ if not replace_file and os.path.exists(path):
+ raise PathError('File already exists: ' + path)
+ dest = open(path, 'wb')
+ shutil.copyfileobj(infile, dest, 10*1024*1024)
+ dest.flush()
+ dest.close()
+
def munge_path(self, path):
if path.startswith('/') and not (path.startswith(self._main_prefix) or \
(self._card_prefix and path.startswith(self._card_prefix))):
@@ -157,6 +169,34 @@ class USBMS(Device):
path = path.replace('card:', self._card_prefix[:-1])
return path
+ def list(self, path, recurse=False, end_session=True, munge=True):
+ if munge:
+ path = self.munge_path(path)
+ if os.path.isfile(path):
+ return [(os.path.dirname(path), [File(path)])]
+ entries = [File(os.path.join(path, f)) for f in os.listdir(path)]
+ dirs = [(path, entries)]
+ for _file in entries:
+ if recurse and _file.is_dir:
+ dirs[len(dirs):] = self.list(_file.path, recurse=True, munge=False)
+ return dirs
+
+ def mkdir(self, path, end_session=True):
+ if self.SUPPORTS_SUB_DIRS:
+ path = self.munge_path(path)
+ os.mkdir(path)
+
+ def rm(self, path, end_session=True):
+ path = self.munge_path(path)
+ self.delete_books([path])
+
+ def touch(self, path, end_session=True):
+ path = self.munge_path(path)
+ if not os.path.exists(path):
+ open(path, 'w').close()
+ if not os.path.isdir(path):
+ os.utime(path, None)
+
@classmethod
def extract_book_metadata_by_filename(cls, filename):
book_title = ''
@@ -183,5 +223,3 @@ class USBMS(Device):
return book_title, book_author, book_mime
-# ls, rm, cp, mkdir, touch, cat
-
From d599956a7228d8b02051c4d04123854178e184f5 Mon Sep 17 00:00:00 2001
From: John Schember
Date: Sat, 17 Jan 2009 12:43:50 -0500
Subject: [PATCH 02/21] Kindle support for OSX and Windows
---
src/calibre/devices/__init__.py | 4 ++--
src/calibre/devices/kindle/driver.py | 9 +++++++--
2 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/src/calibre/devices/__init__.py b/src/calibre/devices/__init__.py
index f300c666b9..e68a8b3de3 100644
--- a/src/calibre/devices/__init__.py
+++ b/src/calibre/devices/__init__.py
@@ -10,7 +10,7 @@ def devices():
from calibre.devices.prs505.driver import PRS505
from calibre.devices.prs700.driver import PRS700
from calibre.devices.cybookg3.driver import CYBOOKG3
- #from calibre.devices.kindle.driver import KINDLE
+ from calibre.devices.kindle.driver import KINDLE
return (PRS500, PRS505, PRS700, CYBOOKG3)
import time
@@ -31,4 +31,4 @@ def strftime(epoch, zone=time.gmtime):
src = time.strftime("%w, %d %m %Y %H:%M:%S GMT", zone(epoch)).split()
src[0] = INVERSE_DAY_MAP[int(src[0][:-1])]+','
src[2] = INVERSE_MONTH_MAP[int(src[2])]
- return ' '.join(src)
\ No newline at end of file
+ return ' '.join(src)
diff --git a/src/calibre/devices/kindle/driver.py b/src/calibre/devices/kindle/driver.py
index d5ef7008bc..d4cbb5b90b 100755
--- a/src/calibre/devices/kindle/driver.py
+++ b/src/calibre/devices/kindle/driver.py
@@ -16,13 +16,18 @@ class KINDLE(USBMS):
PRODUCT_ID = 0x0001
BCD = [0x399]
- VENDOR_NAME = 'AMAZON'
- WINDOWS_MAIN_MEM = 'KINDLE'
+ VENDOR_NAME = 'KINDLE'
+ WINDOWS_MAIN_MEM = 'INTERNAL_STORAGE'
+ WINDOWS_CARD_MEM = 'CARD_STORAGE'
+
+ OSX_MAIN_MEM = 'Kindle Internal Storage Media'
+ OSX_CARD_MEM = 'Kindle Card Storage Media'
MAIN_MEMORY_VOLUME_LABEL = 'Kindle Main Memory'
STORAGE_CARD_VOLUME_LABEL = 'Kindle Storage Card'
EBOOK_DIR_MAIN = "documents"
+ SUPPORTS_SUB_DIRS = True
def delete_books(self, paths, end_session=True):
for path in paths:
From a12b1bd4a4fea332254e12ff94ff56f293089c74 Mon Sep 17 00:00:00 2001
From: John Schember
Date: Sat, 17 Jan 2009 14:12:15 -0500
Subject: [PATCH 03/21] Better t2b deletion for Cybook
---
src/calibre/devices/cybookg3/driver.py | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/src/calibre/devices/cybookg3/driver.py b/src/calibre/devices/cybookg3/driver.py
index 6c026c8669..517baf7407 100644
--- a/src/calibre/devices/cybookg3/driver.py
+++ b/src/calibre/devices/cybookg3/driver.py
@@ -36,17 +36,15 @@ class CYBOOKG3(USBMS):
os.unlink(path)
filepath, ext = os.path.splitext(path)
- basepath, filename = os.path.split(filepath)
# Delete the ebook auxiliary file
if os.path.exists(filepath + '.mbp'):
os.unlink(filepath + '.mbp')
# Delete the thumbnails file auto generated for the ebook
- for p, d, files in os.walk(basepath):
- for filen in fnmatch.filter(files, filename + "*.t2b"):
- os.unlink(os.path.join(p, filen))
-
+ if os.path.exists(filepath + '_6090.t2b'):
+ os.unlink(filepath + '_6090.t2b')
+
try:
os.removedirs(os.path.dirname(path))
except:
From 68fe7a1e8e11ba5249f206e67ea5f3c2e32d2620 Mon Sep 17 00:00:00 2001
From: "Marshall T. Vandegrift"
Date: Sat, 17 Jan 2009 14:50:11 -0500
Subject: [PATCH 04/21] Force default font-size in CSS flattening.
---
src/calibre/ebooks/oeb/transforms/flatcss.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/calibre/ebooks/oeb/transforms/flatcss.py b/src/calibre/ebooks/oeb/transforms/flatcss.py
index 7110c2db2d..8a3057787d 100644
--- a/src/calibre/ebooks/oeb/transforms/flatcss.py
+++ b/src/calibre/ebooks/oeb/transforms/flatcss.py
@@ -172,11 +172,11 @@ class CSSFlattener(object):
if 'bgcolor' in node.attrib:
cssdict['background-color'] = node.attrib['bgcolor']
del node.attrib['bgcolor']
+ if 'font-size' in cssdict or tag == 'body':
+ fsize = self.fmap[style['font-size']]
+ cssdict['font-size'] = "%0.5fem" % (fsize / psize)
+ psize = fsize
if cssdict:
- if 'font-size' in cssdict:
- fsize = self.fmap[style['font-size']]
- cssdict['font-size'] = "%0.5fem" % (fsize / psize)
- psize = fsize
if self.lineh and self.fbase and tag != 'body':
self.clean_edges(cssdict, style, psize)
margin = style['margin-left']
From 1a3de747d9bb5680a975b767f2c4054d55fc6771 Mon Sep 17 00:00:00 2001
From: Kovid Goyal
Date: Sat, 17 Jan 2009 12:32:43 -0800
Subject: [PATCH 05/21] IGN:...
---
src/calibre/ebooks/mobi/writer.py | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/calibre/ebooks/mobi/writer.py b/src/calibre/ebooks/mobi/writer.py
index a6dc18110c..62d444ee95 100644
--- a/src/calibre/ebooks/mobi/writer.py
+++ b/src/calibre/ebooks/mobi/writer.py
@@ -393,7 +393,7 @@ class MobiWriter(object):
return data
def _generate_images(self):
- self._oeb.logger.warn('Serializing images...')
+ self._oeb.logger.info('Serializing images...')
images = [(index, href) for href, index in self._images.items()]
images.sort()
metadata = self._oeb.metadata
@@ -502,7 +502,8 @@ def add_mobi_options(parser):
_('Mobipocket-specific options.'))
group.add_option(
'-c', '--compress', default=False, action='store_true',
- help=_('Compress file text using PalmDOC compression.'))
+ help=_('Compress file text using PalmDOC compression. '
+ 'Results in smaller files, but takes a long time to run.'))
group.add_option(
'-r', '--rescale-images', default=False, action='store_true',
help=_('Modify images to meet Palm device size limitations.'))
From a62c15cee0ac4ab07d100f5ebf4ec01e92d7ceac Mon Sep 17 00:00:00 2001
From: "Marshall T. Vandegrift"
Date: Sat, 17 Jan 2009 15:50:07 -0500
Subject: [PATCH 06/21] Fix break to any2lit.
---
src/calibre/ebooks/lit/from_any.py | 3 ++-
src/calibre/ebooks/lit/writer.py | 2 +-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/calibre/ebooks/lit/from_any.py b/src/calibre/ebooks/lit/from_any.py
index cd8b5a115c..af368408ba 100644
--- a/src/calibre/ebooks/lit/from_any.py
+++ b/src/calibre/ebooks/lit/from_any.py
@@ -38,6 +38,7 @@ def any2lit(opts, path):
os.mkdir(oebdir)
opts.output = os.path.join(tdir, 'dummy.epub')
opts.profile = 'None'
+ opts.dont_split_on_page_breaks = True
any2epub(opts, path, create_epub=False, oeb_cover=True, extract_to=oebdir)
opf = glob.glob(os.path.join(oebdir, '*.opf'))[0]
opts.output = orig_output
@@ -56,4 +57,4 @@ def main(args=sys.argv):
return 0
if __name__ == '__main__':
- sys.exit(main())
\ No newline at end of file
+ sys.exit(main())
diff --git a/src/calibre/ebooks/lit/writer.py b/src/calibre/ebooks/lit/writer.py
index 67450fb385..90fca90738 100644
--- a/src/calibre/ebooks/lit/writer.py
+++ b/src/calibre/ebooks/lit/writer.py
@@ -725,7 +725,7 @@ def oeb2lit(opts, inpath):
outpath = os.path.basename(inpath)
outpath = os.path.splitext(outpath)[0] + '.lit'
outpath = os.path.abspath(outpath)
- context = Context('Firefox', 'MSReader')
+ context = Context('Browser', 'MSReader')
oeb = OEBBook(inpath, logger=logger)
tocadder = HTMLTOCAdder()
tocadder.transform(oeb, context)
From 3eef5f35bf71bec485dc304665235dbb2e1d5b8b Mon Sep 17 00:00:00 2001
From: "Marshall T. Vandegrift"
Date: Sat, 17 Jan 2009 15:59:26 -0500
Subject: [PATCH 07/21] Fix further breakage in oeb2lit
---
src/calibre/ebooks/lit/writer.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/calibre/ebooks/lit/writer.py b/src/calibre/ebooks/lit/writer.py
index 90fca90738..6d97471d75 100644
--- a/src/calibre/ebooks/lit/writer.py
+++ b/src/calibre/ebooks/lit/writer.py
@@ -143,7 +143,7 @@ def warn(x):
class ReBinary(object):
NSRMAP = {'': None, XML_NS: 'xml'}
- def __init__(self, root, path, oeb, map=HTML_MAP):
+ def __init__(self, root, item, oeb, map=HTML_MAP):
self.item = item
self.logger = oeb.logger
self.manifest = oeb.manifest
From 05bc96b06701efe926ed5f83a5646bb743ae359d Mon Sep 17 00:00:00 2001
From: Kovid Goyal
Date: Sat, 17 Jan 2009 13:07:04 -0800
Subject: [PATCH 08/21] Fix #1608 (Cover not found in Mobipocket file)
---
src/calibre/ebooks/mobi/reader.py | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/src/calibre/ebooks/mobi/reader.py b/src/calibre/ebooks/mobi/reader.py
index 63ef7b0b14..83624d6b5d 100644
--- a/src/calibre/ebooks/mobi/reader.py
+++ b/src/calibre/ebooks/mobi/reader.py
@@ -466,16 +466,28 @@ class MobiReader(object):
def get_metadata(stream):
mr = MobiReader(stream)
if mr.book_header.exth is None:
- mi = MetaInformation(mr.name, ['Unknown'])
+ mi = MetaInformation(mr.name, [_('Unknown')])
else:
- tdir = tempfile.mkdtemp('_mobi_meta', __appname__)
+ tdir = tempfile.mkdtemp('_mobi_meta', __appname__+'_')
atexit.register(shutil.rmtree, tdir)
mr.extract_images([], tdir)
mi = mr.create_opf('dummy.html')
if mi.cover:
cover = os.path.join(tdir, mi.cover)
+ if not os.access(cover, os.R_OK):
+ fname = os.path.basename(cover)
+ match = re.match(r'(\d+)(.+)', fname)
+ if match:
+ num, ext = int(match.group(1), 10), match.group(2)
+ while num > 0:
+ num -= 1
+ candidate = os.path.join(os.path.dirname(cover), '%05d%s'%(num, ext))
+ if os.access(candidate, os.R_OK):
+ cover = candidate
+ break
+
if os.access(cover, os.R_OK):
- mi.cover_data = ('JPEG', open(os.path.join(tdir, mi.cover), 'rb').read())
+ mi.cover_data = ('JPEG', open(os.path.join(tdir, cover), 'rb').read())
else:
path = os.path.join(tdir, 'images', '00001.jpg')
if os.access(path, os.R_OK):
From ad04058c24b2291a8c2694fb6ad964884d3a8cd3 Mon Sep 17 00:00:00 2001
From: Kovid Goyal
Date: Sat, 17 Jan 2009 13:40:29 -0800
Subject: [PATCH 09/21] IGN:Fix any2lit now disables any2epub font rescaling
and enables splitting on page breaks
---
src/calibre/ebooks/lit/from_any.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/calibre/ebooks/lit/from_any.py b/src/calibre/ebooks/lit/from_any.py
index af368408ba..f6813caf91 100644
--- a/src/calibre/ebooks/lit/from_any.py
+++ b/src/calibre/ebooks/lit/from_any.py
@@ -38,8 +38,10 @@ def any2lit(opts, path):
os.mkdir(oebdir)
opts.output = os.path.join(tdir, 'dummy.epub')
opts.profile = 'None'
- opts.dont_split_on_page_breaks = True
+ orig_bfs = opts.base_font_size2
+ opts.base_font_size2 = 0
any2epub(opts, path, create_epub=False, oeb_cover=True, extract_to=oebdir)
+ opts.base_font_size2 = orig_bfs
opf = glob.glob(os.path.join(oebdir, '*.opf'))[0]
opts.output = orig_output
logging.getLogger('html2epub').info(_('Creating LIT file from EPUB...'))
From 25a176ec0ea1479ec7fcee67cb2db13f215d4d81 Mon Sep 17 00:00:00 2001
From: Kovid Goyal
Date: Sat, 17 Jan 2009 14:23:10 -0800
Subject: [PATCH 10/21] Fix #1631 (Cover Image from epub cut in half)
---
src/calibre/ebooks/metadata/epub.py | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/calibre/ebooks/metadata/epub.py b/src/calibre/ebooks/metadata/epub.py
index a7114c48d8..a8c2105c02 100644
--- a/src/calibre/ebooks/metadata/epub.py
+++ b/src/calibre/ebooks/metadata/epub.py
@@ -103,8 +103,8 @@ class OCFDirReader(OCFReader):
return open(os.path.join(self.root, path), *args, **kwargs)
class CoverRenderer(QObject):
- WIDTH = 1280
- HEIGHT = 1024
+ WIDTH = 600
+ HEIGHT = 800
def __init__(self, url, size, loop):
QObject.__init__(self)
@@ -113,7 +113,7 @@ class CoverRenderer(QObject):
pal = self.page.palette()
pal.setBrush(QPalette.Background, Qt.white)
self.page.setPalette(pal)
- self.page.setViewportSize(QSize(600, 800))
+ self.page.setViewportSize(QSize(self.WIDTH, self.HEIGHT))
self.page.mainFrame().setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff)
self.page.mainFrame().setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff)
QObject.connect(self.page, SIGNAL('loadFinished(bool)'), self.render_html)
@@ -126,9 +126,9 @@ class CoverRenderer(QObject):
try:
if not ok:
return
- size = self.page.mainFrame().contentsSize()
- width, height = fit_image(size.width(), size.height(), self.WIDTH, self.HEIGHT)[1:]
- self.page.setViewportSize(QSize(width, height))
+ #size = self.page.mainFrame().contentsSize()
+ #width, height = fit_image(size.width(), size.height(), self.WIDTH, self.HEIGHT)[1:]
+ #self.page.setViewportSize(QSize(width, height))
image = QImage(self.page.viewportSize(), QImage.Format_ARGB32)
image.setDotsPerMeterX(96*(100/2.54))
image.setDotsPerMeterY(96*(100/2.54))
From b2e00637a2adc902df03c2559b2f5aadd94f8cbd Mon Sep 17 00:00:00 2001
From: Kovid Goyal
Date: Sat, 17 Jan 2009 14:30:00 -0800
Subject: [PATCH 11/21] IGN:Fix building in windows in a Visual Studio Command
prompt
---
setup.py | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/setup.py b/setup.py
index e7c16e6aa6..9da4647858 100644
--- a/setup.py
+++ b/setup.py
@@ -425,7 +425,11 @@ if __name__ == '__main__':
extra_link_args=['-framework', 'IOKit'])
)
- plugins = ['plugins/%s.so'%(x.name.rpartition('.')[-1]) for x in ext_modules]
+ if not iswindows:
+ plugins = ['plugins/%s.so'%(x.name.rpartition('.')[-1]) for x in ext_modules]
+ else:
+ plugins = ['plugins/%s.pyd'%(x.name.rpartition('.')[-1]) for x in ext_modules] + \
+ ['plugins/%s.pyd.manifest'%(x.name.rpartition('.')[-1]) for x in ext_modules if 'pictureflow' not in x.name]
setup(
name = APPNAME,
From 67e9eac46cd5e7328562e0b7f8b48d91d4b24779 Mon Sep 17 00:00:00 2001
From: John Schember
Date: Sun, 18 Jan 2009 11:16:19 -0500
Subject: [PATCH 12/21] Add KINDLE to avaliable device list.
---
src/calibre/devices/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/calibre/devices/__init__.py b/src/calibre/devices/__init__.py
index e68a8b3de3..ebb95a4e86 100644
--- a/src/calibre/devices/__init__.py
+++ b/src/calibre/devices/__init__.py
@@ -11,7 +11,7 @@ def devices():
from calibre.devices.prs700.driver import PRS700
from calibre.devices.cybookg3.driver import CYBOOKG3
from calibre.devices.kindle.driver import KINDLE
- return (PRS500, PRS505, PRS700, CYBOOKG3)
+ return (PRS500, PRS505, PRS700, CYBOOKG3, KINDLE)
import time
From 5a16951ded8907a33b5dd3273dacef4ac1427e03 Mon Sep 17 00:00:00 2001
From: Kovid Goyal
Date: Sun, 18 Jan 2009 09:35:56 -0800
Subject: [PATCH 13/21] New recipes for Pagina/12 and Infobae as well as an
updtaed recipe for Clarin (thanks to Darko Miletic)
---
setup.py | 5 ++-
src/calibre/gui2/images/news/infobae.png | Bin 0 -> 425 bytes
src/calibre/gui2/images/news/pagina12.png | Bin 0 -> 414 bytes
src/calibre/web/feeds/recipes/__init__.py | 2 +-
.../web/feeds/recipes/recipe_clarin.py | 9 ++--
.../web/feeds/recipes/recipe_infobae.py | 40 ++++++++++++++++++
.../web/feeds/recipes/recipe_pagina12.py | 39 +++++++++++++++++
7 files changed, 89 insertions(+), 6 deletions(-)
create mode 100644 src/calibre/gui2/images/news/infobae.png
create mode 100644 src/calibre/gui2/images/news/pagina12.png
create mode 100644 src/calibre/web/feeds/recipes/recipe_infobae.py
create mode 100644 src/calibre/web/feeds/recipes/recipe_pagina12.py
diff --git a/setup.py b/setup.py
index 9da4647858..2f0c5aad26 100644
--- a/setup.py
+++ b/setup.py
@@ -415,8 +415,9 @@ if __name__ == '__main__':
ext_modules.append(Extension('calibre.plugins.winutil',
sources=['src/calibre/utils/windows/winutil.c'],
libraries=['shell32', 'setupapi'],
- include_dirs=['C:/WinDDK/6001.18001/inc/api/',
- 'C:/WinDDK/6001.18001/inc/crt/'],
+ include_dirs=os.environ.get('INCLUDE',
+ 'C:/WinDDK/6001.18001/inc/api/;'
+ 'C:/WinDDK/6001.18001/inc/crt/').split(';'),
extra_compile_args=['/X']
))
if isosx:
diff --git a/src/calibre/gui2/images/news/infobae.png b/src/calibre/gui2/images/news/infobae.png
new file mode 100644
index 0000000000000000000000000000000000000000..6a25d93325c5af2e9cc4aa9b2747e6828a262194
GIT binary patch
literal 425
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b
zK-vS0-A-oPfdtD69Mgd`SU*F|v9*VRoJ*cAjv*GOmrnMcbXY;ad46!Q{*IYP&(4~x
z$!%xWw|T}6^L0!wOPkN6-L_eAUHCK8imms!j{VwRYs2kb#WAf6^-X6Feg|oDR*=8t!aD3G}C=T7{lJrTiH?=WBLt_?VtC3U7rMR&V(Q)
zhhOeJnyNRXQjRRuZ;8@gI%Q?`*&g1dCV}T9Jzb8lD=3NmxIbfo$PHEt-L@bu%jbuC
zuDyJxXQ-4GqFnFzf8F%my~j)bh2D0_ejfOHpT4l)f%RX1nC@fTZtvZT(08gO
zt`Q~4MX8A;sk$jZg2BkZz*5)1P}k5R#L(Qz*vQJ*P}{)3%D^CMUMfFKLvDUbW?Cfy
U4XpaY)<6vmp00i_>zopr0FghJ`2YX_
literal 0
HcmV?d00001
diff --git a/src/calibre/gui2/images/news/pagina12.png b/src/calibre/gui2/images/news/pagina12.png
new file mode 100644
index 0000000000000000000000000000000000000000..e6384e8ad92b25c9b5ef6b8faa8ee023cb50a50a
GIT binary patch
literal 414
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b
zK-vS0-A-oPfdtD69Mgd`SU*F|v9*VRoa3G@jv*GOj|OezJ)*#4BhVa>!qdewsVOi|
zq^oD5QY*XX$7GjB-R=C0c0cu|=}6Acy?c|vfA+8K0WOdBy*D^^z_R?y+SgKyb7EYQ
zjycbemT~a;`LAJ0w!tLdxpKz?83Pp0@V?Ehu1%h#u+n8o3V-d=+rK?0vM@wgGcZg`
zeJMUYYIBRw>X*-BXYPJGx#ymLDc?1|f^(X+*XO8CaJe(hjYSg(wXCjMp-&`YW%t`Q~4MX8A;sk$jZ
zg2BkZz*5)1P}k5R#K6GH(8$WjKpV&~Fz5(2I0e&?o1c=IR!Km^^+#_1fEpM)UHx3v
IIVCg!00mo'
+'''
+infobae.com
+'''
+
+from calibre.web.feeds.news import BasicNewsRecipe
+
+class Infobae(BasicNewsRecipe):
+ title = 'Infobae.com'
+ __author__ = 'Darko Miletic'
+ description = 'Informacion Libre las 24 horas'
+ oldest_article = 2
+ max_articles_per_feed = 100
+ no_stylesheets = True
+ use_embedded_content = False
+ encoding = 'iso-8859-1'
+ cover_url = 'http://www.infobae.com/imgs/header/header.gif'
+
+ html2lrf_options = [
+ '--comment' , description
+ , '--category' , 'news, Argentina'
+ , '--publisher' , 'Infobae.com'
+ ]
+
+
+
+ feeds = [
+ (u'Noticias' , u'http://www.infobae.com/adjuntos/html/RSS/hoy.xml' )
+ ,(u'Salud' , u'http://www.infobae.com/adjuntos/html/RSS/salud.xml' )
+ ,(u'Tecnologia', u'http://www.infobae.com/adjuntos/html/RSS/tecnologia.xml')
+ ,(u'Deportes' , u'http://www.infobae.com/adjuntos/html/RSS/deportes.xml' )
+ ]
+
+ def print_version(self, url):
+ main, sep, article_part = url.partition('contenidos/')
+ article_id, rsep, rrest = article_part.partition('-')
+ return u'http://www.infobae.com/notas/nota_imprimir.php?Idx=' + article_id
diff --git a/src/calibre/web/feeds/recipes/recipe_pagina12.py b/src/calibre/web/feeds/recipes/recipe_pagina12.py
new file mode 100644
index 0000000000..8b427e8ad1
--- /dev/null
+++ b/src/calibre/web/feeds/recipes/recipe_pagina12.py
@@ -0,0 +1,39 @@
+#!/usr/bin/env python
+
+__license__ = 'GPL v3'
+__copyright__ = '2008, Darko Miletic '
+'''
+pagina12.com.ar
+'''
+
+from calibre import strftime
+from calibre.web.feeds.news import BasicNewsRecipe
+
+class Pagina12(BasicNewsRecipe):
+ title = u'Pagina/12'
+ __author__ = 'Darko Miletic'
+ description = 'Noticias de Argentina y el resto del mundo'
+ oldest_article = 2
+ max_articles_per_feed = 100
+ no_stylesheets = True
+ use_embedded_content = False
+ encoding = 'cp1252'
+ cover_url = strftime('http://www.pagina12.com.ar/fotos/%Y%m%d/diario/TAPAN.jpg')
+
+ html2lrf_options = [
+ '--comment' , description
+ , '--category' , 'news, Argentina'
+ , '--publisher' , 'La Pagina S.A.'
+ ]
+
+
+ remove_tags = [
+ dict(name='div', attrs={'id':'volver'})
+ ,dict(name='div', attrs={'id':'logo' })
+ ]
+
+
+ feeds = [(u'Pagina/12', u'http://www.pagina12.com.ar/diario/rss/principal.xml')]
+
+ def print_version(self, url):
+ return url.replace('http://www.pagina12.com.ar/','http://www.pagina12.com.ar/imprimir/')
From 8d6bc29107fbda0c6968dad4f42c612a4965faa9 Mon Sep 17 00:00:00 2001
From: Kovid Goyal
Date: Sun, 18 Jan 2009 11:28:27 -0800
Subject: [PATCH 14/21] New recipes for Ambito and El Argentino by Darko
Miletic
---
src/calibre/gui2/images/news/ambito.png | Bin 0 -> 508 bytes
src/calibre/gui2/images/news/elargentino.png | Bin 0 -> 805 bytes
src/calibre/web/feeds/recipes/__init__.py | 2 +-
.../web/feeds/recipes/recipe_ambito.py | 44 ++++++++++++++
.../web/feeds/recipes/recipe_elargentino.py | 55 ++++++++++++++++++
5 files changed, 100 insertions(+), 1 deletion(-)
create mode 100644 src/calibre/gui2/images/news/ambito.png
create mode 100644 src/calibre/gui2/images/news/elargentino.png
create mode 100644 src/calibre/web/feeds/recipes/recipe_ambito.py
create mode 100644 src/calibre/web/feeds/recipes/recipe_elargentino.py
diff --git a/src/calibre/gui2/images/news/ambito.png b/src/calibre/gui2/images/news/ambito.png
new file mode 100644
index 0000000000000000000000000000000000000000..e0a6f409cf01248d35328d5a43c3cb78981d2139
GIT binary patch
literal 508
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b
zK-vS0-A-oPfdtD69Mgd`SU*F|v9*U87#LMOT^vI!PA7j^WASS~BmaYE35hR!E~f=d
zdXkm^1UtU}(RMz!q`RO}jg3j+maEvhpRfDvd1_a`UvOe`!sR6@C(kCV)ID3<
z3A&u(`B5d!5AS_mzk?TKk_K03;)W|ihYY@eG{x8dIV#}((P>scQ&(Eb?H!g85?RTn
zAEXy7KhnQQ(sF|Y5FBB>`BA!I&4bh5?F*JKZs$K|pfSIc_2l__$tfy3C3jc`9G*G5
zS#mq$^!N2iAol@HPwFU}==xDeuOX>nl8U)=?i#i`+CZxke|-9@AGSZ4mpSFEfPQRh
z#m|52apDhnj#QuDpQIwy#HPR;q0_-#G$FlVo{)X>>Wva{|C1#O{@k(_IeADx^wORU
zCFhfQoG&m|)iE$Mt40*-YTYsbhMsDPYeY$MQEFmIs%{F9U@$T;u+%j$)HSpSF|@QY
tGO{u@)iyA&GBB9Bb5agWLvDUbW?Cfy4W~GsL;y7~c)I$ztaD0e0sy%tz9|3z
literal 0
HcmV?d00001
diff --git a/src/calibre/gui2/images/news/elargentino.png b/src/calibre/gui2/images/news/elargentino.png
new file mode 100644
index 0000000000000000000000000000000000000000..1e3e64d8a512fc1eba6e2352a617e090892befcd
GIT binary patch
literal 805
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b
zK-vS0-A-oPfdtD69Mgd`SU*F|v9*U87?}J#T^vI!PPb0>^%oA5Xr2Ev>-CnB6$^P+
zs){-%WlU|&Mt(v)YoNk!;@Z~E2`7wzg}W~67a~LkIC?fLym(((a*qR
z`3dG+H)4eww%+BF4&{EC&%e*Sy5}X=GF6FJViWfWT4`^eP$M{{cymY4v};e*mlT&?
z+R3&|_1B|^+gYU(5{o$Yt4)qt|LA(kwDqkWH|#e^vpxxEDp_~#^V(U?bNF@{nsC1K
zUYdP=-4qYE(rI0}&ko5M{Z!+g>})gVOLA0GtA8p`kl|6ATh^%rs~2nzz0y()GixS`
zhcln6N?TI@@YyRlpsN~wa>}pNOkR-w>f+g$8_n^PJ>5zff?kKV&zWU3WBv!mgs3K;
zeV#_EJ-YWau_qT^_tk{-nWc)~NjW$b+ku0P9x7{Mqw)ftc+<48^W-8gQ
zRD5u`(K787hR(|0)KBg2s0z)S|9#V+%|~D7^X@v7ruO8Z?&00>xmnX5oZGS8zVrD0
z&zTiFV~@Y#3iFnYQ$1%?<@V5=^TFE%E8Sa;1CyC*iEBhja#3nxNvduNkYF$}FtF4$
zFw`})2r;y@GBU6-G1oRQure^<5sLyPW3YzY{FKbJN&*^!m+OQAH86O(`njxgN@xNA
Dhy6&K
literal 0
HcmV?d00001
diff --git a/src/calibre/web/feeds/recipes/__init__.py b/src/calibre/web/feeds/recipes/__init__.py
index 8b0165b184..e6bcdaed9c 100644
--- a/src/calibre/web/feeds/recipes/__init__.py
+++ b/src/calibre/web/feeds/recipes/__init__.py
@@ -22,7 +22,7 @@ recipe_modules = ['recipe_' + r for r in (
'time_magazine', 'endgadget', 'fudzilla', 'nspm_int', 'nspm', 'pescanik',
'spiegel_int', 'themarketticker', 'tomshardware', 'xkcd', 'ftd', 'zdnet',
'joelonsoftware', 'telepolis', 'common_dreams', 'nin', 'tomshardware_de',
- 'pagina12', 'infobae',
+ 'pagina12', 'infobae', 'ambito', 'elargentino',
)]
import re, imp, inspect, time, os
diff --git a/src/calibre/web/feeds/recipes/recipe_ambito.py b/src/calibre/web/feeds/recipes/recipe_ambito.py
new file mode 100644
index 0000000000..56528c27c0
--- /dev/null
+++ b/src/calibre/web/feeds/recipes/recipe_ambito.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+
+__license__ = 'GPL v3'
+__copyright__ = '2008, Darko Miletic '
+'''
+ambito.com
+'''
+
+
+from calibre.web.feeds.news import BasicNewsRecipe
+
+class Ambito(BasicNewsRecipe):
+ title = 'Ambito.com'
+ __author__ = 'Darko Miletic'
+ description = 'Informacion Libre las 24 horas'
+ oldest_article = 2
+ max_articles_per_feed = 100
+ no_stylesheets = True
+ use_embedded_content = False
+ encoding = 'iso--8859-1'
+ cover_url = 'http://www.ambito.com/img/logo_.jpg'
+
+ html2lrf_options = [
+ '--comment' , description
+ , '--category' , 'news, Argentina'
+ , '--publisher' , title
+ ]
+
+ feeds = [
+ (u'Principales Noticias', u'http://www.ambito.com/rss/noticiasp.asp' )
+ ,(u'Economia' , u'http://www.ambito.com/rss/noticias.asp?S=Econom%EDa' )
+ ,(u'Politica' , u'http://www.ambito.com/rss/noticias.asp?S=Pol%EDtica' )
+ ,(u'Informacion General' , u'http://www.ambito.com/rss/noticias.asp?S=Informaci%F3n%20General')
+ ,(u'Agro' , u'http://www.ambito.com/rss/noticias.asp?S=Agro' )
+ ,(u'Internacionales' , u'http://www.ambito.com/rss/noticias.asp?S=Internacionales' )
+ ,(u'Deportes' , u'http://www.ambito.com/rss/noticias.asp?S=Deportes' )
+ ,(u'Espectaculos' , u'http://www.ambito.com/rss/noticias.asp?S=Espect%E1culos' )
+ ,(u'Tecnologia' , u'http://www.ambito.com/rss/noticias.asp?S=Tecnologia' )
+ ,(u'Salud' , u'http://www.ambito.com/rss/noticias.asp?S=Salud' )
+ ,(u'Ambito Nacional' , u'http://www.ambito.com/rss/noticias.asp?S=Ambito%20Nacional' )
+ ]
+
+ def print_version(self, url):
+ return url.replace('http://www.ambito.com/noticia.asp?','http://www.ambito.com/noticias/imprimir.asp?')
diff --git a/src/calibre/web/feeds/recipes/recipe_elargentino.py b/src/calibre/web/feeds/recipes/recipe_elargentino.py
new file mode 100644
index 0000000000..7aee232787
--- /dev/null
+++ b/src/calibre/web/feeds/recipes/recipe_elargentino.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python
+
+__license__ = 'GPL v3'
+__copyright__ = '2008, Darko Miletic '
+'''
+elargentino.com
+'''
+
+from calibre.web.feeds.news import BasicNewsRecipe
+
+class ElArgentino(BasicNewsRecipe):
+ title = 'ElArgentino.com'
+ __author__ = 'Darko Miletic'
+ description = 'Informacion Libre las 24 horas'
+ oldest_article = 2
+ max_articles_per_feed = 100
+ no_stylesheets = True
+ use_embedded_content = False
+ encoding = 'utf8'
+ cover_url = 'http://www.elargentino.com/TemplateWeb/MediosFooter/tapa_elargentino.png'
+
+ html2lrf_options = [
+ '--comment' , description
+ , '--category' , 'news, Argentina'
+ , '--publisher' , 'ElArgentino.com'
+ ]
+
+ remove_tags = [
+ dict(name='div', attrs={'id':'noprint' })
+ ,dict(name='div', attrs={'class':'encabezadoImprimir'})
+ ,dict(name='a' , attrs={'target':'_blank' })
+ ]
+
+ feeds = [
+ (u'Portada' , u'http://www.elargentino.com/Highlights.aspx?Content-Type=text/xml&ChannelDesc=Home' )
+ ,(u'Pais' , u'http://www.elargentino.com/Highlights.aspx?ParentType=Section&ParentId=112&Content-Type=text/xml&ChannelDesc=Pa%C3%ADs' )
+ ,(u'Economia' , u'http://www.elargentino.com/Highlights.aspx?ParentType=Section&ParentId=107&Content-Type=text/xml&ChannelDesc=Econom%C3%ADa' )
+ ,(u'Mundo' , u'http://www.elargentino.com/Highlights.aspx?ParentType=Section&ParentId=113&Content-Type=text/xml&ChannelDesc=Mundo' )
+ ,(u'Tecnologia' , u'http://www.elargentino.com/Highlights.aspx?ParentType=Section&ParentId=118&Content-Type=text/xml&ChannelDesc=Tecnolog%C3%ADa' )
+ ,(u'Espectaculos', u'http://www.elargentino.com/Highlights.aspx?ParentType=Section&ParentId=114&Content-Type=text/xml&ChannelDesc=Espect%C3%A1culos')
+ ,(u'Deportes' , u'http://www.elargentino.com/Highlights.aspx?ParentType=Section&ParentId=106&Content-Type=text/xml&ChannelDesc=Deportes' )
+ ,(u'Sociedad' , u'http://www.elargentino.com/Highlights.aspx?ParentType=Section&ParentId=109&Content-Type=text/xml&ChannelDesc=Sociedad' )
+ ,(u'Entrevistas' , u'http://www.elargentino.com/Highlights.aspx?ParentType=Section&ParentId=115&Content-Type=text/xml&ChannelDesc=Entrevistas' )
+ ]
+
+ def print_version(self, url):
+ main, sep, article_part = url.partition('/nota-')
+ article_id, rsep, rrest = article_part.partition('-')
+ return u'http://www.elargentino.com/Impresion.aspx?Id=' + article_id
+
+ def preprocess_html(self, soup):
+ mtag = ''
+ soup.head.insert(0,mtag)
+ soup.prettify()
+ return soup
From df1c2911af21aedfc933357713311629536c0609 Mon Sep 17 00:00:00 2001
From: John Schember
Date: Sun, 18 Jan 2009 16:39:01 -0500
Subject: [PATCH 15/21] Cybook: Generate thumbnail file when adding books to
device.
---
src/calibre/devices/cybookg3/driver.py | 74 ++++++++++++++++++-
src/calibre/devices/cybookg3/t2b.py | 48 ++++++++++++
.../web/feeds/recipes/recipe_clarin.py | 3 +-
3 files changed, 123 insertions(+), 2 deletions(-)
create mode 100644 src/calibre/devices/cybookg3/t2b.py
diff --git a/src/calibre/devices/cybookg3/driver.py b/src/calibre/devices/cybookg3/driver.py
index 517baf7407..ea6376df0d 100644
--- a/src/calibre/devices/cybookg3/driver.py
+++ b/src/calibre/devices/cybookg3/driver.py
@@ -4,9 +4,11 @@ __copyright__ = '2009, John Schember '
Device driver for Bookeen's Cybook Gen 3
'''
-import os, fnmatch
+import os, shutil
+from itertools import cycle
from calibre.devices.usbms.driver import USBMS
+import calibre.devices.cybookg3.t2b as t2b
class CYBOOKG3(USBMS):
# Ordered list of supported formats
@@ -29,6 +31,76 @@ class CYBOOKG3(USBMS):
EBOOK_DIR_MAIN = "eBooks"
SUPPORTS_SUB_DIRS = True
+
+ def upload_books(self, files, names, on_card=False, end_session=True,
+ metadata=None):
+ if on_card and not self._card_prefix:
+ raise ValueError(_('The reader has no storage card connected.'))
+
+ if not on_card:
+ path = os.path.join(self._main_prefix, self.EBOOK_DIR_MAIN)
+ else:
+ path = os.path.join(self._card_prefix, self.EBOOK_DIR_CARD)
+
+ def get_size(obj):
+ if hasattr(obj, 'seek'):
+ obj.seek(0, os.SEEK_END)
+ size = obj.tell()
+ obj.seek(0)
+ return size
+ return os.path.getsize(obj)
+
+ sizes = map(get_size, files)
+ size = sum(sizes)
+
+ if on_card and size > self.free_space()[2] - 1024*1024:
+ raise FreeSpaceError(_("There is insufficient free space on the storage card"))
+ if not on_card and size > self.free_space()[0] - 2*1024*1024:
+ raise FreeSpaceError(_("There is insufficient free space in main memory"))
+
+ paths = []
+ names = iter(names)
+ metadata = iter(metadata)
+
+ for infile in files:
+ newpath = path
+ mdata = metadata.next()
+
+ if self.SUPPORTS_SUB_DIRS:
+ if 'tags' in mdata.keys():
+ for tag in mdata['tags']:
+ if tag.startswith('/'):
+ newpath += tag
+ newpath = os.path.normpath(newpath)
+ break
+
+ if not os.path.exists(newpath):
+ os.makedirs(newpath)
+
+ filepath = os.path.join(newpath, names.next())
+ paths.append(filepath)
+
+ if hasattr(infile, 'read'):
+ infile.seek(0)
+
+ dest = open(filepath, 'wb')
+ shutil.copyfileobj(infile, dest, 10*1024*1024)
+
+ dest.flush()
+ dest.close()
+ else:
+ shutil.copy2(infile, filepath)
+
+ coverdata = None
+ if 'cover' in mdata.keys():
+ if mdata['cover'] != None:
+ coverdata = mdata['cover'][2]
+
+ t2bfile = open('%s_6090.t2b' % (os.path.splitext(filepath)[0]), 'wb')
+ t2b.write_t2b(t2bfile, coverdata)
+ t2bfile.close()
+
+ return zip(paths, cycle([on_card]))
def delete_books(self, paths, end_session=True):
for path in paths:
diff --git a/src/calibre/devices/cybookg3/t2b.py b/src/calibre/devices/cybookg3/t2b.py
new file mode 100644
index 0000000000..0baa7a1060
--- /dev/null
+++ b/src/calibre/devices/cybookg3/t2b.py
@@ -0,0 +1,48 @@
+__license__ = 'GPL v3'
+__copyright__ = '2009, John Schember '
+'''
+Write a t2b file to disk.
+'''
+
+import Image, StringIO
+
+DEFAULT_T2B_DATA = '\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x0f\xff\xff\xff\xf0\xff\x0f\xc3\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x00\xff\xff\xff\xf0\xff\x0f\xc3\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\xff\xf0\xff\xff\xff\xf0\xff\xff\xc3\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc3\xff\xff\xff\xff\xff\xf0\xff\xff\xc3\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x07\xff\xff\xfc\x00?\xf0\xff\x0f\xc3\x00?\xf0\xc0\xfe\x00?\xff\xff\xff\xff\xff\xff\xff\x0f\xff\xff\xf0<\x0f\xf0\xff\x0f\xc0,\x0f\xf0\x0e\xf0,\x0f\xff\xff\xff\xff\xff\xff\xff\x0f\xff\xff\xff\xff\xc3\xf0\xff\x0f\xc0\xff\x0f\xf0\xff\xf0\xff\xc7\xff\xff\xff\xff\xff\xff\xff\x0f\xff\xff\xff\xff\xc3\xf0\xff\x0f\xc3\xff\xc3\xf0\xff\xc3\xff\xc3\xff\xff\xff\xff\xff\xff\xff\x0f\xff\xff\xff\x00\x03\xf0\xff\x0f\xc3\xff\xc3\xf0\xff\xc3\xff\xc3\xff\xff\xff\xff\xff\xff\xff\x0f\xff\xff\xf0\x1f\xc3\xf0\xff\x0f\xc3\xff\xc3\xf0\xff\xc0\x00\x03\xff\xff\xff\xff\xff\xff\xff\x0b\xff\xff\xf0\xff\xc3\xf0\xff\x0f\xc3\xff\xc3\xf0\xff\xc3\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc3\xff\xff\xf3\xff\xc3\xf0\xff\x0f\xc3\xff\xc3\xf0\xff\xc3\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\xff\xfc\xf0\xff\x03\xf0\xff\x0f\xc0\xff\x0f\xf0\xff\xf0\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x0f\x00\xf08\x03\xf0\xff\x0f\xc0,\x0f\xf0\xff\xf0\x1f\x03\xff\xff\xff\xff\xff\xff\xff\xff\x00\x0f\xfc\x00\xc3\xf0\xff\x0f\xc3\x00?\xf0\xff\xff\x00\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\xfe\x94\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x0f\xff\xff\xff\xff\xff\xff\xfc\x7f\xfe\x94\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x0f\xff\xfe\xa9@\xff\xff\xff\xff\xff\xff\xfc?\xfe\xa4\xff\xff\xff\xff\xff\xff\xff\xff\xfc\xff\xff\xff\xe9P\xff\xff\xff\xff\xff\xff\xfe/\xfe\xa8\xff\xff\xff\xff\xff\xff\xff\xff\xfc\xff\xff\xff\xf9T\xff\xff\xff\xff\xf0@\x00+\xfa\xa8?\xff\xff\xff\xff\xff\xff\xff\xfc\xbf\xff\xff\xf9T\xff\xff\xff\xff\xcb\xe4}*\xaa\xaa?\xff\xff\xff\xff\xff\xff\xff\xfc\xbf\xff\xff\xe9T\xff\xff\xff\xff\xc7\xe4\xfd\x1a\xaa\xaa?\xff\xff\xff\xff\xff\xff\xff\xfc\xaf\xea\xaa\xa6\xa4\xff@\x00\x0f\xc3\xe8\xfe\x1a\xaa\xaa?\xff\xff\xff\xff\xff\xff\xff\xfcj\x95UZ\xa4\x00\x7f\xfe\x90\x03\xe8\xfe\n\xaa\xaa?\xff\xff\xff\xff\xff\xff\xff\xfcj\x95UZ\xa4?\xff\xff\xa5C\xe8\xfe\x06\xaa\xaa?\xff\xff\xff\xff\xff\xff\xff\xfcj\x95UZ\xa4?\xff\xff\xeaC\xe8\xbe\x06\xaa\xaa\x0f\xff\xff\xff\xff\xff\xff\xff\xfcj\x95UZ\xa4/\xff\xff\xea\x82\xe8j\x06\xaa\xaa\x0f\xff\xff\xff\xff\xff\xff\xff\xfcj\x95UZ\xa4/\xff\xff\xaa\x82\xe8*F\xaa\xaa\x8f\xff\xff\xff\xff\xff\xff\xff\xfcj\x95UZ\xa4+\xff\xfe\xaa\x82\xe8*\x86\xaa\xaa\x8f\xff\xff\x80\xff\xff\xff\xff\xfcj\x95UV\xa4\x1a\xfa\xaa\xaa\x82\xe8*\x86\xaa\xaa\x8f\xf0\x00T?\xff\xff\xff\xfcj\x95UV\xa4\x1a\xfa\xaa\xaa\x82\xe8*\x81\xaa\xaa\x8c\x03\xff\x95?\xff\xff\xff\xfcj\x95UV\xa4\x1a\xfa\xaa\xaa\x82\xe8*\x81\xaa\xaa\x80\xbf\xff\x95?\xff\xff\xff\xfcj\x95UV\xa4\x1a\xfa\xaa\xaa\x82\xe8*\x81\xaa\xaa\x9b\xff\xff\x95\x0f\xff\xff\xff\xfcj\x95UV\xa4\x1a\xfa\xaa\xaa\x82\xe8\x1a\x81\xaa\xaa\x9a\xff\xfe\x95\x0f\xff\xff\xff\xfcj\x95UV\xa4\x1a\xfa\xaa\xaa\x82\xe8\n\x81\xaa\xaa\xa6\xbf\xfeUO\xff\xff\xff\xfcj\x95UV\xa4\x1a\xfa\xaa\xaa\x82\xa8\n\x91j\xaa\xa5\xaa\xa9ZO\xff\xff\xff\xfcj\x95UV\xa4\x1a\xfa\xaa\xaa\x82\xa8\n\xa0j\xaa\xa5Z\x95ZO\xff\xff\xff\xfcj\x95UV\xa4*\xfa\xaa\xaa\x82\xa9\n\xa0j\xaa\xa5UUZC\xff\xff\xff\xfcj\x95UV\xa4*\xfa\xaa\xaa\x82\xaa\n\xa0j\xaa\xa4UUZS\xff\xff\xff\xfcZ\x95UV\xa4*\xfa\xaa\xaa\x82\xaa\n\xa0j\xaa\xa4UUZS\xff\xff\xff\xfcZ\x95UU\xa4*\xfa\xaa\xaa\x82\xaa\n\xa0j\xaa\xa8UUVS\xff\xff\xff\xfcZ\x95UU\xa4*\xea\xaa\xaa\x82\xaa\x06\xa0Z\xaa\xa8UUV\x93\xff\xff\xff\xfcZ\x95UU\xa4*\xaa\xaa\xaa\x81\xaa\x02\xa0\x1a\xaa\xa8UUV\x90\xff\xff\xff\xfcZ\x95UU\xa4*\xaa\xaa\xaa\x80\xaa\x02\xa0\x1a\xaa\xa8\x15UU\x94\xff\xff\xff\xfcZ\x95UU\xa4*\xaa\xaa\xaa\x80\xaa"\xa0\x1a\xaa\xa8\x15UU\x94\xff\xff\xff\xfcZ\x95UU\xa4*\xaa\xaa\xaa\x80\xaa2\xa4\x16\xaa\xa8\x15UU\x94\xff\xff\xff\xfcZ\x95UU\xa4*\xaa\xaa\xaa\x80\xaa2\xa8\x16\xa6\xa9\x15UU\x94\xff\xff\xff\xfcZ\x95UU\xa4*\xaa\xaa\xaa\x80\xaa2\xa8\x16\xa6\xa9\x05UUT?\xff\xff\xfcZ\x95UU\xa4*\xaa\xaa\xaa\x84\xaa2\xa8\x16\xaa\xaa\x05UUU?\xff\xff\xfcZ\x95UU\xa4*\xaa\xaa\xaa\x88\xaa2\xa8\x06\xaa\xaa\x05UUU?\xff\xff\xfcZ\x95UU\xa4*\xaa\xaa\xaa\x8c\xaa1\xa8\xc5\xaa\xaa\x05UUU?\xff\xff\xfcZ\x95UU\xa4*\xaa\xaa\xaa\x8c\xaa0\xa8E\xa9\xaa\x05UUU/\xff\xff\xfcZ\x95UU\xa4*\xaa\xaa\xaa\x8c\xaa<\xa8\x05\xa9\xaaAUUU\x0f\xff\xff\xfcZ\x95UU\xa4*\xaa\xaa\xaa\x8c\xaa<\xa8\x05\xa9\xaaAUUUO\xff\xff\xfcZ\x95UU\xa4*\xaa\xaa\xaa\x8c\xaa<\xa9\x05\xaa\xaaAUUUO\xff\xff\xfcZ\x95UU\xa4*\xaa\xaa\xaa\x8c\xaa\x1c\xaa\x01\xaa\xaa\x81UUUO\xff\xff\xfcZ\x95UU\xa4*\xaa\xaa\xaa\x8c\xaa\x0c\xaa\x01\xaa\xaa\x81UUUO\xff\xff\xfcZ\x95UU\xa4*\xaa\xaa\xaa\x8c\xaa\x0c\xaa1j\xaa\x80UUUC\xff\xff\xfcZ\x95UU\xa4*\xaa\xaa\xaa\x8c\xaa\x0cj1jj\x90UUUS\xff\xff\xfcZ\x95UU\xa4*\xaa\xaa\xaa\x8c\xaa\x0c*1jj\x90UUUS\xff\xff\xfcZ\x95UU\xa4*\xaa\xaa\xaa\x8c\xaaL*1jj\xa0UUUS\xff\xff\xfcZ\x95UU\xa4*\xaa\xaa\xaa\x8c\xaa\x8f* j\xaa\xa0\x15UUS\xff\xff\xfcZ\x95UU\xa4*\xaa\xaa\xaa\x8c\xaa\x8f*@j\xaa\xa0\x15UUP\xff\xff\xfcZ\x95UU\xa4*\xaa\xaa\xaa\x8c\xaa\x8f*\x8cZ\xaa\xa1\x15UUT\xff\xff\xfcZ\x95UU\xa4j\xaa\xaa\xaa\x8c\xaa\x8f*\x8cZ\x9a\xa0\x15UUT\xff\xff\xfcZ\x95UU\xa4j\xaa\xaa\xaa\x8c\xaa\x8f*\x8cZ\x9a\xa0\x15UUT\xff\xff\xfcZ\x95UU\xa4j\xaa\xaa\xaa\x8c\xaa\x8f\x1a\x8cZ\x9a\xa4\x15UUT?\xff\xfcZ\x95UU\x94j\xaa\xaa\xaa\x8cj\x8f\n\x8cVj\xa4\x05UU\xa4?\xff\xfcVUUU\xa4j\xaa\xaa\xaa\x8cj\x8fJ\x8c\x16\xaa\xa8\xc5UZ\xa5?\xff\xfcUUUV\xa4j\xaa\xaa\xaa\x8cj\x8f\xca\x8f\x16\xaa\xa8\xc5V\xaa\xa5?\xff\xfcUj\xaa\xaa\xa4j\xaa\xaa\xaa\x8cj\x8f\xca\x8f\x1a\xaa\xa8\x05Z\xaaU?\xff\xfcV\xaa\xaa\xaa\xa5j\xaa\xaa\xaa\x8e*\x8f\xca\x83\x1a\xaa\xa4\x01eUU?\xff\xfcZ\xaa\xaa\xaa\xa5j\xaa\xaa\xaa\x8f*\x8f\xca\x83\x1a\xa5U\x01U\x00\x00\x0f\xff\xfcUUUUUZ\xaa\xaa\xaaO%\x8f\xc6\x93\x15\x00\x001@\x0f\xff\xff\xff\xfcP\x00\x00\x00\x15\x00\x00\x00\x00\x0f\x00\x07\xc0\x03\x00\xff\xff0\x1f\xff\xff\xff\xff\xfc\x00\xff\xff\xf8\x00?\xff\xff\xff\x0f?\xc7\xc3\xf7\x0f\xff\xff\xf1\xff\xff\xff\xff\xff\xfc\xff\xff\xff\xff\xf4\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'
+
+def reduce_color(c):
+ if c <= 64:
+ return 0
+ elif c > 64 and c <= 128:
+ return 1
+ elif c > 128 and c <= 192:
+ return 2
+ else:
+ return 3
+
+def i2b(n):
+ return "".join([str((n >> y) & 1) for y in range(1, -1, -1)])
+
+def write_t2b(t2bfile, coverdata=None):
+ '''
+ t2bfile is a file handle ready to write binary data to disk.
+ coverdata is a string representation of a JPEG file.
+ '''
+ if coverdata != None:
+ coverdata = StringIO.StringIO(coverdata)
+ cover = Image.open(coverdata).convert("L")
+ cover.thumbnail((96, 144))
+ t2bcover = Image.new('L', (96, 144), 'white')
+
+ x, y = cover.size
+ t2bcover.paste(cover, ((96-x)/2, (144-y)/2))
+
+ px = []
+ pxs = t2bcover.getdata()
+ for i in range(len(pxs)):
+ px.append(pxs[i])
+ if len(px) >= 4:
+ binstr = i2b(reduce_color(px[0])) + i2b(reduce_color(px[1])) + i2b(reduce_color(px[2])) + i2b(reduce_color(px[3]))
+ t2bfile.write(chr(int(binstr, 2)))
+ px = []
+ else:
+ t2bfile.write(DEFAULT_T2B_DATA)
+
diff --git a/src/calibre/web/feeds/recipes/recipe_clarin.py b/src/calibre/web/feeds/recipes/recipe_clarin.py
index 1840be291f..f205dc6f3d 100644
--- a/src/calibre/web/feeds/recipes/recipe_clarin.py
+++ b/src/calibre/web/feeds/recipes/recipe_clarin.py
@@ -7,6 +7,7 @@ clarin.com
'''
from calibre import strftime
+from calibre.web.feeds.news import BasicNewsRecipe
class Clarin(BasicNewsRecipe):
title = 'Clarin'
@@ -47,4 +48,4 @@ class Clarin(BasicNewsRecipe):
rest = artl.partition('-0')[-1]
lmain = rest.partition('.')[0]
return 'http://www.servicios.clarin.com/notas/jsp/clarin/v9/notas/imprimir.jsp?pagid=' + lmain
-
\ No newline at end of file
+
From edd7ef00b183647ff5f766fd35c8aaedfce8adc2 Mon Sep 17 00:00:00 2001
From: Kovid Goyal
Date: Sun, 18 Jan 2009 14:00:47 -0800
Subject: [PATCH 16/21] Add progress dialog for saving to disk. Also Fix #1624
(Reading meta-data dialogue box doesn't close in windows XP)
---
src/calibre/ebooks/lrf/comic/convert_from.py | 12 +--
src/calibre/gui2/dialogs/progress.py | 48 +++++++++++
src/calibre/gui2/dialogs/progress.ui | 72 ++++++++++++++++
src/calibre/gui2/library.py | 13 ++-
src/calibre/gui2/main.py | 84 +++++++++++--------
src/calibre/library/database.py | 18 ++--
src/calibre/trac/bzr_commit_plugin.py | 1 -
.../web/feeds/recipes/recipe_clarin.py | 3 +-
8 files changed, 196 insertions(+), 55 deletions(-)
create mode 100644 src/calibre/gui2/dialogs/progress.py
create mode 100644 src/calibre/gui2/dialogs/progress.ui
diff --git a/src/calibre/ebooks/lrf/comic/convert_from.py b/src/calibre/ebooks/lrf/comic/convert_from.py
index 0569bf3733..c22f1745ae 100755
--- a/src/calibre/ebooks/lrf/comic/convert_from.py
+++ b/src/calibre/ebooks/lrf/comic/convert_from.py
@@ -10,11 +10,6 @@ Based on ideas from comiclrf created by FangornUK.
import os, sys, shutil, traceback, textwrap
from uuid import uuid4
-try:
- from reportlab.pdfgen import canvas
- _reportlab = True
-except:
- _reportlab = False
@@ -396,10 +391,9 @@ def create_lrf(pages, profile, opts, thumbnail=None):
def create_pdf(pages, profile, opts, thumbnail=None):
width, height = PROFILES[profile]
-
- if not _reportlab:
- raise RuntimeError('Failed to load reportlab')
-
+
+ from reportlab.pdfgen import canvas
+
pdf = canvas.Canvas(filename=opts.output, pagesize=(width,height+15))
pdf.setAuthor(opts.author)
pdf.setTitle(opts.title)
diff --git a/src/calibre/gui2/dialogs/progress.py b/src/calibre/gui2/dialogs/progress.py
new file mode 100644
index 0000000000..2543cefb4d
--- /dev/null
+++ b/src/calibre/gui2/dialogs/progress.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+__license__ = 'GPL v3'
+__copyright__ = '2009, Kovid Goyal kovid@kovidgoyal.net'
+__docformat__ = 'restructuredtext en'
+
+''''''
+
+from PyQt4.Qt import QDialog, SIGNAL, Qt
+
+from calibre.gui2.dialogs.progress_ui import Ui_Dialog
+
+class ProgressDialog(QDialog, Ui_Dialog):
+
+ def __init__(self, title, msg='', min=0, max=99, parent=None):
+ QDialog.__init__(self, parent)
+ self.setupUi(self)
+ self.setWindowTitle(title)
+ self.title.setText(title)
+ self.message.setText(msg)
+ self.setWindowModality(Qt.ApplicationModal)
+ self.set_min(min)
+ self.set_max(max)
+ self.canceled = False
+
+ self.connect(self.button_box, SIGNAL('rejected()'), self._canceled)
+
+ def set_msg(self, msg=''):
+ self.message.setText(msg)
+
+ def set_value(self, val):
+ self.bar.setValue(val)
+
+ def set_min(self, min):
+ self.bar.setMinimum(min)
+
+ def set_max(self, max):
+ self.bar.setMaximum(max)
+
+ def _canceled(self, *args):
+ self.canceled = True
+ self.button_box.setDisabled(True)
+ self.title.setText(_('Aborting...'))
+
+ def keyPressEvent(self, ev):
+ if ev.key() == Qt.Key_Escape:
+ self._canceled()
+ else:
+ QDialog.keyPressEvent(self, ev)
\ No newline at end of file
diff --git a/src/calibre/gui2/dialogs/progress.ui b/src/calibre/gui2/dialogs/progress.ui
new file mode 100644
index 0000000000..60488be62d
--- /dev/null
+++ b/src/calibre/gui2/dialogs/progress.ui
@@ -0,0 +1,72 @@
+
+ Dialog
+
+
+
+ 0
+ 0
+ 712
+ 308
+
+
+
+ Dialog
+
+
+
+ :/images/jobs.svg:/images/jobs.svg
+
+
+ -
+
+
+
+ 75
+ true
+
+
+
+ TextLabel
+
+
+ Qt::AlignCenter
+
+
+ true
+
+
+
+ -
+
+
+ 0
+
+
+
+ -
+
+
+ TextLabel
+
+
+ Qt::AlignCenter
+
+
+ true
+
+
+
+ -
+
+
+ QDialogButtonBox::Abort
+
+
+
+
+
+
+
+
+
+
diff --git a/src/calibre/gui2/library.py b/src/calibre/gui2/library.py
index 792d011883..8a737fd608 100644
--- a/src/calibre/gui2/library.py
+++ b/src/calibre/gui2/library.py
@@ -198,13 +198,18 @@ class BooksModel(QAbstractTableModel):
''' Return list indices of all cells in index.row()'''
return [ self.index(index.row(), c) for c in range(self.columnCount(None))]
- def save_to_disk(self, rows, path, single_dir=False, single_format=None):
+ def save_to_disk(self, rows, path, single_dir=False, single_format=None,
+ callback=None):
rows = [row.row() for row in rows]
if single_format is None:
- return self.db.export_to_dir(path, rows, self.sorted_on[0] == 'authors',
- single_dir=single_dir)
+ return self.db.export_to_dir(path, rows,
+ self.sorted_on[0] == 'authors',
+ single_dir=single_dir,
+ callback=callback)
else:
- return self.db.export_single_format_to_dir(path, rows, single_format)
+ return self.db.export_single_format_to_dir(path, rows,
+ single_format,
+ callback=callback)
def delete_books(self, indices):
diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py
index 6ff5df412d..b04ad18c97 100644
--- a/src/calibre/gui2/main.py
+++ b/src/calibre/gui2/main.py
@@ -28,6 +28,7 @@ from calibre.gui2.cover_flow import CoverFlow, DatabaseImages, pictureflowerror
from calibre.library.database import LibraryDatabase
from calibre.gui2.dialogs.scheduler import Scheduler
from calibre.gui2.update import CheckForUpdates
+from calibre.gui2.dialogs.progress import ProgressDialog
from calibre.gui2.main_window import MainWindow, option_parser as _option_parser
from calibre.gui2.main_ui import Ui_MainWindow
from calibre.gui2.device import DeviceManager
@@ -598,29 +599,26 @@ class Main(MainWindow, Ui_MainWindow):
root = choose_dir(self, 'recursive book import root dir dialog', 'Select root folder')
if not root:
return
- progress = QProgressDialog('', '&'+_('Stop'),
- 0, 0, self)
- progress.setWindowModality(Qt.ApplicationModal)
- progress.setWindowTitle(_('Adding books recursively...'))
+ progress = ProgressDialog(_('Adding books recursively...'),
+ min=0, max=0, parent=self)
progress.show()
def callback(msg):
if msg != '.':
- progress.setLabelText((_('Added ')+msg) if msg else _('Searching...'))
- stop = progress.wasCanceled()
+ progress.set_msg((_('Added ')+msg) if msg else _('Searching...'))
QApplication.processEvents()
QApplication.sendPostedEvents()
QApplication.flush()
- return stop
+ return progress.canceled
try:
duplicates = self.library_view.model().db.recursive_import(root, single, callback=callback)
finally:
- progress.hide()
- progress.close()
+ progress.hide()
if duplicates:
files = _('Books with the same title as the following already exist in the database. Add them anyway?
')
for mi, formats in duplicates:
files += '- '+mi.title+'
\n'
- d = WarningDialog(_('Duplicates found!'), _('Duplicates found!'), files+'
', self)
+ d = WarningDialog(_('Duplicates found!'), _('Duplicates found!'),
+ files+'', self)
if d.exec_() == QDialog.Accepted:
for mi, formats in duplicates:
self.library_view.model().db.import_book(mi, formats )
@@ -686,15 +684,13 @@ class Main(MainWindow, Ui_MainWindow):
return
# Get format and metadata information
formats, metadata, names, infos = [], [], [], []
- progress = QProgressDialog(_('Reading metadata...'), _('Stop'), 0, len(paths), self)
- progress.setWindowTitle(_('Adding books...'))
- progress.setWindowModality(Qt.ApplicationModal)
- progress.setLabelText(_('Reading metadata...'))
+ progress = ProgressDialog(_('Adding books...'), _('Reading metadata...'),
+ min=0, max=len(paths), parent=self)
progress.show()
try:
for c, book in enumerate(paths):
- progress.setValue(c)
- if progress.wasCanceled():
+ progress.set_value(c)
+ if progress.canceled:
return
format = os.path.splitext(book)[1]
format = format[1:] if format else None
@@ -713,15 +709,14 @@ class Main(MainWindow, Ui_MainWindow):
infos.append({'title':mi.title, 'authors':', '.join(mi.authors),
'cover':self.default_thumbnail, 'tags':[]})
title = mi.title if isinstance(mi.title, unicode) else mi.title.decode(preferred_encoding, 'replace')
- progress.setLabelText(_('Read metadata from ')+title)
+ progress.set_msg(_('Read metadata from ')+title)
if not to_device:
- progress.setLabelText(_('Adding books to database...'))
+ progress.set_msg(_('Adding books to database...'))
model = self.library_view.model()
paths = list(paths)
duplicates, number_added = model.add_books(paths, formats, metadata)
- progress.cancel()
if duplicates:
files = _('Books with the same title as the following already exist in the database. Add them anyway?
')
for mi in duplicates[2]:
@@ -734,9 +729,7 @@ class Main(MainWindow, Ui_MainWindow):
else:
self.upload_books(paths, list(map(sanitize_file_name, names)), infos, on_card=on_card)
finally:
- progress.setValue(progress.maximum())
progress.hide()
- progress.close()
def upload_books(self, files, names, metadata, on_card=False, memory=None):
'''
@@ -979,28 +972,49 @@ class Main(MainWindow, Ui_MainWindow):
self.save_to_disk(checked, True)
def save_to_disk(self, checked, single_dir=False, single_format=None):
+
rows = self.current_view().selectionModel().selectedRows()
if not rows or len(rows) == 0:
d = error_dialog(self, _('Cannot save to disk'), _('No books selected'))
d.exec_()
return
-
+
+ progress = ProgressDialog(_('Saving to disk...'), min=0, max=len(rows),
+ parent=self)
+
+ def callback(count, msg):
+ progress.set_value(count)
+ progress.set_msg(_('Saved')+' '+msg)
+ QApplication.processEvents()
+ QApplication.sendPostedEvents()
+ QApplication.flush()
+ return not progress.canceled
+
dir = choose_dir(self, 'save to disk dialog', _('Choose destination directory'))
if not dir:
return
- if self.current_view() == self.library_view:
- failures = self.current_view().model().save_to_disk(rows, dir,
- single_dir=single_dir, single_format=single_format)
- if failures and single_format is not None:
- msg = _('Could not save the following books to disk, because the %s format is not available for them:
')%single_format.upper()
- for f in failures:
- msg += '- %s
'%f[1]
- msg += '
'
- warning_dialog(self, _('Could not save some ebooks'), msg).exec_()
- QDesktopServices.openUrl(QUrl('file:'+dir))
- else:
- paths = self.current_view().model().paths(rows)
- self.device_manager.save_books(Dispatcher(self.books_saved), paths, dir)
+
+ progress.show()
+ QApplication.processEvents()
+ QApplication.sendPostedEvents()
+ QApplication.flush()
+ try:
+ if self.current_view() == self.library_view:
+ failures = self.current_view().model().save_to_disk(rows, dir,
+ single_dir=single_dir, callback=callback,
+ single_format=single_format)
+ if failures and single_format is not None:
+ msg = _('Could not save the following books to disk, because the %s format is not available for them:
')%single_format.upper()
+ for f in failures:
+ msg += '- %s
'%f[1]
+ msg += '
'
+ warning_dialog(self, _('Could not save some ebooks'), msg).exec_()
+ QDesktopServices.openUrl(QUrl('file:'+dir))
+ else:
+ paths = self.current_view().model().paths(rows)
+ self.device_manager.save_books(Dispatcher(self.books_saved), paths, dir)
+ finally:
+ progress.hide()
def books_saved(self, job):
if job.exception is not None:
diff --git a/src/calibre/library/database.py b/src/calibre/library/database.py
index ecf272618f..2979c95d26 100644
--- a/src/calibre/library/database.py
+++ b/src/calibre/library/database.py
@@ -1390,10 +1390,11 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE;
return [i[0] for i in self.conn.get('SELECT id FROM books')]
def export_to_dir(self, dir, indices, byauthor=False, single_dir=False,
- index_is_id=False):
+ index_is_id=False, callback=None):
if not os.path.exists(dir):
raise IOError('Target directory does not exist: '+dir)
by_author = {}
+ count = 0
for index in indices:
id = index if index_is_id else self.id(index)
au = self.conn.get('SELECT author_sort FROM books WHERE id=?',
@@ -1403,8 +1404,6 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE;
if not au:
au = _('Unknown')
au = au.split(',')[0]
- else:
- au = au.replace(',', ';')
if not by_author.has_key(au):
by_author[au] = []
by_author[au].append(index)
@@ -1456,6 +1455,11 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE;
print 'Error setting metadata for book:', mi.title
traceback.print_exc()
f.close()
+ count += 1
+ if callable(callback):
+ if not callback(count, mi.title):
+ return
+
def import_book(self, mi, formats):
@@ -1569,12 +1573,13 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE;
return duplicates
- def export_single_format_to_dir(self, dir, indices, format, index_is_id=False):
+ def export_single_format_to_dir(self, dir, indices, format,
+ index_is_id=False, callback=None):
dir = os.path.abspath(dir)
if not index_is_id:
indices = map(self.id, indices)
failures = []
- for id in indices:
+ for count, id in enumerate(indices):
try:
data = self.format(id, format, index_is_id=True)
if not data:
@@ -1599,6 +1604,9 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE;
except:
pass
f.close()
+ if callable(callback):
+ if not callback(count, title):
+ break
return failures
diff --git a/src/calibre/trac/bzr_commit_plugin.py b/src/calibre/trac/bzr_commit_plugin.py
index 8cd8b53d09..5ec6e8f7e8 100644
--- a/src/calibre/trac/bzr_commit_plugin.py
+++ b/src/calibre/trac/bzr_commit_plugin.py
@@ -38,7 +38,6 @@ class cmd_commit(_cmd_commit):
print attributes['summary']
return attributes['summary']
-
def expand_bug(self, msg, nick, config, bug_tracker, type='trac'):
prefix = '%s_%s_'%(type, nick)
username = config.get_user_option(prefix+'username')
diff --git a/src/calibre/web/feeds/recipes/recipe_clarin.py b/src/calibre/web/feeds/recipes/recipe_clarin.py
index 1840be291f..f4b810f087 100644
--- a/src/calibre/web/feeds/recipes/recipe_clarin.py
+++ b/src/calibre/web/feeds/recipes/recipe_clarin.py
@@ -7,6 +7,7 @@ clarin.com
'''
from calibre import strftime
+from calibre.web.feeds.news import BasicNewsRecipe
class Clarin(BasicNewsRecipe):
title = 'Clarin'
@@ -47,4 +48,4 @@ class Clarin(BasicNewsRecipe):
rest = artl.partition('-0')[-1]
lmain = rest.partition('.')[0]
return 'http://www.servicios.clarin.com/notas/jsp/clarin/v9/notas/imprimir.jsp?pagid=' + lmain
-
\ No newline at end of file
+
From d724f09059ba58532ee8746707663dbe2c605e0a Mon Sep 17 00:00:00 2001
From: Kovid Goyal
Date: Sun, 18 Jan 2009 14:22:21 -0800
Subject: [PATCH 17/21] Recipe for Sueddeutsche by Oliver Niesner
---
src/calibre/gui2/images/news/ftd.png | Bin 0 -> 383 bytes
src/calibre/gui2/images/news/heise.png | Bin 0 -> 636 bytes
.../gui2/images/news/security_watch.png | Bin 0 -> 5266 bytes
src/calibre/gui2/images/news/sueddeutsche.png | Bin 0 -> 901 bytes
src/calibre/gui2/images/news/zdnet.png | Bin 0 -> 592 bytes
.../feeds/recipes/recipe_security_watch.py | 2 +-
.../web/feeds/recipes/recipe_sueddeutsche.py | 58 ++++++++++++++++++
7 files changed, 59 insertions(+), 1 deletion(-)
create mode 100644 src/calibre/gui2/images/news/ftd.png
create mode 100644 src/calibre/gui2/images/news/heise.png
create mode 100644 src/calibre/gui2/images/news/security_watch.png
create mode 100644 src/calibre/gui2/images/news/sueddeutsche.png
create mode 100644 src/calibre/gui2/images/news/zdnet.png
create mode 100644 src/calibre/web/feeds/recipes/recipe_sueddeutsche.py
diff --git a/src/calibre/gui2/images/news/ftd.png b/src/calibre/gui2/images/news/ftd.png
new file mode 100644
index 0000000000000000000000000000000000000000..a37c7a22f439c6cfb9f49d14bdc11ea259a09575
GIT binary patch
literal 383
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b
zK-vS0-A-oPfdtD69Mgd`SU*F|v9*VRoE4rfjv*GOlS4L~{CVDiF(EM_Az{Z}lRllZ
zt1fmcupO{i!Z2g0&lHRKT5JdQZdhcXd)q*%DC39!PpjmSn7iF3=@h?rB
z26VG(iEBhja#3nxNvduNkYF$}FtF4$Fw`})2r)9UGBmX^Hq$G0|dX~;KjzIO^Ro&RhS;pKVR?KiIlQx;`PG4pJQTQBJJ;P<|Zr3Ml&W*v_{P+)Q8J$I%6i^fuqNiOBK^UvSd
z_IK)oYnM!1IT{~ZEXm|LP-3-oUG}YQM+@g@JFdUZ{Gh@nOV>kFvN!IFUd{dEn{-yK
zQsQ9R`(pX&ve@fa>(6ZBQDj-a-hSmOu7;yYj0rkdE;s_+FVS{4ZSzm1ht-z%f8A00
zWMl5}uS~p9raU$B)eOa_)t3Ek`Zo6e85U@8F$5p`zP+G6Bs8?pLS{p*^zlNT2isZx
zXYXfRJ-h#D?h!r{VC<=uxJHyD7o{ear0S*s2?iqr14~^4LtR6Q5F;ZiLsKhbLu~^C
zD+7bZgur^3hTQy=%(P0l1`}OF16?EY5F=wNBQq;wV~B=oqm)*l1_n=8KbLh*2~7Yz
CgbJMi
literal 0
HcmV?d00001
diff --git a/src/calibre/gui2/images/news/security_watch.png b/src/calibre/gui2/images/news/security_watch.png
new file mode 100644
index 0000000000000000000000000000000000000000..1c048d6577906376b30b08dc1eaa4b0f0805da28
GIT binary patch
literal 5266
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
YFfckWFp2|%ApigX07*qoM6N<$f}iNvvH$=8
literal 0
HcmV?d00001
diff --git a/src/calibre/gui2/images/news/sueddeutsche.png b/src/calibre/gui2/images/news/sueddeutsche.png
new file mode 100644
index 0000000000000000000000000000000000000000..b7a5de767bd5fcb07f6d278d7acdb6970ba131eb
GIT binary patch
literal 901
zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzwj^(N7l!{JxM1({$v_d#0*}aI
zAngIhZYQ(tK!Rljj_E*J0gT&!&6&%#~oR7|2@XvqCN{bqap$xloSUmX5a
zF8Qe5sLrUg==$6C`}gCGjs@KRZqlb*`ChY2$!k)J#q%ktlC?E8EYELF+^~f_%^F}28gis7|vM6$?#xr`&O~2Y@pP!2!|92wkxH)$0T0u
z;`?^4;9O(zJ_-LxDTNJbk6l`Jtt(`CZ@cB1$0U|QnZr@tg)-%C*ELQXeb~2ZRcbGT
z!f7J`!Bd-TR16MFH1B)Q|FtdgMr-|CyHEGnE3ZY}_kAQ+Q&-1!Y--R!E5?Q?Mgfz8
z9@W_0=Xq`W;U4==b)}Nn?dl7*@=ZzeyezW(GUu@w^-2jnoacm{4pi?~FVN(QKDmkK
z`RB^=1G+h~*|XA?Zx$#xw@~Nw(zEM4XD!Q^#ddDz;ScAJ+P>dCCFoWi&|kT?oiw+u
zzV|k@SlhHX`~0PCZ(VH<@%B9CSZg{ZsN->k`y!35)%Um+#ca?0yxO$SGl4hz?K>wy
zr%7h4*nwWF*((L(Kl3Gb>^yH=liy=$KoW3tbL
zb&GFLZTPTF$mzlB*RKt@UW@1U=FaLnr}W??CrGwm2lQS%5n$AYji0k^#o2!RcTqUef##iDp$9?HF7*V`C^q-l)tN&W>tOt
z^3^Q=#O3U!*m2r$+RQl+zgVUzW6|oiJ-{TaTH+c}l3bLUSdyxn0wfrW3=AxF4GeV+
zEkcZptPD-9j19F746F*k;TkM-4GnaSEJF+ptqe`9jEo=}LYH!_
Q0BT_HboFyt=akR{0KV{m1^@s6
literal 0
HcmV?d00001
diff --git a/src/calibre/gui2/images/news/zdnet.png b/src/calibre/gui2/images/news/zdnet.png
new file mode 100644
index 0000000000000000000000000000000000000000..9e2605dc5232af973cc5063065c92e66a0845099
GIT binary patch
literal 592
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b
zK-vS0-A-oPfdtD69Mgd`SU*F|v9*U87#J%(T^vI!PWJ{G`X6$Ts1=euI&)`YqkY5V
z$xBKnuqy9*nZ%>V_OErxj)%|Mm@gZ0ygU?fN1N~4GNG7-J*Gcp_8pqKO(L#n=e^kb
z)8Fs?-dNVC+wp}h(7@j&QCo9{Fz0NK{0ZF6F%m9m`X6u02?{Dj=uNkf>1{|8|8(13
zCh7y*8~L^8R~>lIRPmo_jiJJFk7gOa1v9rFNDhsi^ju)3T6T%er`q_h>9cfHWA?pY
zy?ZOWV6PsJo{NhL%lyucSGoVhnojm@)|=q?I&Jg$-&!AbHmuomgoUReZTi<}F>kgB
zjvG0A^%*1_R!?vIEOenV_3)>g9*oW1%nr|+|1upg'
+
+'''
+Fetch sueddeutsche.
+'''
+
+from calibre.web.feeds.news import BasicNewsRecipe
+
+
+class Sueddeutsche(BasicNewsRecipe):
+
+ title = u'Sueddeutsche'
+ description = 'News from Germany'
+ __author__ = 'Oliver Niesner'
+ use_embedded_content = False
+ timefmt = ' [%d %b %Y]'
+ max_articles_per_feed = 40
+ no_stylesheets = True
+ encoding = 'latin1'
+ remove_tags_after = [dict(name='div', attrs={'class':'artikelBox navigatorBox'})]
+ #dict(name='table', attrs={'class':'bgf2f2f2 absatz print100'})]
+
+ remove_tags = [dict(name='div', attrs={'class':'bannerSuperBanner'}),
+ dict(name='div', attrs={'class':'bannerSky'}),
+ dict(name='div', attrs={'class':'footerLinks'}),
+ dict(name='div', attrs={'class':'seitenanfang'}),
+ dict(name='td', attrs={'class':'mar5'}),
+ dict(name='table', attrs={'class':'pageAktiv'}),
+ dict(name='table', attrs={'class':'xartable'}),
+ dict(name='table', attrs={'class':'wpnavi'}),
+ dict(name='table', attrs={'class':'bgcontent absatz'}),
+ dict(name='table', attrs={'class':'footer'}),
+ dict(name='table', attrs={'class':'artikelBox'}),
+ dict(name='table', attrs={'class':'kommentare'}),
+ dict(name='table', attrs={'class':'pageBoxBot'}),
+ dict(name='div', attrs={'class':'artikelBox navigatorBox'}),
+ dict(name='div', attrs={'class':'similar-article-box'}),
+ dict(name='div', attrs={'class':'videoBigHack'}),
+ dict(name='td', attrs={'class':'artikelDruckenRight'}),
+ dict(name='span', attrs={'class':'hidePrint'}),
+ dict(id='headerLBox'),
+ dict(id='rechteSpalte'),
+ dict(id='newsticker-list-small'),
+ dict(id='ntop5'),
+ dict(id='ntop5send'),
+ dict(id='ntop5commented'),
+ dict(id='nnav-bgheader'),
+ dict(id='nnav-headerteaser'),
+ dict(id='nnav-head'),
+ dict(id='nnav-top'),
+ dict(id='nnav-logodiv'),
+ dict(id='nnav-logo'),
+ dict(id='nnav-oly'),
+ dict(id='readcomment')]
+
+ feeds = [ (u'Sueddeutsche', u'http://www.sueddeutsche.de/app/service/rss/alles/rss.xml') ]
+
From a83de9ce2d6ad5cf60b250d4d92afc5e2bcfdd46 Mon Sep 17 00:00:00 2001
From: Kovid Goyal
Date: Sun, 18 Jan 2009 16:07:15 -0800
Subject: [PATCH 18/21] Fix #1639 (Calibre can not handle properly URL's with
non-ascii characters). New recipe for Sueddeutsche by Oliver Niesner
---
src/calibre/ebooks/epub/from_feeds.py | 1 +
src/calibre/web/feeds/recipes/__init__.py | 2 +-
src/calibre/web/feeds/recipes/recipe_sueddeutsche.py | 4 ++++
src/calibre/web/fetch/simple.py | 6 +++++-
4 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/src/calibre/ebooks/epub/from_feeds.py b/src/calibre/ebooks/epub/from_feeds.py
index bbadbc54de..fd1759712d 100644
--- a/src/calibre/ebooks/epub/from_feeds.py
+++ b/src/calibre/ebooks/epub/from_feeds.py
@@ -40,6 +40,7 @@ def convert(opts, recipe_arg, notification=None):
c.smart_update(recipe_opts, opts)
opts = recipe_opts
opts.chapter_mark = 'none'
+ opts.dont_split_on_page_breaks = True
opf = glob.glob(os.path.join(tdir, '*.opf'))
if not opf:
raise Exception('Downloading of recipe: %s failed'%recipe_arg)
diff --git a/src/calibre/web/feeds/recipes/__init__.py b/src/calibre/web/feeds/recipes/__init__.py
index e6bcdaed9c..f0687ece28 100644
--- a/src/calibre/web/feeds/recipes/__init__.py
+++ b/src/calibre/web/feeds/recipes/__init__.py
@@ -22,7 +22,7 @@ recipe_modules = ['recipe_' + r for r in (
'time_magazine', 'endgadget', 'fudzilla', 'nspm_int', 'nspm', 'pescanik',
'spiegel_int', 'themarketticker', 'tomshardware', 'xkcd', 'ftd', 'zdnet',
'joelonsoftware', 'telepolis', 'common_dreams', 'nin', 'tomshardware_de',
- 'pagina12', 'infobae', 'ambito', 'elargentino',
+ 'pagina12', 'infobae', 'ambito', 'elargentino', 'sueddeutsche',
)]
import re, imp, inspect, time, os
diff --git a/src/calibre/web/feeds/recipes/recipe_sueddeutsche.py b/src/calibre/web/feeds/recipes/recipe_sueddeutsche.py
index 606fc35320..fa97b73c80 100644
--- a/src/calibre/web/feeds/recipes/recipe_sueddeutsche.py
+++ b/src/calibre/web/feeds/recipes/recipe_sueddeutsche.py
@@ -56,3 +56,7 @@ class Sueddeutsche(BasicNewsRecipe):
feeds = [ (u'Sueddeutsche', u'http://www.sueddeutsche.de/app/service/rss/alles/rss.xml') ]
+ def postprocess_html(self, soup, first_fetch):
+ for t in soup.findAll(['table', 'tr', 'td']):
+ t.name = 'div'
+ return soup
diff --git a/src/calibre/web/fetch/simple.py b/src/calibre/web/fetch/simple.py
index 2a8b03a545..43f7aa0626 100644
--- a/src/calibre/web/fetch/simple.py
+++ b/src/calibre/web/fetch/simple.py
@@ -395,7 +395,11 @@ class RecursiveFetcher(object, LoggingInterface):
if self.download_stylesheets:
self.process_stylesheets(soup, newbaseurl)
- res = os.path.join(linkdiskpath, basename(iurl))
+ _fname = basename(iurl)
+ if not isinstance(_fname, unicode):
+ _fname.decode('latin1', 'replace')
+ _fname.encode('ascii', 'replace').replace('%', '')
+ res = os.path.join(linkdiskpath, _fname)
self.downloaded_paths.append(res)
self.filemap[nurl] = res
if recursion_level < self.max_recursions:
From a0e9483e92b4832351be4f66feb7c75d63261912 Mon Sep 17 00:00:00 2001
From: Kovid Goyal
Date: Sun, 18 Jan 2009 18:04:11 -0800
Subject: [PATCH 19/21] Fix #1623 (Filter stats update)
---
src/calibre/gui2/main.py | 3 +++
src/calibre/gui2/tags.py | 10 +++++++++-
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py
index b04ad18c97..0910f85dac 100644
--- a/src/calibre/gui2/main.py
+++ b/src/calibre/gui2/main.py
@@ -340,6 +340,8 @@ class Main(MainWindow, Ui_MainWindow):
self.connect(self.search, SIGNAL('search(PyQt_PyObject, PyQt_PyObject)'),
self.tags_view.model().reinit)
self.connect(self.library_view.model(), SIGNAL('count_changed(int)'), self.location_view.count_changed)
+ self.connect(self.library_view.model(), SIGNAL('count_changed(int)'),
+ self.tags_view.recount)
self.library_view.model().count_changed()
########################### Cover Flow ################################
self.cover_flow = None
@@ -1129,6 +1131,7 @@ class Main(MainWindow, Ui_MainWindow):
os.remove(f.name)
except:
pass
+ self.tags_view.recount()
if self.current_view() is self.library_view:
current = self.library_view.currentIndex()
self.library_view.model().current_changed(current, QModelIndex())
diff --git a/src/calibre/gui2/tags.py b/src/calibre/gui2/tags.py
index 167236c960..a6772a3b44 100644
--- a/src/calibre/gui2/tags.py
+++ b/src/calibre/gui2/tags.py
@@ -7,7 +7,7 @@ __docformat__ = 'restructuredtext en'
Browsing book collection by tags.
'''
from PyQt4.Qt import QAbstractItemModel, Qt, QVariant, QTreeView, QModelIndex, \
- QFont, SIGNAL, QSize, QColor, QIcon
+ QFont, SIGNAL, QSize, QColor, QIcon, QPoint
from calibre.gui2 import config
NONE = QVariant()
@@ -36,6 +36,14 @@ class TagsView(QTreeView):
if self._model.toggle(index):
self.emit(SIGNAL('tags_marked(PyQt_PyObject, PyQt_PyObject)'),
self._model.tokens(), self.match_all.isChecked())
+
+ def recount(self, *args):
+ ci = self.currentIndex()
+ if not ci.isValid():
+ ci = self.indexAt(QPoint(10, 10))
+ self.model().refresh()
+ if ci.isValid():
+ self.scrollTo(ci, QTreeView.PositionAtTop)
class TagsModel(QAbstractItemModel):
From 00ae0d0edd4e2ba916c8f4727157ad72dbc2dacf Mon Sep 17 00:00:00 2001
From: Kovid Goyal
Date: Sun, 18 Jan 2009 18:07:59 -0800
Subject: [PATCH 20/21] version 0.4.129
---
src/calibre/constants.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/calibre/constants.py b/src/calibre/constants.py
index 180433532d..0004d80b6e 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.4.128'
+__version__ = '0.4.129'
__author__ = "Kovid Goyal "
'''
Various run time constants.
From f5dd06b9c259f1f781bb568381046944ed6bcabd Mon Sep 17 00:00:00 2001
From: Kovid Goyal
Date: Sun, 18 Jan 2009 18:12:54 -0800
Subject: [PATCH 21/21] IGN:Tag release