Merge from trunk

This commit is contained in:
Charles Haley 2012-01-15 10:13:37 +01:00
commit d68ff2bc3f
13 changed files with 163 additions and 47 deletions

View File

@ -0,0 +1,50 @@
__license__ = 'GPL v3'
__copyright__ = '2012 Levien van Zon <levien@zonnetjes.net>'
'''
Fetch Edge.org conversations
'''
from calibre.web.feeds.news import BasicNewsRecipe
class EdgeConversationRSS(BasicNewsRecipe):
title = u'Edge.org Conversations'
__author__ = 'levien'
language = 'en'
description = '''Edge.org offers "open-minded, free ranging, intellectually
playful ... an unadorned pleasure in curiosity, a collective expression of
wonder at the living and inanimate world ... an ongoing and thrilling
colloquium.'''
oldest_article = 60
max_articles_per_feed = 100
no_stylesheets = True
keep_only_tags = [dict(name='div', attrs={'class':'HomeLeftPannel IMGCTRL'}) ]
remove_tags = [
dict(name='div',attrs={'class':'Logo'})
]
feeds = [(u'Edge RSS', u'http://edge.org/feeds/')]
def print_version(self, url):
return url.replace('conversation/', 'conversation.php?cid=')
def parse_feeds(self):
# Call parent's method.
feeds = BasicNewsRecipe.parse_feeds(self)
# Loop through all feeds.
for feed in feeds:
# Loop through all articles in feed.
for article in feed.articles[:]:
# Remove anything that is not a conversation, and remove PDF files as well...
if not ('CONVERSATION' in article.title):
feed.articles.remove(article)
elif 'pdf' in article.url:
feed.articles.remove(article)
return feeds

View File

@ -22,13 +22,16 @@ class NoviList_hr(BasicNewsRecipe):
language = 'hr'
remove_empty_feeds = True
publication_type = 'newspaper'
needs_subscription = 'required'
needs_subscription = True
masthead_url = 'http://novine.novilist.hr/images/system/novilist-logo.jpg'
index = 'http://novine.novilist.hr/'
extra_css = """
body{font-family: Geneva,Arial,Helvetica,Swiss,sans-serif }
@font-face {font-family: "sans1";src:url(res:///opt/sony/ebook/FONT/tt0003m_.ttf)}
body{font-family: Geneva,Arial,Helvetica,Swiss,sans1,sans-serif }
img{display:block; margin-bottom: 0.4em; margin-top: 0.4em}
.nadnaslov,.podnaslov{font-size: small; text-align: center}
.naslov{font-size: x-large; color: maroon; font-weight: bold}
.nadnaslov,.podnaslov{font-size: small; display: block; margin-bottom: 1em}
.naslov{font-size: x-large; color: maroon; font-weight: bold; display: block; margin-bottom: 1em;}
p{display: block}
"""
preprocess_regexps = [(re.compile(u'\u0110'), lambda match: u'\u00D0')]
@ -47,12 +50,12 @@ class NoviList_hr(BasicNewsRecipe):
]
remove_tags = [dict(name=['meta', 'link', 'iframe', 'embed', 'object'])]
remove_attributes=['border', 'lang']
remove_attributes=['border', 'lang', 'size', 'face', 'bgcolor']
def get_browser(self):
br = BasicNewsRecipe.get_browser()
if self.username is not None and self.password is not None:
br.open('http://novine.novilist.hr/loginnow.asp')
br.open(self.index + 'loginnow.asp')
br.select_form(nr=0)
br['username'] = self.username
br['password'] = self.password
@ -62,11 +65,11 @@ class NoviList_hr(BasicNewsRecipe):
def parse_index(self):
articles = []
count = 0
soup = self.index_to_soup('http://novine.novilist.hr/')
soup = self.index_to_soup(self.index)
#cover url
for alink in soup.findAll('a'):
if alink['href'].startswith('images/clanci/DOC_'):
self.cover_url = 'http://novine.novilist.hr/' + alink['href']
self.cover_url = self.index + alink['href']
#feeds
for item in soup.findAll('td',attrs={'class':'tocrubrika'}):
count = count +1
@ -74,28 +77,24 @@ class NoviList_hr(BasicNewsRecipe):
return articles
aitem = item.a
section = self.tag_to_string(aitem)
feedlink = 'http://novine.novilist.hr/' + aitem['href']
feedlink = self.index + aitem['href']
feedpage = self.index_to_soup(feedlink)
self.report_progress(0, _('Fetching feed')+' %s...'%(section))
inarts = []
for alink in feedpage.findAll('a',attrs={'class':'naslovlinkdesno'}):
url = 'http://novine.novilist.hr/' + alink['href']
title = self.tag_to_string(alink)
date = strftime(self.timefmt)
description = ''
url = self.index + alink['href']
inarts.append({
'title' :title
,'date' :date
'title' :self.tag_to_string(alink)
,'date' :strftime(self.timefmt)
,'url' :url
,'description':description
,'description':''
})
articles.append((section,inarts))
if self.remove_empty_feeds:
if inarts:
articles.append((section,inarts))
else:
articles.append((section,inarts))
return articles
def print_version(self, url):
return url.replace('?WCI=Rubrike&','?WCI=Pretrazivac&')
def preprocess_html(self, soup):
for item in soup.findAll(style=True):
del item['style']
return soup

