mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-07 10:14:46 -04:00
Sync to trunk
This commit is contained in:
commit
6f6fb1b1e8
@ -2,7 +2,7 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
__appname__ = 'calibre'
|
__appname__ = 'calibre'
|
||||||
__version__ = '0.4.126'
|
__version__ = '0.4.127'
|
||||||
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
||||||
'''
|
'''
|
||||||
Various run time constants.
|
Various run time constants.
|
||||||
|
@ -41,6 +41,20 @@ class Device(object):
|
|||||||
'''Return the FDI description of this device for HAL on linux.'''
|
'''Return the FDI description of this device for HAL on linux.'''
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def can_handle(cls, device_info):
|
||||||
|
'''
|
||||||
|
Optional method to perform further checks on a device to see if this driver
|
||||||
|
is capable of handling it. If it is not it should return False. This method
|
||||||
|
is only called after the vendor, product ids and the bcd have matched, so
|
||||||
|
it can do some relatively time intensive checks. The default implementation
|
||||||
|
returns True.
|
||||||
|
|
||||||
|
:param device_info: On windows a device ID string. On Unix a tuple of
|
||||||
|
``(vendor_id, product_id, bcd)``.
|
||||||
|
'''
|
||||||
|
return True
|
||||||
|
|
||||||
def open(self):
|
def open(self):
|
||||||
'''
|
'''
|
||||||
Perform any device specific initialization. Called after the device is
|
Perform any device specific initialization. Called after the device is
|
||||||
|
@ -63,12 +63,14 @@ class DeviceScanner(object):
|
|||||||
for device_id in self.devices:
|
for device_id in self.devices:
|
||||||
if vid in device_id and pid in device_id:
|
if vid in device_id and pid in device_id:
|
||||||
if self.test_bcd_windows(device_id, getattr(device, 'BCD', None)):
|
if self.test_bcd_windows(device_id, getattr(device, 'BCD', None)):
|
||||||
return True
|
if device.can_handle(device_id):
|
||||||
|
return True
|
||||||
else:
|
else:
|
||||||
for vendor, product, bcdDevice in self.devices:
|
for vendor, product, bcdDevice in self.devices:
|
||||||
if device.VENDOR_ID == vendor and device.PRODUCT_ID == product:
|
if device.VENDOR_ID == vendor and device.PRODUCT_ID == product:
|
||||||
if self.test_bcd(bcdDevice, getattr(device, 'BCD', None)):
|
if self.test_bcd(bcdDevice, getattr(device, 'BCD', None)):
|
||||||
return True
|
if device.can_handle((vendor, product, bcdDevice)):
|
||||||
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
@ -67,6 +67,7 @@ def txt2opf(path, tdir, opts):
|
|||||||
def pdf2opf(path, tdir, opts):
|
def pdf2opf(path, tdir, opts):
|
||||||
from calibre.ebooks.lrf.pdf.convert_from import generate_html
|
from calibre.ebooks.lrf.pdf.convert_from import generate_html
|
||||||
generate_html(path, tdir)
|
generate_html(path, tdir)
|
||||||
|
opts.dont_split_on_page_breaks = True
|
||||||
return os.path.join(tdir, 'metadata.opf')
|
return os.path.join(tdir, 'metadata.opf')
|
||||||
|
|
||||||
def epub2opf(path, tdir, opts):
|
def epub2opf(path, tdir, opts):
|
||||||
|
@ -560,7 +560,7 @@ class Processor(Parser):
|
|||||||
hr = etree.Element('hr')
|
hr = etree.Element('hr')
|
||||||
if elem.getprevious() is None:
|
if elem.getprevious() is None:
|
||||||
elem.getparent()[:0] = [hr]
|
elem.getparent()[:0] = [hr]
|
||||||
else:
|
elif elem.getparent() is not None:
|
||||||
insert = None
|
insert = None
|
||||||
for i, c in enumerate(elem.getparent()):
|
for i, c in enumerate(elem.getparent()):
|
||||||
if c is elem:
|
if c is elem:
|
||||||
@ -796,7 +796,18 @@ class Processor(Parser):
|
|||||||
setting = ''
|
setting = ''
|
||||||
face = font.attrib.pop('face', None)
|
face = font.attrib.pop('face', None)
|
||||||
if face is not None:
|
if face is not None:
|
||||||
setting += 'font-face:%s;'%face
|
faces = []
|
||||||
|
for face in face.split(','):
|
||||||
|
if ' ' in face:
|
||||||
|
face = "%s" % face
|
||||||
|
faces.append(face)
|
||||||
|
for generic in ('serif', 'sans-serif', 'monospace'):
|
||||||
|
if generic in faces:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
faces.append('serif')
|
||||||
|
family = ', '.join(faces)
|
||||||
|
setting += 'font-family: %s;' % family
|
||||||
color = font.attrib.pop('color', None)
|
color = font.attrib.pop('color', None)
|
||||||
if color is not None:
|
if color is not None:
|
||||||
setting += 'color:%s'%color
|
setting += 'color:%s'%color
|
||||||
|
@ -425,7 +425,7 @@ def do_convert(path_to_file, opts, notification=lambda m, p: p, output_format='l
|
|||||||
thumbnail = None
|
thumbnail = None
|
||||||
if not pages:
|
if not pages:
|
||||||
raise ValueError('Could not find any pages in the comic: %s'%source)
|
raise ValueError('Could not find any pages in the comic: %s'%source)
|
||||||
if not opts.no_process:
|
if not getattr(opts, 'no_process', False):
|
||||||
pages, failures, tdir2 = process_pages(pages, opts, notification)
|
pages, failures, tdir2 = process_pages(pages, opts, notification)
|
||||||
if not pages:
|
if not pages:
|
||||||
raise ValueError('Could not find any valid pages in the comic: %s'%source)
|
raise ValueError('Could not find any valid pages in the comic: %s'%source)
|
||||||
|
@ -29,7 +29,7 @@ def config(defaults=None):
|
|||||||
c.add_opt('top_right_y', [ '-w', '--righty'], default=default_crop,
|
c.add_opt('top_right_y', [ '-w', '--righty'], default=default_crop,
|
||||||
help=_('Number of pixels to crop from the right most y (default is %d)')%default_crop )
|
help=_('Number of pixels to crop from the right most y (default is %d)')%default_crop )
|
||||||
c.add_opt('bounding', ['-b', '--bounding'],
|
c.add_opt('bounding', ['-b', '--bounding'],
|
||||||
help=_('A file generated by ghostscript which allows each page to be individually cropped'))
|
help=_('A file generated by ghostscript which allows each page to be individually cropped [gs -dSAFER -dNOPAUSE -dBATCH -sDEVICE=bbox > bounding] '))
|
||||||
return c
|
return c
|
||||||
|
|
||||||
|
|
||||||
@ -38,14 +38,24 @@ def option_parser():
|
|||||||
return c.option_parser(usage=_('''\
|
return c.option_parser(usage=_('''\
|
||||||
%prog [options] file.pdf
|
%prog [options] file.pdf
|
||||||
|
|
||||||
Crop a pdf.
|
Crops a pdf.
|
||||||
'''))
|
'''))
|
||||||
|
|
||||||
def main(args=sys.argv):
|
def main(args=sys.argv):
|
||||||
parser = option_parser()
|
parser = option_parser()
|
||||||
opts, args = parser.parse_args(args)
|
opts, args = parser.parse_args(args)
|
||||||
source = os.path.abspath(args[1])
|
try:
|
||||||
input_pdf = PdfFileReader(file(source, "rb"))
|
source = os.path.abspath(args[1])
|
||||||
|
input_pdf = PdfFileReader(file(source, "rb"))
|
||||||
|
except:
|
||||||
|
print "Unable to read input"
|
||||||
|
return 2
|
||||||
|
info = input_pdf.getDocumentInfo()
|
||||||
|
title = 'Unknown'
|
||||||
|
author = 'Unknown'
|
||||||
|
if info.title:
|
||||||
|
title = info.title
|
||||||
|
author = info.author
|
||||||
if opts.bounding != None:
|
if opts.bounding != None:
|
||||||
try:
|
try:
|
||||||
bounding = open( opts.bounding , 'r' )
|
bounding = open( opts.bounding , 'r' )
|
||||||
@ -53,7 +63,7 @@ def main(args=sys.argv):
|
|||||||
except:
|
except:
|
||||||
print 'Error opening %s' % opts.bounding
|
print 'Error opening %s' % opts.bounding
|
||||||
return 1
|
return 1
|
||||||
output_pdf = PdfFileWriter()
|
output_pdf = PdfFileWriter(title=title,author=author)
|
||||||
for page_number in range (0, input_pdf.getNumPages() ):
|
for page_number in range (0, input_pdf.getNumPages() ):
|
||||||
page = input_pdf.getPage(page_number)
|
page = input_pdf.getPage(page_number)
|
||||||
if opts.bounding != None:
|
if opts.bounding != None:
|
||||||
|
@ -75,7 +75,13 @@ def save_recipes(recipes):
|
|||||||
|
|
||||||
def load_recipes():
|
def load_recipes():
|
||||||
config.refresh()
|
config.refresh()
|
||||||
return [Recipe().unpickle(r) for r in config.get('scheduled_recipes', [])]
|
recipes = []
|
||||||
|
for r in config.get('scheduled_recipes', []):
|
||||||
|
r = Recipe().unpickle(r)
|
||||||
|
if r.builtin and not str(r.id).startswith('recipe_'):
|
||||||
|
continue
|
||||||
|
recipes.append(r)
|
||||||
|
return recipes
|
||||||
|
|
||||||
class RecipeModel(QAbstractListModel, SearchQueryParser):
|
class RecipeModel(QAbstractListModel, SearchQueryParser):
|
||||||
|
|
||||||
@ -438,7 +444,7 @@ class Scheduler(QObject):
|
|||||||
self.lock.unlock()
|
self.lock.unlock()
|
||||||
|
|
||||||
def main(args=sys.argv):
|
def main(args=sys.argv):
|
||||||
app = QApplication([])
|
QApplication([])
|
||||||
from calibre.library.database2 import LibraryDatabase2
|
from calibre.library.database2 import LibraryDatabase2
|
||||||
d = SchedulerDialog(LibraryDatabase2('/home/kovid/documents/library'))
|
d = SchedulerDialog(LibraryDatabase2('/home/kovid/documents/library'))
|
||||||
d.exec_()
|
d.exec_()
|
||||||
|
BIN
src/calibre/gui2/images/news/telepolis.png
Normal file
BIN
src/calibre/gui2/images/news/telepolis.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 586 B |
@ -217,8 +217,7 @@ class Server(object):
|
|||||||
pos = pos.replace(month = 1)
|
pos = pos.replace(month = 1)
|
||||||
else:
|
else:
|
||||||
pos = pos.replace(month = pos.month + 1)
|
pos = pos.replace(month = pos.month + 1)
|
||||||
|
_months = list(months(self.earliest, self.latest))[:-1][-12:]
|
||||||
_months = list(months(self.earliest, self.latest))[:-1][:12]
|
|
||||||
_months = [range_for_month(*m) for m in _months]
|
_months = [range_for_month(*m) for m in _months]
|
||||||
_months = [self.get_slice(*m) for m in _months]
|
_months = [self.get_slice(*m) for m in _months]
|
||||||
x = [m.min for m in _months]
|
x = [m.min for m in _months]
|
||||||
|
@ -35,7 +35,7 @@ class Distribution(object):
|
|||||||
('xdg-utils', '1.0.2', 'xdg-utils', 'xdg-utils', 'xdg-utils'),
|
('xdg-utils', '1.0.2', 'xdg-utils', 'xdg-utils', 'xdg-utils'),
|
||||||
('dbus-python', '0.82.2', 'dbus-python', 'python-dbus', 'dbus-python'),
|
('dbus-python', '0.82.2', 'dbus-python', 'python-dbus', 'dbus-python'),
|
||||||
('lxml', '2.0.5', 'lxml', 'python-lxml', 'python-lxml'),
|
('lxml', '2.0.5', 'lxml', 'python-lxml', 'python-lxml'),
|
||||||
('BeautifulSoup', '3.0.5', 'beautifulsoup', 'python-beautifulsoup', 'python-beautifulsoup'),
|
('BeautifulSoup', '3.0.5', 'beautifulsoup', 'python-beautifulsoup', 'python-BeautifulSoup'),
|
||||||
('help2man', '1.36.4', 'help2man', 'help2man', 'help2man'),
|
('help2man', '1.36.4', 'help2man', 'help2man', 'help2man'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -765,6 +765,8 @@ class BasicNewsRecipe(object, LoggingInterface):
|
|||||||
self.log_debug(traceback.format_exc())
|
self.log_debug(traceback.format_exc())
|
||||||
if cu is not None:
|
if cu is not None:
|
||||||
ext = cu.rpartition('.')[-1]
|
ext = cu.rpartition('.')[-1]
|
||||||
|
if '?' in ext:
|
||||||
|
ext = ''
|
||||||
ext = ext.lower() if ext else 'jpg'
|
ext = ext.lower() if ext else 'jpg'
|
||||||
self.report_progress(1, _('Downloading cover from %s')%cu)
|
self.report_progress(1, _('Downloading cover from %s')%cu)
|
||||||
cpath = os.path.join(self.output_dir, 'cover.'+ext)
|
cpath = os.path.join(self.output_dir, 'cover.'+ext)
|
||||||
|
@ -21,7 +21,7 @@ recipe_modules = ['recipe_' + r for r in (
|
|||||||
'linux_magazine', 'telegraph_uk', 'utne', 'sciencedaily', 'forbes',
|
'linux_magazine', 'telegraph_uk', 'utne', 'sciencedaily', 'forbes',
|
||||||
'time_magazine', 'endgadget', 'fudzilla', 'nspm_int', 'nspm', 'pescanik',
|
'time_magazine', 'endgadget', 'fudzilla', 'nspm_int', 'nspm', 'pescanik',
|
||||||
'spiegel_int', 'themarketticker', 'tomshardware', 'xkcd', 'ftd', 'zdnet',
|
'spiegel_int', 'themarketticker', 'tomshardware', 'xkcd', 'ftd', 'zdnet',
|
||||||
'joelonsoftware',
|
'joelonsoftware', 'telepolis', 'common_dreams',
|
||||||
)]
|
)]
|
||||||
|
|
||||||
import re, imp, inspect, time, os
|
import re, imp, inspect, time, os
|
||||||
|
@ -42,3 +42,9 @@ class ChristianScienceMonitor(BasicNewsRecipe):
|
|||||||
feeds[-1][1].append(art)
|
feeds[-1][1].append(art)
|
||||||
return feeds
|
return feeds
|
||||||
|
|
||||||
|
def postprocess_html(self, soup, first_fetch):
|
||||||
|
html = soup.find('html')
|
||||||
|
if html is None:
|
||||||
|
return soup
|
||||||
|
html.extract()
|
||||||
|
return html
|
||||||
|
16
src/calibre/web/feeds/recipes/recipe_common_dreams.py
Normal file
16
src/calibre/web/feeds/recipes/recipe_common_dreams.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class CommonDreams(BasicNewsRecipe):
|
||||||
|
title = u'Common Dreams'
|
||||||
|
description = u'Progressive news and views'
|
||||||
|
__author__ = u'XanthanGum'
|
||||||
|
oldest_article = 7
|
||||||
|
max_articles_per_feed = 100
|
||||||
|
|
||||||
|
feeds = [
|
||||||
|
(u'Common Dreams Headlines',
|
||||||
|
u'http://www.commondreams.org/feed/headlines_rss'),
|
||||||
|
(u'Common Dreams Views', u'http://www.commondreams.org/feed/views_rss'),
|
||||||
|
(u'Common Dreams Newswire', u'http://www.commondreams.org/feed/newswire_rss')
|
||||||
|
]
|
@ -49,8 +49,10 @@ class Economist(BasicNewsRecipe):
|
|||||||
if not index_started:
|
if not index_started:
|
||||||
continue
|
continue
|
||||||
text = string.capwords(text)
|
text = string.capwords(text)
|
||||||
feeds[text] = []
|
if text not in feeds.keys():
|
||||||
ans.append(text)
|
feeds[text] = []
|
||||||
|
if text not in ans:
|
||||||
|
ans.append(text)
|
||||||
key = text
|
key = text
|
||||||
continue
|
continue
|
||||||
if key is None:
|
if key is None:
|
||||||
|
34
src/calibre/web/feeds/recipes/recipe_telepolis.py
Normal file
34
src/calibre/web/feeds/recipes/recipe_telepolis.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2008, Darko Miletic <darko.miletic at gmail.com>'
|
||||||
|
'''
|
||||||
|
www.heise.de/tp
|
||||||
|
'''
|
||||||
|
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class Telepolis(BasicNewsRecipe):
|
||||||
|
title = 'Telepolis'
|
||||||
|
__author__ = 'Darko Miletic'
|
||||||
|
description = 'News from Germany in German'
|
||||||
|
oldest_article = 2
|
||||||
|
max_articles_per_feed = 100
|
||||||
|
no_stylesheets = True
|
||||||
|
use_embedded_content = False
|
||||||
|
encoding = 'utf-8'
|
||||||
|
|
||||||
|
html2lrf_options = [ '--comment' , description
|
||||||
|
, '--category' , 'blog,news'
|
||||||
|
]
|
||||||
|
|
||||||
|
keep_only_tags = [
|
||||||
|
dict(name='table', attrs={'class':'inhalt-table'})
|
||||||
|
,dict(name='table', attrs={'class':'blogtable' })
|
||||||
|
]
|
||||||
|
remove_tags = [
|
||||||
|
dict(name='table', attrs={'class':'img' })
|
||||||
|
,dict(name='img' , attrs={'src':'/tp/r4/icons/inline/extlink.gif'})
|
||||||
|
]
|
||||||
|
|
||||||
|
feeds = [(u'Telepolis Newsfeed', u'http://www.heise.de/tp/news.rdf')]
|
@ -33,6 +33,7 @@ class TimesOnline(BasicNewsRecipe):
|
|||||||
('Sports News', 'http://www.timesonline.co.uk/tol/feeds/rss/sport.xml'),
|
('Sports News', 'http://www.timesonline.co.uk/tol/feeds/rss/sport.xml'),
|
||||||
('Film News', 'http://www.timesonline.co.uk/tol/feeds/rss/film.xml'),
|
('Film News', 'http://www.timesonline.co.uk/tol/feeds/rss/film.xml'),
|
||||||
('Tech news', 'http://www.timesonline.co.uk/tol/feeds/rss/tech.xml'),
|
('Tech news', 'http://www.timesonline.co.uk/tol/feeds/rss/tech.xml'),
|
||||||
|
('Literary Supplement', 'http://www.timesonline.co.uk/tol/feeds/rss/thetls.xml'),
|
||||||
]
|
]
|
||||||
|
|
||||||
def print_version(self, url):
|
def print_version(self, url):
|
||||||
|
@ -55,7 +55,7 @@ from utils import readNonWhitespace, readUntilWhitespace, ConvertFunctionsToVirt
|
|||||||
# This class supports writing PDF files out, given pages produced by another
|
# This class supports writing PDF files out, given pages produced by another
|
||||||
# class (typically {@link #PdfFileReader PdfFileReader}).
|
# class (typically {@link #PdfFileReader PdfFileReader}).
|
||||||
class PdfFileWriter(object):
|
class PdfFileWriter(object):
|
||||||
def __init__(self):
|
def __init__(self,title=u"Unknown",author=u"Unknown"):
|
||||||
self._header = "%PDF-1.3"
|
self._header = "%PDF-1.3"
|
||||||
self._objects = [] # array of indirect objects
|
self._objects = [] # array of indirect objects
|
||||||
|
|
||||||
@ -71,7 +71,9 @@ class PdfFileWriter(object):
|
|||||||
# info object
|
# info object
|
||||||
info = DictionaryObject()
|
info = DictionaryObject()
|
||||||
info.update({
|
info.update({
|
||||||
NameObject("/Producer"): createStringObject(u"Python PDF Library - http://pybrary.net/pyPdf/")
|
NameObject("/Producer"): createStringObject(u"Python PDF Library - http://pybrary.net/pyPdf/"),
|
||||||
|
NameObject("/Author"): createStringObject(author),
|
||||||
|
NameObject("/Title"): createStringObject(title),
|
||||||
})
|
})
|
||||||
self._info = self._addObject(info)
|
self._info = self._addObject(info)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user