View File

@ -10,7 +10,10 @@ from math import floor
from functools import partial
warnings.simplefilter('ignore', DeprecationWarning)
try:
os.getcwdu()
except:
os.chdir(os.path.expanduser('~'))
from calibre.constants import (iswindows, isosx, islinux, isfrozen,
isbsd, preferred_encoding, __appname__, __version__, __author__,

View File

@ -97,7 +97,7 @@ class POCKETBOOK360(EB600):
VENDOR_NAME = ['PHILIPS', '__POCKET', 'POCKETBO']
WINDOWS_MAIN_MEM = WINDOWS_CARD_A_MEM = ['MASS_STORGE', 'BOOK_USB_STORAGE',
'POCKET_611_61']
'OK_POCKET_611_61']
OSX_MAIN_MEM = OSX_CARD_A_MEM = 'Philips Mass Storge Media'
OSX_MAIN_MEM_VOL_PAT = re.compile(r'/Pocket')

View File

@ -6,6 +6,8 @@ __license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
import re
from calibre.devices.usbms.driver import USBMS
class IRIVER_STORY(USBMS):
@ -25,7 +27,9 @@ class IRIVER_STORY(USBMS):
VENDOR_NAME = 'IRIVER'
WINDOWS_MAIN_MEM = ['STORY', 'STORY_EB05', 'STORY_WI-FI', 'STORY_EB07']
WINDOWS_MAIN_MEM = re.compile(r'(%s)&'%('|'.join(WINDOWS_MAIN_MEM)))
WINDOWS_CARD_A_MEM = ['STORY', 'STORY_SD']
WINDOWS_CARD_A_MEM = re.compile(r'(%s)&'%('|'.join(WINDOWS_CARD_A_MEM)))
#OSX_MAIN_MEM = 'Kindle Internal Storage Media'
#OSX_CARD_A_MEM = 'Kindle Card Storage Media'

View File

@ -942,12 +942,12 @@ class Manifest(object):
if isinstance(data, etree._Element):
ans = xml2str(data, pretty_print=self.oeb.pretty_print)
if self.media_type in OEB_DOCS:
# Convert self closing div|span|a tags to normally closed
# ones, as they are interpreted incorrectly by some browser
# based renderers
# Convert self closing div|span|a|video|audio|iframe tags
# to normally closed ones, as they are interpreted
# incorrectly by some browser based renderers
ans = re.sub(
# tag name followed by either a space or a /
r'<(?P<tag>div|a|span)(?=[\s/])(?P<arg>[^>]*)/>',
r'<(?P<tag>div|a|span|video|audio|iframe)(?=[\s/])(?P<arg>[^>]*)/>',
r'<\g<tag>\g<arg>></\g<tag>>', ans)
return ans
if isinstance(data, unicode):

View File

@ -398,8 +398,8 @@ class CanonicalFragmentIdentifier
break
rect = target.getBoundingClientRect()
x = x - rect.x
y = y - rect.y
x -= rect.left
y -= rect.top
cdoc = cd
cwin = cdoc.defaultView

View File

@ -32,10 +32,12 @@ window_ypos = (pos=null) ->
mark_and_reload = (evt) ->
# Remove image in case the click was on the image itself, we want the cfi to
# be on the underlying element
x = evt.clientX
y = evt.clientY
if evt.button == 2
return # Right mouse click, generated only in firefox
reset = document.getElementById('reset')
if document.elementFromPoint(evt.clientX, evt.clientY) == reset
if document.elementFromPoint(x, y) == reset
return
ms = document.getElementById("marker")
if ms
@ -43,7 +45,7 @@ mark_and_reload = (evt) ->
fn = () ->
try
window.current_cfi = window.cfi.at(evt.clientX, evt.clientY)
window.current_cfi = window.cfi.at(x, y)
catch err
alert("Failed to calculate cfi: #{ err }")
return
@ -57,6 +59,28 @@ mark_and_reload = (evt) ->
setTimeout(fn, 1)
null
window_scroll_pos = (win) ->
if typeof(win.pageXOffset) == 'number'
x = win.pageXOffset
y = win.pageYOffset
else # IE < 9
if document.body and ( document.body.scrollLeft or document.body.scrollTop )
x = document.body.scrollLeft
y = document.body.scrollTop
else if document.documentElement and ( document.documentElement.scrollLeft or document.documentElement.scrollTop)
y = document.documentElement.scrollTop
x = document.documentElement.scrollLeft
return [x, y]
frame_clicked = (evt) ->
iframe = evt.target.ownerDocument.defaultView.frameElement
# We know that the offset parent of the iframe is body
# So we can easily calculate the event co-ords w.r.t. the browser window
[winx, winy] = window_scroll_pos(window)
x = evt.clientX + iframe.offsetLeft - winx
y = evt.clientY + iframe.offsetTop - winy
mark_and_reload({'clientX':x, 'clientY':y, 'button':evt.button})
window.onload = ->
try
window.cfi.is_compatible()
@ -64,6 +88,9 @@ window.onload = ->
alert(error)
return
document.onclick = mark_and_reload
for iframe in document.getElementsByTagName("iframe")
iframe.contentWindow.document.onclick = frame_clicked
r = location.hash.match(/#(\d*)epubcfi\((.+)\)$/)
if r
window.current_cfi = r[2]

View File

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html>
<head>
<title>Testing EPUB CFI</title>
</head>
<body>
<p id="whitespace">But I must explain to you how all this mistaken
idea of denouncing pleasure and praising pain was born and I will
give you a complete account of the system, and expound the actual
teachings of the great explorer of the truth, the master-builder of
human happiness. No one rejects, dislikes, or avoids pleasure
itself, because it is pleasure, but because those who do not know
how to pursue pleasure rationally encounter consequences that are
extremely painful. Nor again is there anyone who <b>loves or
pursues or desires</b> to obtain pain of itself, because it is
pain, but because occasionally circumstances occur in which toil
and pain can procure him some great pleasure. To take a trivial
example, which of us ever undertakes laborious physical exercise,
except to obtain some advantage from it? But who has any right to
find fault with a man who chooses to enjoy a pleasure that has no
annoying consequences, or one who avoids a pain that produces no
resultant pleasure? On the other hand, we denounce with righteous
indignation and dislike men who are so beguiled and demoralized by
the charms of pleasure of the moment, so blinded by desire, that
they cannot foresee</p>
</body>
</html>

View File

@ -118,6 +118,10 @@
<img src="marker.png" width="150" height="200" alt="Test Image"
style="border: solid 1px black"/>
<h2>Iframes</h2>
<p>Try clicking anywhere in the iframe below:</p>
<iframe src="iframe.html"></iframe>
<h2>Video</h2>
<p>Try clicking on this video while it is playing. The page should
reload with the video paused at the point it was at when you
@ -125,7 +129,7 @@
play (otherwise the click will cause a reload).
</p>
<video width="320" height="240" controls="controls" preload="auto"
src="birds.webm" type="video/webm" />
src="birds.webm" type="video/webm"></video>
</div>
<img id="marker" style="position: absolute; display:none; z-index:10"

View File

@ -179,14 +179,16 @@ class Document(QWebPage): # {{{
self.misc_config()
self.after_load()
def __init__(self, shortcuts, parent=None, resize_callback=lambda: None):
def __init__(self, shortcuts, parent=None, resize_callback=lambda: None,
debug_javascript=False):
QWebPage.__init__(self, parent)
self.setObjectName("py_bridge")
self.debug_javascript = False
self.debug_javascript = debug_javascript
self.resize_callback = resize_callback
self.current_language = None
self.loaded_javascript = False
self.js_loader = None
self.js_loader = JavaScriptLoader(
dynamic_coffeescript=self.debug_javascript)
self.setLinkDelegationPolicy(self.DelegateAllLinks)
self.scroll_marks = []
@ -252,9 +254,6 @@ class Document(QWebPage): # {{{
window.py_bridge.window_resized();
}
''')
if self.js_loader is None:
self.js_loader = JavaScriptLoader(
dynamic_coffeescript=self.debug_javascript)
self.loaded_lang = self.js_loader(self.mainFrame().evaluateJavaScript,
self.current_language, self.hyphenate_default_lang)
@ -470,11 +469,10 @@ class DocumentView(QWebView): # {{{
magnification_changed = pyqtSignal(object)
DISABLED_BRUSH = QBrush(Qt.lightGray, Qt.Dense5Pattern)
def __init__(self, *args):
QWebView.__init__(self, *args)
def initialize_view(self, debug_javascript=False):
self.flipper = SlideFlip(self)
self.is_auto_repeat_event = False
self.debug_javascript = False
self.debug_javascript = debug_javascript
self.shortcuts = Shortcuts(SHORTCUTS, 'shortcuts/viewer')
self.self_closing_pat = re.compile(r'<([a-z1-6]+)\s+([^>]+)/>',
re.IGNORECASE)
@ -483,7 +481,8 @@ class DocumentView(QWebView): # {{{
self.initial_pos = 0.0
self.to_bottom = False
self.document = Document(self.shortcuts, parent=self,
resize_callback=self.viewport_resized)
resize_callback=self.viewport_resized,
debug_javascript=debug_javascript)
self.setPage(self.document)
self.manager = None
self._reference_mode = False

View File

@ -39,14 +39,14 @@ class JavaScriptLoader(object):
self._cache = {}
self._hp_cache = {}
def __getattr__(self, name):
def get(self, name):
ans = self._cache.get(name, None)
if ans is None:
src = self.CS.get(name, None)
if src is None:
src = self.JS.get(name, None)
if src is None:
raise AttributeError('No such resource: %s'%name)
raise KeyError('No such resource: %s'%name)
ans = P(src, data=True,
allow_user_override=False).decode('utf-8')
else:
@ -70,7 +70,7 @@ class JavaScriptLoader(object):
def __call__(self, evaljs, lang, default_lang):
for x in self.ORDER:
src = getattr(self, x)
src = self.get(x)
evaljs(src)
def lang_name(l):

View File

@ -175,6 +175,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
def __init__(self, pathtoebook=None, debug_javascript=False, open_at=None):
MainWindow.__init__(self, None)
self.setupUi(self)
self.view.initialize_view(debug_javascript)
self.view.magnification_changed.connect(self.magnification_changed)
self.show_toc_on_open = False
self.current_book_has_toc = False
@ -215,7 +216,6 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
self.search.setMinimumWidth(200)
self.tool_bar2.insertWidget(self.action_find_next, self.search)
self.view.set_manager(self)
self.view.document.debug_javascript = debug_javascript
self.pi = ProgressIndicator(self)
self.toc.setVisible(False)
self.action_quit = QAction(self)