mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Pull from trunk
This commit is contained in:
commit
9ab8caf6f5
@ -1,5 +1,5 @@
|
|||||||
" Project wide builtins
|
" Project wide builtins
|
||||||
let g:pyflakes_builtins += ["dynamic_property", '__']
|
let g:pyflakes_builtins += ["dynamic_property", "__"]
|
||||||
|
|
||||||
python << EOFPY
|
python << EOFPY
|
||||||
import os
|
import os
|
||||||
|
@ -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.5.3'
|
__version__ = '0.5.4'
|
||||||
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
||||||
'''
|
'''
|
||||||
Various run time constants.
|
Various run time constants.
|
||||||
|
@ -510,8 +510,6 @@ class OPF(object):
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_text(self, elem):
|
def get_text(self, elem):
|
||||||
return u''.join(self.CONTENT(elem) or self.TEXT(elem))
|
return u''.join(self.CONTENT(elem) or self.TEXT(elem))
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||||
import os, glob
|
import os, glob, re
|
||||||
from urlparse import urlparse
|
from urlparse import urlparse
|
||||||
from urllib import unquote
|
from urllib import unquote
|
||||||
|
|
||||||
@ -10,17 +10,17 @@ from calibre.ebooks.BeautifulSoup import BeautifulStoneSoup, BeautifulSoup
|
|||||||
from calibre.ebooks.chardet import xml_to_unicode
|
from calibre.ebooks.chardet import xml_to_unicode
|
||||||
|
|
||||||
class NCXSoup(BeautifulStoneSoup):
|
class NCXSoup(BeautifulStoneSoup):
|
||||||
|
|
||||||
NESTABLE_TAGS = {'navpoint':[]}
|
NESTABLE_TAGS = {'navpoint':[]}
|
||||||
|
|
||||||
def __init__(self, raw):
|
def __init__(self, raw):
|
||||||
BeautifulStoneSoup.__init__(self, raw,
|
BeautifulStoneSoup.__init__(self, raw,
|
||||||
convertEntities=BeautifulSoup.HTML_ENTITIES,
|
convertEntities=BeautifulSoup.HTML_ENTITIES,
|
||||||
selfClosingTags=['meta', 'content'])
|
selfClosingTags=['meta', 'content'])
|
||||||
|
|
||||||
class TOC(list):
|
class TOC(list):
|
||||||
|
|
||||||
def __init__(self, href=None, fragment=None, text=None, parent=None, play_order=0,
|
def __init__(self, href=None, fragment=None, text=None, parent=None, play_order=0,
|
||||||
base_path=os.getcwd(), type='unknown'):
|
base_path=os.getcwd(), type='unknown'):
|
||||||
self.href = href
|
self.href = href
|
||||||
self.fragment = fragment
|
self.fragment = fragment
|
||||||
@ -31,7 +31,7 @@ class TOC(list):
|
|||||||
self.base_path = base_path
|
self.base_path = base_path
|
||||||
self.play_order = play_order
|
self.play_order = play_order
|
||||||
self.type = type
|
self.type = type
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
lines = ['TOC: %s#%s'%(self.href, self.fragment)]
|
lines = ['TOC: %s#%s'%(self.href, self.fragment)]
|
||||||
for child in self:
|
for child in self:
|
||||||
@ -39,10 +39,10 @@ class TOC(list):
|
|||||||
for l in c:
|
for l in c:
|
||||||
lines.append('\t'+l)
|
lines.append('\t'+l)
|
||||||
return '\n'.join(lines)
|
return '\n'.join(lines)
|
||||||
|
|
||||||
def count(self, type):
|
def count(self, type):
|
||||||
return len([i for i in self.flat() if i.type == type])
|
return len([i for i in self.flat() if i.type == type])
|
||||||
|
|
||||||
def purge(self, types, max=0):
|
def purge(self, types, max=0):
|
||||||
remove = []
|
remove = []
|
||||||
for entry in self.flat():
|
for entry in self.flat():
|
||||||
@ -54,23 +54,23 @@ class TOC(list):
|
|||||||
continue
|
continue
|
||||||
entry.parent.remove(entry)
|
entry.parent.remove(entry)
|
||||||
return remove
|
return remove
|
||||||
|
|
||||||
def remove(self, entry):
|
def remove(self, entry):
|
||||||
list.remove(self, entry)
|
list.remove(self, entry)
|
||||||
entry.parent = None
|
entry.parent = None
|
||||||
|
|
||||||
def add_item(self, href, fragment, text, play_order=None, type='unknown'):
|
def add_item(self, href, fragment, text, play_order=None, type='unknown'):
|
||||||
if play_order is None:
|
if play_order is None:
|
||||||
play_order = (self[-1].play_order if len(self) else self.play_order) + 1
|
play_order = (self[-1].play_order if len(self) else self.play_order) + 1
|
||||||
self.append(TOC(href=href, fragment=fragment, text=text, parent=self,
|
self.append(TOC(href=href, fragment=fragment, text=text, parent=self,
|
||||||
base_path=self.base_path, play_order=play_order, type=type))
|
base_path=self.base_path, play_order=play_order, type=type))
|
||||||
return self[-1]
|
return self[-1]
|
||||||
|
|
||||||
def top_level_items(self):
|
def top_level_items(self):
|
||||||
for item in self:
|
for item in self:
|
||||||
if item.text is not None:
|
if item.text is not None:
|
||||||
yield item
|
yield item
|
||||||
|
|
||||||
def depth(self):
|
def depth(self):
|
||||||
depth = 1
|
depth = 1
|
||||||
for obj in self:
|
for obj in self:
|
||||||
@ -78,14 +78,14 @@ class TOC(list):
|
|||||||
if c > depth - 1:
|
if c > depth - 1:
|
||||||
depth = c + 1
|
depth = c + 1
|
||||||
return depth
|
return depth
|
||||||
|
|
||||||
def flat(self):
|
def flat(self):
|
||||||
'Depth first iteration over the tree rooted at self'
|
'Depth first iteration over the tree rooted at self'
|
||||||
yield self
|
yield self
|
||||||
for obj in self:
|
for obj in self:
|
||||||
for i in obj.flat():
|
for i in obj.flat():
|
||||||
yield i
|
yield i
|
||||||
|
|
||||||
@dynamic_property
|
@dynamic_property
|
||||||
def abspath(self):
|
def abspath(self):
|
||||||
doc='Return the file this toc entry points to as a absolute path to a file on the system.'
|
doc='Return the file this toc entry points to as a absolute path to a file on the system.'
|
||||||
@ -96,9 +96,9 @@ class TOC(list):
|
|||||||
if not os.path.isabs(path):
|
if not os.path.isabs(path):
|
||||||
path = os.path.join(self.base_path, path)
|
path = os.path.join(self.base_path, path)
|
||||||
return path
|
return path
|
||||||
|
|
||||||
return property(fget=fget, doc=doc)
|
return property(fget=fget, doc=doc)
|
||||||
|
|
||||||
def read_from_opf(self, opfreader):
|
def read_from_opf(self, opfreader):
|
||||||
toc = opfreader.soup.find('spine', toc=True)
|
toc = opfreader.soup.find('spine', toc=True)
|
||||||
if toc is not None:
|
if toc is not None:
|
||||||
@ -111,7 +111,7 @@ class TOC(list):
|
|||||||
if 'toc' in item.href().lower():
|
if 'toc' in item.href().lower():
|
||||||
toc = item.href()
|
toc = item.href()
|
||||||
break
|
break
|
||||||
|
|
||||||
if toc is not None:
|
if toc is not None:
|
||||||
if toc.lower() not in ('ncx', 'ncxtoc'):
|
if toc.lower() not in ('ncx', 'ncxtoc'):
|
||||||
toc = urlparse(unquote(toc))[2]
|
toc = urlparse(unquote(toc))[2]
|
||||||
@ -123,7 +123,7 @@ class TOC(list):
|
|||||||
bn = os.path.basename(toc)
|
bn = os.path.basename(toc)
|
||||||
bn = bn.replace('_top.htm', '_toc.htm') # Bug in BAEN OPF files
|
bn = bn.replace('_top.htm', '_toc.htm') # Bug in BAEN OPF files
|
||||||
toc = os.path.join(os.path.dirname(toc), bn)
|
toc = os.path.join(os.path.dirname(toc), bn)
|
||||||
|
|
||||||
self.read_html_toc(toc)
|
self.read_html_toc(toc)
|
||||||
except:
|
except:
|
||||||
print 'WARNING: Could not read Table of Contents. Continuing anyway.'
|
print 'WARNING: Could not read Table of Contents. Continuing anyway.'
|
||||||
@ -141,43 +141,43 @@ class TOC(list):
|
|||||||
if m:
|
if m:
|
||||||
toc = m[0]
|
toc = m[0]
|
||||||
self.read_ncx_toc(toc)
|
self.read_ncx_toc(toc)
|
||||||
|
|
||||||
def read_ncx_toc(self, toc):
|
def read_ncx_toc(self, toc):
|
||||||
self.base_path = os.path.dirname(toc)
|
self.base_path = os.path.dirname(toc)
|
||||||
soup = NCXSoup(xml_to_unicode(open(toc, 'rb').read())[0])
|
soup = NCXSoup(xml_to_unicode(open(toc, 'rb').read())[0])
|
||||||
|
|
||||||
def process_navpoint(np, dest):
|
def process_navpoint(np, dest):
|
||||||
play_order = np.get('playOrder', None)
|
play_order = np.get('playOrder', None)
|
||||||
if play_order is None:
|
if play_order is None:
|
||||||
play_order = int(np.get('playorder', 1))
|
play_order = int(np.get('playorder', 1))
|
||||||
href = fragment = text = None
|
href = fragment = text = None
|
||||||
nl = np.find('navlabel')
|
nl = np.find(re.compile('navlabel'))
|
||||||
if nl is not None:
|
if nl is not None:
|
||||||
text = u''
|
text = u''
|
||||||
for txt in nl.findAll('text'):
|
for txt in nl.findAll(re.compile('text')):
|
||||||
text += ''.join([unicode(s) for s in txt.findAll(text=True)])
|
text += ''.join([unicode(s) for s in txt.findAll(text=True)])
|
||||||
content = np.find('content')
|
content = np.find(re.compile('content'))
|
||||||
if content is None or not content.has_key('src') or not txt:
|
if content is None or not content.has_key('src') or not txt:
|
||||||
return
|
return
|
||||||
|
|
||||||
purl = urlparse(unquote(content['src']))
|
purl = urlparse(unquote(content['src']))
|
||||||
href, fragment = purl[2], purl[5]
|
href, fragment = purl[2], purl[5]
|
||||||
nd = dest.add_item(href, fragment, text)
|
nd = dest.add_item(href, fragment, text)
|
||||||
nd.play_order = play_order
|
nd.play_order = play_order
|
||||||
|
|
||||||
for c in np:
|
for c in np:
|
||||||
if getattr(c, 'name', None) == 'navpoint':
|
if 'navpoint' in getattr(c, 'name', ''):
|
||||||
process_navpoint(c, nd)
|
process_navpoint(c, nd)
|
||||||
|
|
||||||
nm = soup.find('navmap')
|
nm = soup.find(re.compile('navmap'))
|
||||||
if nm is None:
|
if nm is None:
|
||||||
raise ValueError('NCX files must have a <navmap> element.')
|
raise ValueError('NCX files must have a <navmap> element.')
|
||||||
|
|
||||||
for elem in nm:
|
for elem in nm:
|
||||||
if getattr(elem, 'name', None) == 'navpoint':
|
if 'navpoint' in getattr(elem, 'name', ''):
|
||||||
process_navpoint(elem, self)
|
process_navpoint(elem, self)
|
||||||
|
|
||||||
|
|
||||||
def read_html_toc(self, toc):
|
def read_html_toc(self, toc):
|
||||||
self.base_path = os.path.dirname(toc)
|
self.base_path = os.path.dirname(toc)
|
||||||
soup = BeautifulSoup(open(toc, 'rb').read(), convertEntities=BeautifulSoup.HTML_ENTITIES)
|
soup = BeautifulSoup(open(toc, 'rb').read(), convertEntities=BeautifulSoup.HTML_ENTITIES)
|
||||||
@ -191,13 +191,13 @@ class TOC(list):
|
|||||||
else:
|
else:
|
||||||
fragment = fragment.strip()
|
fragment = fragment.strip()
|
||||||
href = href.strip()
|
href = href.strip()
|
||||||
|
|
||||||
txt = ''.join([unicode(s).strip() for s in a.findAll(text=True)])
|
txt = ''.join([unicode(s).strip() for s in a.findAll(text=True)])
|
||||||
add = True
|
add = True
|
||||||
for i in self.flat():
|
for i in self.flat():
|
||||||
if i.href == href and i.fragment == fragment:
|
if i.href == href and i.fragment == fragment:
|
||||||
add = False
|
add = False
|
||||||
break
|
break
|
||||||
if add:
|
if add:
|
||||||
self.add_item(href, fragment, txt)
|
self.add_item(href, fragment, txt)
|
||||||
|
|
||||||
@ -208,4 +208,4 @@ class TOC(list):
|
|||||||
template = MarkupTemplate(ncx_template)
|
template = MarkupTemplate(ncx_template)
|
||||||
raw = template.generate(uid=uid, toc=self, __appname__=__appname__)
|
raw = template.generate(uid=uid, toc=self, __appname__=__appname__)
|
||||||
raw = raw.render(doctype=doctype)
|
raw = raw.render(doctype=doctype)
|
||||||
stream.write(raw)
|
stream.write(raw)
|
||||||
|
@ -263,7 +263,7 @@ class EmailAccounts(QAbstractTableModel):
|
|||||||
|
|
||||||
def remove(self, index):
|
def remove(self, index):
|
||||||
if index.isValid():
|
if index.isValid():
|
||||||
row = self.index.row()
|
row = index.row()
|
||||||
account = self.account_order[row]
|
account = self.account_order[row]
|
||||||
self.accounts.pop(account)
|
self.accounts.pop(account)
|
||||||
self.account_order = sorted(self.accounts.keys())
|
self.account_order = sorted(self.accounts.keys())
|
||||||
@ -425,6 +425,8 @@ class ConfigDialog(QDialog, Ui_Dialog):
|
|||||||
self.email_view.resizeColumnsToContents()
|
self.email_view.resizeColumnsToContents()
|
||||||
self.connect(self.test_email_button, SIGNAL('clicked(bool)'),
|
self.connect(self.test_email_button, SIGNAL('clicked(bool)'),
|
||||||
self.test_email)
|
self.test_email)
|
||||||
|
self.connect(self.email_remove, SIGNAL('clicked()'),
|
||||||
|
self.remove_email_account)
|
||||||
|
|
||||||
def add_email_account(self, checked):
|
def add_email_account(self, checked):
|
||||||
index = self._email_accounts.add()
|
index = self._email_accounts.add()
|
||||||
@ -432,6 +434,10 @@ class ConfigDialog(QDialog, Ui_Dialog):
|
|||||||
self.email_view.resizeColumnsToContents()
|
self.email_view.resizeColumnsToContents()
|
||||||
self.email_view.edit(index)
|
self.email_view.edit(index)
|
||||||
|
|
||||||
|
def remove_email_account(self, *args):
|
||||||
|
idx = self.email_view.currentIndex()
|
||||||
|
self._email_accounts.remove(idx)
|
||||||
|
|
||||||
def create_gmail_relay(self, *args):
|
def create_gmail_relay(self, *args):
|
||||||
self.relay_username.setText('@gmail.com')
|
self.relay_username.setText('@gmail.com')
|
||||||
self.relay_password.setText('')
|
self.relay_password.setText('')
|
||||||
|
@ -727,7 +727,7 @@
|
|||||||
<string> px</string>
|
<string> px</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximum" >
|
<property name="maximum" >
|
||||||
<number>200</number>
|
<number>250</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="value" >
|
<property name="value" >
|
||||||
<number>20</number>
|
<number>20</number>
|
||||||
@ -750,7 +750,7 @@
|
|||||||
<string> px</string>
|
<string> px</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximum" >
|
<property name="maximum" >
|
||||||
<number>200</number>
|
<number>250</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="value" >
|
<property name="value" >
|
||||||
<number>20</number>
|
<number>20</number>
|
||||||
@ -773,7 +773,7 @@
|
|||||||
<string> px</string>
|
<string> px</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximum" >
|
<property name="maximum" >
|
||||||
<number>200</number>
|
<number>250</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="value" >
|
<property name="value" >
|
||||||
<number>10</number>
|
<number>10</number>
|
||||||
@ -796,7 +796,7 @@
|
|||||||
<string> px</string>
|
<string> px</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximum" >
|
<property name="maximum" >
|
||||||
<number>200</number>
|
<number>250</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="value" >
|
<property name="value" >
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
|
BIN
src/calibre/gui2/images/news/laprensa_ni.png
Normal file
BIN
src/calibre/gui2/images/news/laprensa_ni.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 638 B |
@ -6,7 +6,7 @@ from PyQt4.QtCore import Qt, QByteArray, SIGNAL
|
|||||||
from PyQt4.QtGui import QGraphicsRectItem, QGraphicsScene, QPen, \
|
from PyQt4.QtGui import QGraphicsRectItem, QGraphicsScene, QPen, \
|
||||||
QBrush, QColor, QFontDatabase, \
|
QBrush, QColor, QFontDatabase, \
|
||||||
QGraphicsItem, QGraphicsLineItem
|
QGraphicsItem, QGraphicsLineItem
|
||||||
|
|
||||||
from calibre.gui2.lrf_renderer.text import TextBlock, FontLoader, COLOR, PixmapItem
|
from calibre.gui2.lrf_renderer.text import TextBlock, FontLoader, COLOR, PixmapItem
|
||||||
|
|
||||||
|
|
||||||
@ -25,17 +25,17 @@ class Pen(QPen):
|
|||||||
|
|
||||||
|
|
||||||
class ContentObject(object):
|
class ContentObject(object):
|
||||||
|
|
||||||
has_content = True
|
has_content = True
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
self.has_content = True
|
self.has_content = True
|
||||||
|
|
||||||
|
|
||||||
class RuledLine(QGraphicsLineItem, ContentObject):
|
class RuledLine(QGraphicsLineItem, ContentObject):
|
||||||
|
|
||||||
map = {'solid': Qt.SolidLine, 'dashed': Qt.DashLine, 'dotted': Qt.DotLine, 'double': Qt.DashDotLine}
|
map = {'solid': Qt.SolidLine, 'dashed': Qt.DashLine, 'dotted': Qt.DotLine, 'double': Qt.DashDotLine}
|
||||||
|
|
||||||
def __init__(self, rl):
|
def __init__(self, rl):
|
||||||
QGraphicsLineItem.__init__(self, 0, 0, rl.linelength, 0)
|
QGraphicsLineItem.__init__(self, 0, 0, rl.linelength, 0)
|
||||||
ContentObject.__init__(self)
|
ContentObject.__init__(self)
|
||||||
@ -43,7 +43,7 @@ class RuledLine(QGraphicsLineItem, ContentObject):
|
|||||||
|
|
||||||
|
|
||||||
class ImageBlock(PixmapItem, ContentObject):
|
class ImageBlock(PixmapItem, ContentObject):
|
||||||
|
|
||||||
def __init__(self, obj):
|
def __init__(self, obj):
|
||||||
ContentObject.__init__(self)
|
ContentObject.__init__(self)
|
||||||
x0, y0, x1, y1 = obj.attrs['x0'], obj.attrs['y0'], obj.attrs['x1'], obj.attrs['y1']
|
x0, y0, x1, y1 = obj.attrs['x0'], obj.attrs['y0'], obj.attrs['x1'], obj.attrs['y1']
|
||||||
@ -51,26 +51,26 @@ class ImageBlock(PixmapItem, ContentObject):
|
|||||||
data, encoding = refstream.stream, refstream.encoding
|
data, encoding = refstream.stream, refstream.encoding
|
||||||
PixmapItem.__init__(self, data, encoding, x0, y0, x1, y1, xsize, ysize)
|
PixmapItem.__init__(self, data, encoding, x0, y0, x1, y1, xsize, ysize)
|
||||||
self.block_id = obj.id
|
self.block_id = obj.id
|
||||||
|
|
||||||
|
|
||||||
def object_factory(container, obj, respect_max_y=False):
|
def object_factory(container, obj, respect_max_y=False):
|
||||||
if hasattr(obj, 'name'):
|
if hasattr(obj, 'name'):
|
||||||
if obj.name.endswith('TextBlock'):
|
if obj.name.endswith('TextBlock'):
|
||||||
|
|
||||||
return TextBlock(obj, container.font_loader, respect_max_y, container.text_width,
|
return TextBlock(obj, container.font_loader, respect_max_y, container.text_width,
|
||||||
container.logger, container.opts, container.ruby_tags,
|
container.logger, container.opts, container.ruby_tags,
|
||||||
container.link_activated)
|
container.link_activated)
|
||||||
elif obj.name.endswith('ImageBlock'):
|
elif obj.name.endswith('ImageBlock'):
|
||||||
return ImageBlock(obj)
|
return ImageBlock(obj)
|
||||||
elif isinstance(obj, _RuledLine):
|
elif isinstance(obj, _RuledLine):
|
||||||
return RuledLine(obj)
|
return RuledLine(obj)
|
||||||
elif isinstance(obj, __Canvas):
|
elif isinstance(obj, __Canvas):
|
||||||
return Canvas(container.font_loader, obj, container.logger, container.opts,
|
return Canvas(container.font_loader, obj, container.logger, container.opts,
|
||||||
container.ruby_tags, container.link_activated)
|
container.ruby_tags, container.link_activated)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
class _Canvas(QGraphicsRectItem):
|
class _Canvas(QGraphicsRectItem):
|
||||||
|
|
||||||
def __init__(self, font_loader, logger, opts, width=0, height=0, parent=None, x=0, y=0):
|
def __init__(self, font_loader, logger, opts, width=0, height=0, parent=None, x=0, y=0):
|
||||||
QGraphicsRectItem.__init__(self, x, y, width, height, parent)
|
QGraphicsRectItem.__init__(self, x, y, width, height, parent)
|
||||||
self.font_loader, self.logger, self.opts = font_loader, logger, opts
|
self.font_loader, self.logger, self.opts = font_loader, logger, opts
|
||||||
@ -79,7 +79,7 @@ class _Canvas(QGraphicsRectItem):
|
|||||||
pen = QPen()
|
pen = QPen()
|
||||||
pen.setStyle(Qt.NoPen)
|
pen.setStyle(Qt.NoPen)
|
||||||
self.setPen(pen)
|
self.setPen(pen)
|
||||||
|
|
||||||
def layout_block(self, block, x, y):
|
def layout_block(self, block, x, y):
|
||||||
if isinstance(block, TextBlock):
|
if isinstance(block, TextBlock):
|
||||||
self.layout_text_block(block, x, y)
|
self.layout_text_block(block, x, y)
|
||||||
@ -89,17 +89,17 @@ class _Canvas(QGraphicsRectItem):
|
|||||||
self.layout_image_block(block, x, y)
|
self.layout_image_block(block, x, y)
|
||||||
elif isinstance(block, Canvas):
|
elif isinstance(block, Canvas):
|
||||||
self.layout_canvas(block, x, y)
|
self.layout_canvas(block, x, y)
|
||||||
|
|
||||||
def layout_canvas(self, canvas, x, y):
|
def layout_canvas(self, canvas, x, y):
|
||||||
if canvas.max_y + y > self.max_y and y > 0:
|
if canvas.max_y + y > self.max_y and y > 0:
|
||||||
self.is_full = True
|
self.is_full = True
|
||||||
return
|
return
|
||||||
canvas.setParentItem(self)
|
canvas.setParentItem(self)
|
||||||
canvas.setPos(x, y)
|
canvas.setPos(x, y)
|
||||||
canvas.has_content = False
|
canvas.has_content = False
|
||||||
canvas.put_objects()
|
canvas.put_objects()
|
||||||
self.current_y += canvas.max_y
|
self.current_y += canvas.max_y
|
||||||
|
|
||||||
def layout_text_block(self, block, x, y):
|
def layout_text_block(self, block, x, y):
|
||||||
textwidth = block.bs.blockwidth - block.bs.sidemargin
|
textwidth = block.bs.blockwidth - block.bs.sidemargin
|
||||||
if block.max_y == 0 or not block.lines: # Empty block skipping
|
if block.max_y == 0 or not block.lines: # Empty block skipping
|
||||||
@ -128,15 +128,15 @@ class _Canvas(QGraphicsRectItem):
|
|||||||
line = block.peek()
|
line = block.peek()
|
||||||
self.current_y = y
|
self.current_y = y
|
||||||
self.is_full = not block_consumed
|
self.is_full = not block_consumed
|
||||||
|
|
||||||
def layout_ruled_line(self, rl, x, y):
|
def layout_ruled_line(self, rl, x, y):
|
||||||
br = rl.boundingRect()
|
br = rl.boundingRect()
|
||||||
rl.setParentItem(self)
|
rl.setParentItem(self)
|
||||||
rl.setPos(x, y+1)
|
rl.setPos(x, y+1)
|
||||||
self.current_y = y + br.height() + 1
|
self.current_y = y + br.height() + 1
|
||||||
self.is_full = y > self.max_y-5
|
self.is_full = y > self.max_y-5
|
||||||
rl.has_content = False
|
rl.has_content = False
|
||||||
|
|
||||||
def layout_image_block(self, ib, x, y):
|
def layout_image_block(self, ib, x, y):
|
||||||
mw, mh = self.max_x - x, self.max_y - y
|
mw, mh = self.max_x - x, self.max_y - y
|
||||||
if self.current_y + ib.height > self.max_y-y and self.current_y > 5:
|
if self.current_y + ib.height > self.max_y-y and self.current_y > 5:
|
||||||
@ -161,8 +161,8 @@ class _Canvas(QGraphicsRectItem):
|
|||||||
print
|
print
|
||||||
print ib.block_id, ib.has_content, self.is_full
|
print ib.block_id, ib.has_content, self.is_full
|
||||||
print self.current_y, self.max_y, y, br.height()
|
print self.current_y, self.max_y, y, br.height()
|
||||||
print
|
print
|
||||||
|
|
||||||
def search(self, phrase):
|
def search(self, phrase):
|
||||||
matches = []
|
matches = []
|
||||||
for child in self.children():
|
for child in self.children():
|
||||||
@ -174,11 +174,11 @@ class _Canvas(QGraphicsRectItem):
|
|||||||
else:
|
else:
|
||||||
matches.append(res)
|
matches.append(res)
|
||||||
return matches
|
return matches
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Canvas(_Canvas, ContentObject):
|
class Canvas(_Canvas, ContentObject):
|
||||||
|
|
||||||
def __init__(self, font_loader, canvas, logger, opts, ruby_tags, link_activated, width=0, height=0):
|
def __init__(self, font_loader, canvas, logger, opts, ruby_tags, link_activated, width=0, height=0):
|
||||||
if hasattr(canvas, 'canvaswidth'):
|
if hasattr(canvas, 'canvaswidth'):
|
||||||
width, height = canvas.canvaswidth, canvas.canvasheight
|
width, height = canvas.canvaswidth, canvas.canvasheight
|
||||||
@ -198,11 +198,11 @@ class Canvas(_Canvas, ContentObject):
|
|||||||
item = object_factory(self, obj, respect_max_y=True)
|
item = object_factory(self, obj, respect_max_y=True)
|
||||||
if item:
|
if item:
|
||||||
self.items.append((item, po.x1, po.y1))
|
self.items.append((item, po.x1, po.y1))
|
||||||
|
|
||||||
def put_objects(self):
|
def put_objects(self):
|
||||||
for block, x, y in self.items:
|
for block, x, y in self.items:
|
||||||
self.layout_block(block, x, y)
|
self.layout_block(block, x, y)
|
||||||
|
|
||||||
def layout_block(self, block, x, y):
|
def layout_block(self, block, x, y):
|
||||||
block.reset()
|
block.reset()
|
||||||
_Canvas.layout_block(self, block, x, y)
|
_Canvas.layout_block(self, block, x, y)
|
||||||
@ -212,17 +212,17 @@ class Header(Canvas):
|
|||||||
Canvas.__init__(self, font_loader, header, logger, opts, ruby_tags, link_activated,
|
Canvas.__init__(self, font_loader, header, logger, opts, ruby_tags, link_activated,
|
||||||
page_style.textwidth, page_style.headheight)
|
page_style.textwidth, page_style.headheight)
|
||||||
if opts.visual_debug:
|
if opts.visual_debug:
|
||||||
self.setPen(QPen(Qt.blue, 1, Qt.DashLine))
|
self.setPen(QPen(Qt.blue, 1, Qt.DashLine))
|
||||||
|
|
||||||
class Footer(Canvas):
|
class Footer(Canvas):
|
||||||
def __init__(self, font_loader, footer, page_style, logger, opts, ruby_tags, link_activated):
|
def __init__(self, font_loader, footer, page_style, logger, opts, ruby_tags, link_activated):
|
||||||
Canvas.__init__(self, font_loader, footer, logger, opts, ruby_tags, link_activated,
|
Canvas.__init__(self, font_loader, footer, logger, opts, ruby_tags, link_activated,
|
||||||
page_style.textwidth, page_style.footheight)
|
page_style.textwidth, page_style.footheight)
|
||||||
if opts.visual_debug:
|
if opts.visual_debug:
|
||||||
self.setPen(QPen(Qt.blue, 1, Qt.DashLine))
|
self.setPen(QPen(Qt.blue, 1, Qt.DashLine))
|
||||||
|
|
||||||
class Screen(_Canvas):
|
class Screen(_Canvas):
|
||||||
|
|
||||||
def __init__(self, font_loader, chapter, odd, logger, opts, ruby_tags, link_activated):
|
def __init__(self, font_loader, chapter, odd, logger, opts, ruby_tags, link_activated):
|
||||||
self.logger, self.opts = logger, opts
|
self.logger, self.opts = logger, opts
|
||||||
page_style = chapter.style
|
page_style = chapter.style
|
||||||
@ -231,11 +231,11 @@ class Screen(_Canvas):
|
|||||||
self.content_x = 0 + sidemargin
|
self.content_x = 0 + sidemargin
|
||||||
self.text_width = page_style.textwidth
|
self.text_width = page_style.textwidth
|
||||||
self.header_y = page_style.topmargin
|
self.header_y = page_style.topmargin
|
||||||
|
|
||||||
self.text_y = self.header_y + page_style.headheight + page_style.headsep
|
self.text_y = self.header_y + page_style.headheight + page_style.headsep
|
||||||
self.text_height = page_style.textheight
|
self.text_height = page_style.textheight
|
||||||
self.footer_y = self.text_y + self.text_height + (page_style.footspace - page_style.footheight)
|
self.footer_y = self.text_y + self.text_height + (page_style.footspace - page_style.footheight)
|
||||||
|
|
||||||
_Canvas.__init__(self, font_loader, logger, opts, width=width, height=self.footer_y+page_style.footheight)
|
_Canvas.__init__(self, font_loader, logger, opts, width=width, height=self.footer_y+page_style.footheight)
|
||||||
if opts.visual_debug:
|
if opts.visual_debug:
|
||||||
self.setPen(QPen(Qt.red, 1, Qt.SolidLine))
|
self.setPen(QPen(Qt.red, 1, Qt.SolidLine))
|
||||||
@ -256,57 +256,57 @@ class Screen(_Canvas):
|
|||||||
if footer:
|
if footer:
|
||||||
footer = Footer(font_loader, footer, page_style, logger, opts, ruby_tags, link_activated)
|
footer = Footer(font_loader, footer, page_style, logger, opts, ruby_tags, link_activated)
|
||||||
self.layout_canvas(footer, self.content_x, self.header_y)
|
self.layout_canvas(footer, self.content_x, self.header_y)
|
||||||
|
|
||||||
self.page = None
|
self.page = None
|
||||||
|
|
||||||
def set_page(self, page):
|
def set_page(self, page):
|
||||||
if self.page is not None and self.page.scene():
|
if self.page is not None and self.page.scene():
|
||||||
self.scene().removeItem(self.page)
|
self.scene().removeItem(self.page)
|
||||||
self.page = page
|
self.page = page
|
||||||
self.page.setPos(self.content_x, self.text_y)
|
self.page.setPos(self.content_x, self.text_y)
|
||||||
self.scene().addItem(self.page)
|
self.scene().addItem(self.page)
|
||||||
|
|
||||||
def remove(self):
|
def remove(self):
|
||||||
if self.scene():
|
if self.scene():
|
||||||
if self.page is not None and self.page.scene():
|
if self.page is not None and self.page.scene():
|
||||||
self.scene().removeItem(self.page)
|
self.scene().removeItem(self.page)
|
||||||
self.scene().removeItem(self)
|
self.scene().removeItem(self)
|
||||||
|
|
||||||
|
|
||||||
class Page(_Canvas):
|
class Page(_Canvas):
|
||||||
|
|
||||||
def __init__(self, font_loader, logger, opts, width, height):
|
def __init__(self, font_loader, logger, opts, width, height):
|
||||||
_Canvas.__init__(self, font_loader, logger, opts, width, height)
|
_Canvas.__init__(self, font_loader, logger, opts, width, height)
|
||||||
if opts.visual_debug:
|
if opts.visual_debug:
|
||||||
self.setPen(QPen(Qt.cyan, 1, Qt.DashLine))
|
self.setPen(QPen(Qt.cyan, 1, Qt.DashLine))
|
||||||
|
|
||||||
def id(self):
|
def id(self):
|
||||||
for child in self.children():
|
for child in self.children():
|
||||||
if hasattr(child, 'block_id'):
|
if hasattr(child, 'block_id'):
|
||||||
return child.block_id
|
return child.block_id
|
||||||
|
|
||||||
def add_block(self, block):
|
def add_block(self, block):
|
||||||
self.layout_block(block, 0, self.current_y)
|
self.layout_block(block, 0, self.current_y)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Chapter(object):
|
class Chapter(object):
|
||||||
|
|
||||||
num_of_pages = property(fget=lambda self: len(self.pages))
|
num_of_pages = property(fget=lambda self: len(self.pages))
|
||||||
|
|
||||||
def __init__(self, oddscreen, evenscreen, pages, object_to_page_map):
|
def __init__(self, oddscreen, evenscreen, pages, object_to_page_map):
|
||||||
self.oddscreen, self.evenscreen, self.pages, self.object_to_page_map = \
|
self.oddscreen, self.evenscreen, self.pages, self.object_to_page_map = \
|
||||||
oddscreen, evenscreen, pages, object_to_page_map
|
oddscreen, evenscreen, pages, object_to_page_map
|
||||||
|
|
||||||
def page_of_object(self, id):
|
def page_of_object(self, id):
|
||||||
return self.object_to_page_map[id]
|
return self.object_to_page_map[id]
|
||||||
|
|
||||||
def page(self, num):
|
def page(self, num):
|
||||||
return self.pages[num-1]
|
return self.pages[num-1]
|
||||||
|
|
||||||
def screen(self, odd):
|
def screen(self, odd):
|
||||||
return self.oddscreen if odd else self.evenscreen
|
return self.oddscreen if odd else self.evenscreen
|
||||||
|
|
||||||
def search(self, phrase):
|
def search(self, phrase):
|
||||||
pages = []
|
pages = []
|
||||||
for i in range(len(self.pages)):
|
for i in range(len(self.pages)):
|
||||||
@ -314,36 +314,36 @@ class Chapter(object):
|
|||||||
if matches:
|
if matches:
|
||||||
pages.append([i, matches])
|
pages.append([i, matches])
|
||||||
return pages
|
return pages
|
||||||
|
|
||||||
|
|
||||||
class History(collections.deque):
|
class History(collections.deque):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
collections.deque.__init__(self)
|
collections.deque.__init__(self)
|
||||||
self.pos = 0
|
self.pos = 0
|
||||||
|
|
||||||
def back(self):
|
def back(self):
|
||||||
if self.pos - 1 < 0: return None
|
if self.pos - 1 < 0: return None
|
||||||
self.pos -= 1
|
self.pos -= 1
|
||||||
return self[self.pos]
|
return self[self.pos]
|
||||||
|
|
||||||
def forward(self):
|
def forward(self):
|
||||||
if self.pos + 1 >= len(self): return None
|
if self.pos + 1 >= len(self): return None
|
||||||
self.pos += 1
|
self.pos += 1
|
||||||
return self[self.pos]
|
return self[self.pos]
|
||||||
|
|
||||||
def add(self, item):
|
def add(self, item):
|
||||||
while len(self) > self.pos+1:
|
while len(self) > self.pos+1:
|
||||||
self.pop()
|
self.pop()
|
||||||
self.append(item)
|
self.append(item)
|
||||||
self.pos += 1
|
self.pos += 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Document(QGraphicsScene):
|
class Document(QGraphicsScene):
|
||||||
|
|
||||||
num_of_pages = property(fget=lambda self: sum(self.chapter_layout))
|
num_of_pages = property(fget=lambda self: sum(self.chapter_layout))
|
||||||
|
|
||||||
def __init__(self, logger, opts):
|
def __init__(self, logger, opts):
|
||||||
QGraphicsScene.__init__(self)
|
QGraphicsScene.__init__(self)
|
||||||
self.logger, self.opts = logger, opts
|
self.logger, self.opts = logger, opts
|
||||||
@ -358,23 +358,23 @@ class Document(QGraphicsScene):
|
|||||||
self.last_search = iter([])
|
self.last_search = iter([])
|
||||||
if not opts.white_background:
|
if not opts.white_background:
|
||||||
self.setBackgroundBrush(QBrush(QColor(0xee, 0xee, 0xee)))
|
self.setBackgroundBrush(QBrush(QColor(0xee, 0xee, 0xee)))
|
||||||
|
|
||||||
def page_of(self, oid):
|
def page_of(self, oid):
|
||||||
for chapter in self.chapters:
|
for chapter in self.chapters:
|
||||||
if oid in chapter.object_to_page_map:
|
if oid in chapter.object_to_page_map:
|
||||||
return chapter.object_to_page_map[oid]
|
return chapter.object_to_page_map[oid]
|
||||||
|
|
||||||
def get_page_num(self, chapterid, objid):
|
def get_page_num(self, chapterid, objid):
|
||||||
cnum = self.chapter_map[chapterid]
|
cnum = self.chapter_map[chapterid]
|
||||||
page = self.chapters[cnum].object_to_page_map[objid]
|
page = self.chapters[cnum].object_to_page_map[objid]
|
||||||
return sum(self.chapter_layout[:cnum])+page
|
return sum(self.chapter_layout[:cnum])+page
|
||||||
|
|
||||||
def add_to_history(self):
|
def add_to_history(self):
|
||||||
page = self.chapter_page(self.current_page)[1]
|
page = self.chapter_page(self.current_page)[1]
|
||||||
page_id = page.id()
|
page_id = page.id()
|
||||||
if page_id is not None:
|
if page_id is not None:
|
||||||
self.history.add(page_id)
|
self.history.add(page_id)
|
||||||
|
|
||||||
def link_activated(self, objid, on_creation=None):
|
def link_activated(self, objid, on_creation=None):
|
||||||
if on_creation is None:
|
if on_creation is None:
|
||||||
cid, oid = self.link_map[objid]
|
cid, oid = self.link_map[objid]
|
||||||
@ -385,30 +385,30 @@ class Document(QGraphicsScene):
|
|||||||
else:
|
else:
|
||||||
jb = self.objects[objid]
|
jb = self.objects[objid]
|
||||||
self.link_map[objid] = (jb.refpage, jb.refobj)
|
self.link_map[objid] = (jb.refpage, jb.refobj)
|
||||||
|
|
||||||
|
|
||||||
def back(self):
|
def back(self):
|
||||||
oid = self.history.back()
|
oid = self.history.back()
|
||||||
if oid is not None:
|
if oid is not None:
|
||||||
page = self.page_of(oid)
|
page = self.page_of(oid)
|
||||||
self.show_page(page)
|
self.show_page(page)
|
||||||
|
|
||||||
def forward(self):
|
def forward(self):
|
||||||
oid = self.history.forward()
|
oid = self.history.forward()
|
||||||
if oid is not None:
|
if oid is not None:
|
||||||
page = self.page_of(oid)
|
page = self.page_of(oid)
|
||||||
self.show_page(page)
|
self.show_page(page)
|
||||||
|
|
||||||
|
|
||||||
def load_fonts(self, lrf, load_substitutions=True):
|
def load_fonts(self, lrf, load_substitutions=True):
|
||||||
font_map = {}
|
font_map = {}
|
||||||
|
|
||||||
for font in lrf.font_map:
|
for font in lrf.font_map:
|
||||||
fdata = QByteArray(lrf.font_map[font].data)
|
fdata = QByteArray(lrf.font_map[font].data)
|
||||||
id = QFontDatabase.addApplicationFontFromData(fdata)
|
id = QFontDatabase.addApplicationFontFromData(fdata)
|
||||||
if id != -1:
|
if id != -1:
|
||||||
font_map[font] = [str(i) for i in QFontDatabase.applicationFontFamilies(id)][0]
|
font_map[font] = [str(i) for i in QFontDatabase.applicationFontFamilies(id)][0]
|
||||||
|
|
||||||
if load_substitutions:
|
if load_substitutions:
|
||||||
from calibre.ebooks.lrf.fonts.liberation import LiberationMono_BoldItalic
|
from calibre.ebooks.lrf.fonts.liberation import LiberationMono_BoldItalic
|
||||||
QFontDatabase.addApplicationFontFromData(QByteArray(LiberationMono_BoldItalic.font_data))
|
QFontDatabase.addApplicationFontFromData(QByteArray(LiberationMono_BoldItalic.font_data))
|
||||||
@ -434,10 +434,10 @@ class Document(QGraphicsScene):
|
|||||||
QFontDatabase.addApplicationFontFromData(QByteArray(LiberationSerif_BoldItalic.font_data))
|
QFontDatabase.addApplicationFontFromData(QByteArray(LiberationSerif_BoldItalic.font_data))
|
||||||
from calibre.ebooks.lrf.fonts.liberation import LiberationSans_Regular
|
from calibre.ebooks.lrf.fonts.liberation import LiberationSans_Regular
|
||||||
QFontDatabase.addApplicationFontFromData(QByteArray(LiberationSans_Regular.font_data))
|
QFontDatabase.addApplicationFontFromData(QByteArray(LiberationSans_Regular.font_data))
|
||||||
|
|
||||||
self.font_loader = FontLoader(font_map, self.dpi)
|
self.font_loader = FontLoader(font_map, self.dpi)
|
||||||
|
|
||||||
|
|
||||||
def render_chapter(self, chapter, lrf):
|
def render_chapter(self, chapter, lrf):
|
||||||
oddscreen, evenscreen = Screen(self.font_loader, chapter, True, self.logger, self.opts, self.ruby_tags, self.link_activated), \
|
oddscreen, evenscreen = Screen(self.font_loader, chapter, True, self.logger, self.opts, self.ruby_tags, self.link_activated), \
|
||||||
Screen(self.font_loader, chapter, False, self.logger, self.opts, self.ruby_tags, self.link_activated)
|
Screen(self.font_loader, chapter, False, self.logger, self.opts, self.ruby_tags, self.link_activated)
|
||||||
@ -459,36 +459,36 @@ class Document(QGraphicsScene):
|
|||||||
if current_page:
|
if current_page:
|
||||||
pages.append(current_page)
|
pages.append(current_page)
|
||||||
self.chapters.append(Chapter(oddscreen, evenscreen, pages, object_to_page_map))
|
self.chapters.append(Chapter(oddscreen, evenscreen, pages, object_to_page_map))
|
||||||
self.chapter_map[chapter.id] = len(self.chapters)-1
|
self.chapter_map[chapter.id] = len(self.chapters)-1
|
||||||
|
|
||||||
|
|
||||||
def render(self, lrf, load_substitutions=True):
|
def render(self, lrf, load_substitutions=True):
|
||||||
self.dpi = lrf.device_info.dpi/10.
|
self.dpi = lrf.device_info.dpi/10.
|
||||||
self.ruby_tags = dict(**lrf.ruby_tags)
|
self.ruby_tags = dict(**lrf.ruby_tags)
|
||||||
self.load_fonts(lrf, load_substitutions)
|
self.load_fonts(lrf, load_substitutions)
|
||||||
self.objects = lrf.objects
|
self.objects = lrf.objects
|
||||||
|
|
||||||
num_chaps = 0
|
num_chaps = 0
|
||||||
for pt in lrf.page_trees:
|
for pt in lrf.page_trees:
|
||||||
for chapter in pt:
|
for chapter in pt:
|
||||||
num_chaps += 1
|
num_chaps += 1
|
||||||
self.emit(SIGNAL('chapter_rendered(int)'), num_chaps)
|
self.emit(SIGNAL('chapter_rendered(int)'), num_chaps)
|
||||||
|
|
||||||
for pt in lrf.page_trees:
|
for pt in lrf.page_trees:
|
||||||
for chapter in pt:
|
for chapter in pt:
|
||||||
self.render_chapter(chapter, lrf)
|
self.render_chapter(chapter, lrf)
|
||||||
|
|
||||||
self.emit(SIGNAL('chapter_rendered(int)'), -1)
|
self.emit(SIGNAL('chapter_rendered(int)'), -1)
|
||||||
self.chapter_layout = [i.num_of_pages for i in self.chapters]
|
self.chapter_layout = [i.num_of_pages for i in self.chapters]
|
||||||
self.objects = None
|
self.objects = None
|
||||||
|
|
||||||
def chapter_page(self, num):
|
def chapter_page(self, num):
|
||||||
for chapter in self.chapters:
|
for chapter in self.chapters:
|
||||||
if num <= chapter.num_of_pages:
|
if num <= chapter.num_of_pages:
|
||||||
break
|
break
|
||||||
num -= chapter.num_of_pages
|
num -= chapter.num_of_pages
|
||||||
return chapter, chapter.page(num)
|
return chapter, chapter.page(num)
|
||||||
|
|
||||||
def show_page(self, num):
|
def show_page(self, num):
|
||||||
if num < 1 or num > self.num_of_pages or num == self.current_page:
|
if num < 1 or num > self.num_of_pages or num == self.current_page:
|
||||||
return
|
return
|
||||||
@ -496,33 +496,33 @@ class Document(QGraphicsScene):
|
|||||||
self.current_page = num
|
self.current_page = num
|
||||||
chapter, page = self.chapter_page(num)
|
chapter, page = self.chapter_page(num)
|
||||||
screen = chapter.screen(odd)
|
screen = chapter.screen(odd)
|
||||||
|
|
||||||
if self.current_screen is not None and self.current_screen is not screen:
|
if self.current_screen is not None and self.current_screen is not screen:
|
||||||
self.current_screen.remove()
|
self.current_screen.remove()
|
||||||
self.current_screen = screen
|
self.current_screen = screen
|
||||||
if self.current_screen.scene() is None:
|
if self.current_screen.scene() is None:
|
||||||
self.addItem(self.current_screen)
|
self.addItem(self.current_screen)
|
||||||
|
|
||||||
self.current_screen.set_page(page)
|
self.current_screen.set_page(page)
|
||||||
self.emit(SIGNAL('page_changed(PyQt_PyObject)'), self.current_page)
|
self.emit(SIGNAL('page_changed(PyQt_PyObject)'), self.current_page)
|
||||||
|
|
||||||
|
|
||||||
def next(self):
|
def next(self):
|
||||||
self.next_by(1)
|
self.next_by(1)
|
||||||
|
|
||||||
def previous(self):
|
def previous(self):
|
||||||
self.previous_by(1)
|
self.previous_by(1)
|
||||||
|
|
||||||
def next_by(self, num):
|
def next_by(self, num):
|
||||||
self.show_page(self.current_page + num)
|
self.show_page(self.current_page + num)
|
||||||
|
|
||||||
def previous_by(self, num):
|
def previous_by(self, num):
|
||||||
self.show_page(self.current_page - num)
|
self.show_page(self.current_page - num)
|
||||||
|
|
||||||
def show_page_at_percent(self, p):
|
def show_page_at_percent(self, p):
|
||||||
num = self.num_of_pages*(p/100.)
|
num = self.num_of_pages*(p/100.)
|
||||||
self.show_page(num)
|
self.show_page(num)
|
||||||
|
|
||||||
def search(self, phrase):
|
def search(self, phrase):
|
||||||
if not phrase:
|
if not phrase:
|
||||||
return
|
return
|
||||||
@ -534,7 +534,7 @@ class Document(QGraphicsScene):
|
|||||||
matches += cmatches
|
matches += cmatches
|
||||||
self.last_search = itertools.cycle(matches)
|
self.last_search = itertools.cycle(matches)
|
||||||
self.next_match()
|
self.next_match()
|
||||||
|
|
||||||
def next_match(self):
|
def next_match(self):
|
||||||
page_num = self.last_search.next()[0]
|
page_num = self.last_search.next()[0]
|
||||||
if self.current_page == page_num:
|
if self.current_page == page_num:
|
||||||
@ -542,4 +542,4 @@ class Document(QGraphicsScene):
|
|||||||
else:
|
else:
|
||||||
self.add_to_history()
|
self.add_to_history()
|
||||||
self.show_page(page_num)
|
self.show_page(page_num)
|
||||||
|
|
||||||
|
@ -52,29 +52,29 @@ def config(defaults=None):
|
|||||||
c = Config('viewer', desc)
|
c = Config('viewer', desc)
|
||||||
else:
|
else:
|
||||||
c = StringConfig(defaults, desc)
|
c = StringConfig(defaults, desc)
|
||||||
|
|
||||||
c.add_opt('user_css', default='',
|
c.add_opt('user_css', default='',
|
||||||
help=_('Set the user CSS stylesheet. This can be used to customize the look of all books.'))
|
help=_('Set the user CSS stylesheet. This can be used to customize the look of all books.'))
|
||||||
|
|
||||||
fonts = c.add_group('FONTS', _('Font options'))
|
fonts = c.add_group('FONTS', _('Font options'))
|
||||||
fonts('serif_family', default='Times New Roman' if iswindows else 'Liberation Serif',
|
fonts('serif_family', default='Times New Roman' if iswindows else 'Liberation Serif',
|
||||||
help=_('The serif font family'))
|
help=_('The serif font family'))
|
||||||
fonts('sans_family', default='Verdana' if iswindows else 'Liberation Sans',
|
fonts('sans_family', default='Verdana' if iswindows else 'Liberation Sans',
|
||||||
help=_('The sans-serif font family'))
|
help=_('The sans-serif font family'))
|
||||||
fonts('mono_family', default='Courier New' if iswindows else 'Liberation Mono',
|
fonts('mono_family', default='Courier New' if iswindows else 'Liberation Mono',
|
||||||
help=_('The monospaced font family'))
|
help=_('The monospaced font family'))
|
||||||
fonts('default_font_size', default=20, help=_('The standard font size in px'))
|
fonts('default_font_size', default=20, help=_('The standard font size in px'))
|
||||||
fonts('mono_font_size', default=16, help=_('The monospaced font size in px'))
|
fonts('mono_font_size', default=16, help=_('The monospaced font size in px'))
|
||||||
fonts('standard_font', default='serif', help=_('The standard font type'))
|
fonts('standard_font', default='serif', help=_('The standard font type'))
|
||||||
|
|
||||||
return c
|
return c
|
||||||
|
|
||||||
class ConfigDialog(QDialog, Ui_Dialog):
|
class ConfigDialog(QDialog, Ui_Dialog):
|
||||||
|
|
||||||
def __init__(self, *args):
|
def __init__(self, *args):
|
||||||
QDialog.__init__(self, *args)
|
QDialog.__init__(self, *args)
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
|
|
||||||
opts = config().parse()
|
opts = config().parse()
|
||||||
self.serif_family.setCurrentFont(QFont(opts.serif_family))
|
self.serif_family.setCurrentFont(QFont(opts.serif_family))
|
||||||
self.sans_family.setCurrentFont(QFont(opts.sans_family))
|
self.sans_family.setCurrentFont(QFont(opts.sans_family))
|
||||||
@ -84,7 +84,7 @@ class ConfigDialog(QDialog, Ui_Dialog):
|
|||||||
self.standard_font.setCurrentIndex({'serif':0, 'sans':1, 'mono':2}[opts.standard_font])
|
self.standard_font.setCurrentIndex({'serif':0, 'sans':1, 'mono':2}[opts.standard_font])
|
||||||
self.css.setPlainText(opts.user_css)
|
self.css.setPlainText(opts.user_css)
|
||||||
self.css.setToolTip(_('Set the user CSS stylesheet. This can be used to customize the look of all books.'))
|
self.css.setToolTip(_('Set the user CSS stylesheet. This can be used to customize the look of all books.'))
|
||||||
|
|
||||||
def accept(self, *args):
|
def accept(self, *args):
|
||||||
c = config()
|
c = config()
|
||||||
c.set('serif_family', unicode(self.serif_family.currentFont().family()))
|
c.set('serif_family', unicode(self.serif_family.currentFont().family()))
|
||||||
@ -95,10 +95,10 @@ class ConfigDialog(QDialog, Ui_Dialog):
|
|||||||
c.set('standard_font', {0:'serif', 1:'sans', 2:'mono'}[self.standard_font.currentIndex()])
|
c.set('standard_font', {0:'serif', 1:'sans', 2:'mono'}[self.standard_font.currentIndex()])
|
||||||
c.set('user_css', unicode(self.css.toPlainText()))
|
c.set('user_css', unicode(self.css.toPlainText()))
|
||||||
return QDialog.accept(self, *args)
|
return QDialog.accept(self, *args)
|
||||||
|
|
||||||
|
|
||||||
class Document(QWebPage):
|
class Document(QWebPage):
|
||||||
|
|
||||||
def set_font_settings(self):
|
def set_font_settings(self):
|
||||||
opts = config().parse()
|
opts = config().parse()
|
||||||
settings = self.settings()
|
settings = self.settings()
|
||||||
@ -110,14 +110,14 @@ class Document(QWebPage):
|
|||||||
settings.setFontFamily(QWebSettings.SerifFont, opts.serif_family)
|
settings.setFontFamily(QWebSettings.SerifFont, opts.serif_family)
|
||||||
settings.setFontFamily(QWebSettings.SansSerifFont, opts.sans_family)
|
settings.setFontFamily(QWebSettings.SansSerifFont, opts.sans_family)
|
||||||
settings.setFontFamily(QWebSettings.FixedFont, opts.mono_family)
|
settings.setFontFamily(QWebSettings.FixedFont, opts.mono_family)
|
||||||
|
|
||||||
def do_config(self, parent=None):
|
def do_config(self, parent=None):
|
||||||
d = ConfigDialog(parent)
|
d = ConfigDialog(parent)
|
||||||
if d.exec_() == QDialog.Accepted:
|
if d.exec_() == QDialog.Accepted:
|
||||||
self.set_font_settings()
|
self.set_font_settings()
|
||||||
self.set_user_stylesheet()
|
self.set_user_stylesheet()
|
||||||
self.triggerAction(QWebPage.Reload)
|
self.triggerAction(QWebPage.Reload)
|
||||||
|
|
||||||
def __init__(self, *args):
|
def __init__(self, *args):
|
||||||
QWebPage.__init__(self, *args)
|
QWebPage.__init__(self, *args)
|
||||||
self.setLinkDelegationPolicy(self.DelegateAllLinks)
|
self.setLinkDelegationPolicy(self.DelegateAllLinks)
|
||||||
@ -125,53 +125,53 @@ class Document(QWebPage):
|
|||||||
pal = self.palette()
|
pal = self.palette()
|
||||||
pal.setBrush(QPalette.Background, QColor(0xee, 0xee, 0xee))
|
pal.setBrush(QPalette.Background, QColor(0xee, 0xee, 0xee))
|
||||||
self.setPalette(pal)
|
self.setPalette(pal)
|
||||||
|
|
||||||
settings = self.settings()
|
settings = self.settings()
|
||||||
|
|
||||||
# Fonts
|
# Fonts
|
||||||
load_builtin_fonts()
|
load_builtin_fonts()
|
||||||
self.set_font_settings()
|
self.set_font_settings()
|
||||||
|
|
||||||
# Security
|
# Security
|
||||||
settings.setAttribute(QWebSettings.JavaEnabled, False)
|
settings.setAttribute(QWebSettings.JavaEnabled, False)
|
||||||
settings.setAttribute(QWebSettings.PluginsEnabled, False)
|
settings.setAttribute(QWebSettings.PluginsEnabled, False)
|
||||||
settings.setAttribute(QWebSettings.JavascriptCanOpenWindows, False)
|
settings.setAttribute(QWebSettings.JavascriptCanOpenWindows, False)
|
||||||
settings.setAttribute(QWebSettings.JavascriptCanAccessClipboard, False)
|
settings.setAttribute(QWebSettings.JavascriptCanAccessClipboard, False)
|
||||||
|
|
||||||
# Miscellaneous
|
# Miscellaneous
|
||||||
settings.setAttribute(QWebSettings.LinksIncludedInFocusChain, True)
|
settings.setAttribute(QWebSettings.LinksIncludedInFocusChain, True)
|
||||||
self.set_user_stylesheet()
|
self.set_user_stylesheet()
|
||||||
|
|
||||||
# Load jQuery
|
# Load jQuery
|
||||||
self.connect(self.mainFrame(), SIGNAL('javaScriptWindowObjectCleared()'),
|
self.connect(self.mainFrame(), SIGNAL('javaScriptWindowObjectCleared()'),
|
||||||
self.load_javascript_libraries)
|
self.load_javascript_libraries)
|
||||||
|
|
||||||
def set_user_stylesheet(self):
|
def set_user_stylesheet(self):
|
||||||
raw = config().parse().user_css
|
raw = config().parse().user_css
|
||||||
pt = PersistentTemporaryFile('_user_stylesheet.css')
|
pt = PersistentTemporaryFile('_user_stylesheet.css')
|
||||||
pt.write(raw.encode('utf-8'))
|
pt.write(raw.encode('utf-8'))
|
||||||
pt.close()
|
pt.close()
|
||||||
self.settings().setUserStyleSheetUrl(QUrl.fromLocalFile(pt.name))
|
self.settings().setUserStyleSheetUrl(QUrl.fromLocalFile(pt.name))
|
||||||
|
|
||||||
def load_javascript_libraries(self):
|
def load_javascript_libraries(self):
|
||||||
from calibre.resources import jquery, jquery_scrollTo
|
from calibre.resources import jquery, jquery_scrollTo
|
||||||
self.javascript(jquery)
|
self.javascript(jquery)
|
||||||
self.javascript(jquery_scrollTo)
|
self.javascript(jquery_scrollTo)
|
||||||
self.javascript(bookmarks)
|
self.javascript(bookmarks)
|
||||||
self.javascript(referencing)
|
self.javascript(referencing)
|
||||||
|
|
||||||
def reference_mode(self, enable):
|
def reference_mode(self, enable):
|
||||||
self.javascript(('enter' if enable else 'leave')+'_reference_mode()')
|
self.javascript(('enter' if enable else 'leave')+'_reference_mode()')
|
||||||
|
|
||||||
def set_reference_prefix(self, prefix):
|
def set_reference_prefix(self, prefix):
|
||||||
self.javascript('reference_prefix = "%s"'%prefix)
|
self.javascript('reference_prefix = "%s"'%prefix)
|
||||||
|
|
||||||
def goto(self, ref):
|
def goto(self, ref):
|
||||||
self.javascript('goto_reference("%s")'%ref)
|
self.javascript('goto_reference("%s")'%ref)
|
||||||
|
|
||||||
def goto_bookmark(self, bm):
|
def goto_bookmark(self, bm):
|
||||||
self.javascript('scroll_to_bookmark("%s")'%bm)
|
self.javascript('scroll_to_bookmark("%s")'%bm)
|
||||||
|
|
||||||
def javascript(self, string, typ=None):
|
def javascript(self, string, typ=None):
|
||||||
ans = self.mainFrame().evaluateJavaScript(string)
|
ans = self.mainFrame().evaluateJavaScript(string)
|
||||||
if typ == 'int':
|
if typ == 'int':
|
||||||
@ -182,65 +182,65 @@ class Document(QWebPage):
|
|||||||
if typ == 'string':
|
if typ == 'string':
|
||||||
return unicode(ans.toString())
|
return unicode(ans.toString())
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
def scroll_by(self, x=0, y=0):
|
def scroll_by(self, x=0, y=0):
|
||||||
self.javascript('window.scrollBy(%d, %d)'%(x, y))
|
self.javascript('window.scrollBy(%d, %d)'%(x, y))
|
||||||
|
|
||||||
def scroll_to(self, x=0, y=0):
|
def scroll_to(self, x=0, y=0):
|
||||||
self.javascript('window.scrollTo(%d, %d)'%(x, y))
|
self.javascript('window.scrollTo(%d, %d)'%(x, y))
|
||||||
|
|
||||||
def jump_to_anchor(self, anchor):
|
def jump_to_anchor(self, anchor):
|
||||||
self.javascript('document.location.hash = "%s"'%anchor)
|
self.javascript('document.location.hash = "%s"'%anchor)
|
||||||
|
|
||||||
def quantize(self):
|
def quantize(self):
|
||||||
if self.height > self.window_height:
|
if self.height > self.window_height:
|
||||||
r = self.height%self.window_height
|
r = self.height%self.window_height
|
||||||
if r > 0:
|
if r > 0:
|
||||||
self.javascript('document.body.style.paddingBottom = "%dpx"'%r)
|
self.javascript('document.body.style.paddingBottom = "%dpx"'%r)
|
||||||
|
|
||||||
def bookmark(self):
|
def bookmark(self):
|
||||||
return self.javascript('calculate_bookmark(%d)'%(self.ypos+25), 'string')
|
return self.javascript('calculate_bookmark(%d)'%(self.ypos+25), 'string')
|
||||||
|
|
||||||
@dynamic_property
|
@dynamic_property
|
||||||
def at_bottom(self):
|
def at_bottom(self):
|
||||||
def fget(self):
|
def fget(self):
|
||||||
return self.height - self.ypos <= self.window_height
|
return self.height - self.ypos <= self.window_height
|
||||||
return property(fget=fget)
|
return property(fget=fget)
|
||||||
|
|
||||||
@dynamic_property
|
@dynamic_property
|
||||||
def at_top(self):
|
def at_top(self):
|
||||||
def fget(self):
|
def fget(self):
|
||||||
return self.ypos <= 0
|
return self.ypos <= 0
|
||||||
return property(fget=fget)
|
return property(fget=fget)
|
||||||
|
|
||||||
|
|
||||||
def test(self):
|
def test(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@dynamic_property
|
@dynamic_property
|
||||||
def ypos(self):
|
def ypos(self):
|
||||||
def fget(self):
|
def fget(self):
|
||||||
return self.javascript('window.pageYOffset', 'int')
|
return self.javascript('window.pageYOffset', 'int')
|
||||||
return property(fget=fget)
|
return property(fget=fget)
|
||||||
|
|
||||||
@dynamic_property
|
@dynamic_property
|
||||||
def window_height(self):
|
def window_height(self):
|
||||||
def fget(self):
|
def fget(self):
|
||||||
return self.javascript('window.innerHeight', 'int')
|
return self.javascript('window.innerHeight', 'int')
|
||||||
return property(fget=fget)
|
return property(fget=fget)
|
||||||
|
|
||||||
@dynamic_property
|
@dynamic_property
|
||||||
def window_width(self):
|
def window_width(self):
|
||||||
def fget(self):
|
def fget(self):
|
||||||
return self.javascript('window.innerWidth', 'int')
|
return self.javascript('window.innerWidth', 'int')
|
||||||
return property(fget=fget)
|
return property(fget=fget)
|
||||||
|
|
||||||
@dynamic_property
|
@dynamic_property
|
||||||
def xpos(self):
|
def xpos(self):
|
||||||
def fget(self):
|
def fget(self):
|
||||||
return self.javascript('window.pageXOffset', 'int')
|
return self.javascript('window.pageXOffset', 'int')
|
||||||
return property(fget=fget)
|
return property(fget=fget)
|
||||||
|
|
||||||
@dynamic_property
|
@dynamic_property
|
||||||
def scroll_fraction(self):
|
def scroll_fraction(self):
|
||||||
def fget(self):
|
def fget(self):
|
||||||
@ -249,19 +249,19 @@ class Document(QWebPage):
|
|||||||
except ZeroDivisionError:
|
except ZeroDivisionError:
|
||||||
return 0.
|
return 0.
|
||||||
return property(fget=fget)
|
return property(fget=fget)
|
||||||
|
|
||||||
@dynamic_property
|
@dynamic_property
|
||||||
def hscroll_fraction(self):
|
def hscroll_fraction(self):
|
||||||
def fget(self):
|
def fget(self):
|
||||||
return float(self.xpos)/self.width
|
return float(self.xpos)/self.width
|
||||||
return property(fget=fget)
|
return property(fget=fget)
|
||||||
|
|
||||||
@dynamic_property
|
@dynamic_property
|
||||||
def height(self):
|
def height(self):
|
||||||
def fget(self):
|
def fget(self):
|
||||||
return self.javascript('document.body.offsetHeight', 'int') # contentsSize gives inaccurate results
|
return self.javascript('document.body.offsetHeight', 'int') # contentsSize gives inaccurate results
|
||||||
return property(fget=fget)
|
return property(fget=fget)
|
||||||
|
|
||||||
@dynamic_property
|
@dynamic_property
|
||||||
def width(self):
|
def width(self):
|
||||||
def fget(self):
|
def fget(self):
|
||||||
@ -269,7 +269,7 @@ class Document(QWebPage):
|
|||||||
return property(fget=fget)
|
return property(fget=fget)
|
||||||
|
|
||||||
class EntityDeclarationProcessor(object):
|
class EntityDeclarationProcessor(object):
|
||||||
|
|
||||||
def __init__(self, html):
|
def __init__(self, html):
|
||||||
self.declared_entities = {}
|
self.declared_entities = {}
|
||||||
for match in re.finditer(r'<!\s*ENTITY\s+([^>]+)>', html):
|
for match in re.finditer(r'<!\s*ENTITY\s+([^>]+)>', html):
|
||||||
@ -281,9 +281,9 @@ class EntityDeclarationProcessor(object):
|
|||||||
self.processed_html = self.processed_html.replace('&%s;'%key, val)
|
self.processed_html = self.processed_html.replace('&%s;'%key, val)
|
||||||
|
|
||||||
class DocumentView(QWebView):
|
class DocumentView(QWebView):
|
||||||
|
|
||||||
DISABLED_BRUSH = QBrush(Qt.lightGray, Qt.Dense5Pattern)
|
DISABLED_BRUSH = QBrush(Qt.lightGray, Qt.Dense5Pattern)
|
||||||
|
|
||||||
def __init__(self, *args):
|
def __init__(self, *args):
|
||||||
QWidget.__init__(self, *args)
|
QWidget.__init__(self, *args)
|
||||||
self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))
|
self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))
|
||||||
@ -299,83 +299,83 @@ class DocumentView(QWebView):
|
|||||||
self.connect(self.document, SIGNAL('linkClicked(QUrl)'), self.link_clicked)
|
self.connect(self.document, SIGNAL('linkClicked(QUrl)'), self.link_clicked)
|
||||||
self.connect(self.document, SIGNAL('linkHovered(QString,QString,QString)'), self.link_hovered)
|
self.connect(self.document, SIGNAL('linkHovered(QString,QString,QString)'), self.link_hovered)
|
||||||
self.connect(self.document, SIGNAL('selectionChanged()'), self.selection_changed)
|
self.connect(self.document, SIGNAL('selectionChanged()'), self.selection_changed)
|
||||||
|
|
||||||
def reference_mode(self, enable):
|
def reference_mode(self, enable):
|
||||||
self._reference_mode = enable
|
self._reference_mode = enable
|
||||||
self.document.reference_mode(enable)
|
self.document.reference_mode(enable)
|
||||||
|
|
||||||
def goto(self, ref):
|
def goto(self, ref):
|
||||||
self.document.goto(ref)
|
self.document.goto(ref)
|
||||||
|
|
||||||
def goto_bookmark(self, bm):
|
def goto_bookmark(self, bm):
|
||||||
self.document.goto_bookmark(bm)
|
self.document.goto_bookmark(bm)
|
||||||
|
|
||||||
def config(self, parent=None):
|
def config(self, parent=None):
|
||||||
self.document.do_config(parent)
|
self.document.do_config(parent)
|
||||||
|
|
||||||
def bookmark(self):
|
def bookmark(self):
|
||||||
return self.document.bookmark()
|
return self.document.bookmark()
|
||||||
|
|
||||||
def selection_changed(self):
|
def selection_changed(self):
|
||||||
if self.manager is not None:
|
if self.manager is not None:
|
||||||
self.manager.selection_changed(unicode(self.document.selectedText()))
|
self.manager.selection_changed(unicode(self.document.selectedText()))
|
||||||
|
|
||||||
def set_manager(self, manager):
|
def set_manager(self, manager):
|
||||||
self.manager = manager
|
self.manager = manager
|
||||||
self.scrollbar = manager.horizontal_scrollbar
|
self.scrollbar = manager.horizontal_scrollbar
|
||||||
self.connect(self.scrollbar, SIGNAL('valueChanged(int)'), self.scroll_horizontally)
|
self.connect(self.scrollbar, SIGNAL('valueChanged(int)'), self.scroll_horizontally)
|
||||||
|
|
||||||
def scroll_horizontally(self, amount):
|
def scroll_horizontally(self, amount):
|
||||||
self.document.scroll_to(y=self.document.ypos, x=amount)
|
self.document.scroll_to(y=self.document.ypos, x=amount)
|
||||||
|
|
||||||
def link_hovered(self, link, text, context):
|
def link_hovered(self, link, text, context):
|
||||||
link, text = unicode(link), unicode(text)
|
link, text = unicode(link), unicode(text)
|
||||||
if link:
|
if link:
|
||||||
self.setCursor(Qt.PointingHandCursor)
|
self.setCursor(Qt.PointingHandCursor)
|
||||||
else:
|
else:
|
||||||
self.unsetCursor()
|
self.unsetCursor()
|
||||||
|
|
||||||
def link_clicked(self, url):
|
def link_clicked(self, url):
|
||||||
if self.manager is not None:
|
if self.manager is not None:
|
||||||
self.manager.link_clicked(url)
|
self.manager.link_clicked(url)
|
||||||
|
|
||||||
def sizeHint(self):
|
def sizeHint(self):
|
||||||
return self._size_hint
|
return self._size_hint
|
||||||
|
|
||||||
@dynamic_property
|
@dynamic_property
|
||||||
def scroll_fraction(self):
|
def scroll_fraction(self):
|
||||||
def fget(self):
|
def fget(self):
|
||||||
return self.document.scroll_fraction
|
return self.document.scroll_fraction
|
||||||
return property(fget=fget)
|
return property(fget=fget)
|
||||||
|
|
||||||
@dynamic_property
|
@dynamic_property
|
||||||
def hscroll_fraction(self):
|
def hscroll_fraction(self):
|
||||||
def fget(self):
|
def fget(self):
|
||||||
return self.document.hscroll_fraction
|
return self.document.hscroll_fraction
|
||||||
return property(fget=fget)
|
return property(fget=fget)
|
||||||
|
|
||||||
@dynamic_property
|
@dynamic_property
|
||||||
def content_size(self):
|
def content_size(self):
|
||||||
def fget(self):
|
def fget(self):
|
||||||
return self.document.width, self.document.height
|
return self.document.width, self.document.height
|
||||||
return property(fget=fget)
|
return property(fget=fget)
|
||||||
|
|
||||||
def search(self, text):
|
def search(self, text):
|
||||||
return self.findText(text)
|
return self.findText(text)
|
||||||
|
|
||||||
def path(self):
|
def path(self):
|
||||||
return os.path.abspath(unicode(self.url().toLocalFile()))
|
return os.path.abspath(unicode(self.url().toLocalFile()))
|
||||||
|
|
||||||
def load_path(self, path, pos=0.0):
|
def load_path(self, path, pos=0.0):
|
||||||
self.initial_pos = pos
|
self.initial_pos = pos
|
||||||
html = open(path, 'rb').read().decode(path.encoding)
|
html = open(path, 'rb').read().decode(path.encoding, 'replace')
|
||||||
html = EntityDeclarationProcessor(html).processed_html
|
html = EntityDeclarationProcessor(html).processed_html
|
||||||
self.setHtml(html, QUrl.fromLocalFile(path))
|
self.setHtml(html, QUrl.fromLocalFile(path))
|
||||||
|
|
||||||
def load_started(self):
|
def load_started(self):
|
||||||
if self.manager is not None:
|
if self.manager is not None:
|
||||||
self.manager.load_started()
|
self.manager.load_started()
|
||||||
|
|
||||||
def initialize_scrollbar(self):
|
def initialize_scrollbar(self):
|
||||||
if getattr(self, 'scrollbar', None) is not None:
|
if getattr(self, 'scrollbar', None) is not None:
|
||||||
delta = self.document.width - self.size().width()
|
delta = self.document.width - self.size().width()
|
||||||
@ -387,7 +387,7 @@ class DocumentView(QWebView):
|
|||||||
self.scrollbar.setPageStep(int(delta/10.))
|
self.scrollbar.setPageStep(int(delta/10.))
|
||||||
self.scrollbar.blockSignals(False)
|
self.scrollbar.blockSignals(False)
|
||||||
self.scrollbar.setVisible(delta > 0)
|
self.scrollbar.setVisible(delta > 0)
|
||||||
|
|
||||||
def load_finished(self, ok):
|
def load_finished(self, ok):
|
||||||
self.document.mainFrame().setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff)
|
self.document.mainFrame().setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff)
|
||||||
self.document.mainFrame().setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff)
|
self.document.mainFrame().setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff)
|
||||||
@ -409,8 +409,8 @@ class DocumentView(QWebView):
|
|||||||
self.document.set_reference_prefix('%d.'%(spine_index+1))
|
self.document.set_reference_prefix('%d.'%(spine_index+1))
|
||||||
if scrolled:
|
if scrolled:
|
||||||
self.manager.scrolled(self.document.scroll_fraction)
|
self.manager.scrolled(self.document.scroll_fraction)
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def test_line(cls, img, y):
|
def test_line(cls, img, y):
|
||||||
start = img.pixel(0, y)
|
start = img.pixel(0, y)
|
||||||
@ -418,7 +418,7 @@ class DocumentView(QWebView):
|
|||||||
if img.pixel(i, y) != start:
|
if img.pixel(i, y) != start:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def find_next_blank_line(self, overlap):
|
def find_next_blank_line(self, overlap):
|
||||||
img = QImage(self.width(), overlap, QImage.Format_ARGB32)
|
img = QImage(self.width(), overlap, QImage.Format_ARGB32)
|
||||||
painter = QPainter(img)
|
painter = QPainter(img)
|
||||||
@ -428,8 +428,8 @@ class DocumentView(QWebView):
|
|||||||
if self.test_line(img, i):
|
if self.test_line(img, i):
|
||||||
self.scroll_by(y=i, notify=False)
|
self.scroll_by(y=i, notify=False)
|
||||||
return
|
return
|
||||||
self.scroll_by(y=overlap)
|
self.scroll_by(y=overlap)
|
||||||
|
|
||||||
def previous_page(self):
|
def previous_page(self):
|
||||||
if self.document.at_top:
|
if self.document.at_top:
|
||||||
if self.manager is not None:
|
if self.manager is not None:
|
||||||
@ -448,12 +448,12 @@ class DocumentView(QWebView):
|
|||||||
break
|
break
|
||||||
if self.manager is not None:
|
if self.manager is not None:
|
||||||
self.manager.scrolled(self.scroll_fraction)
|
self.manager.scrolled(self.scroll_fraction)
|
||||||
|
|
||||||
def wheel_event(self, down=True):
|
def wheel_event(self, down=True):
|
||||||
QWebView.wheelEvent(self,
|
QWebView.wheelEvent(self,
|
||||||
QWheelEvent(QPoint(100, 100), (-120 if down else 120),
|
QWheelEvent(QPoint(100, 100), (-120 if down else 120),
|
||||||
Qt.NoButton, Qt.NoModifier))
|
Qt.NoButton, Qt.NoModifier))
|
||||||
|
|
||||||
def next_page(self):
|
def next_page(self):
|
||||||
if self.document.at_bottom:
|
if self.document.at_bottom:
|
||||||
if self.manager is not None:
|
if self.manager is not None:
|
||||||
@ -472,14 +472,14 @@ class DocumentView(QWebView):
|
|||||||
self.find_next_blank_line( self.height() - (self.document.ypos-opos) )
|
self.find_next_blank_line( self.height() - (self.document.ypos-opos) )
|
||||||
if self.manager is not None:
|
if self.manager is not None:
|
||||||
self.manager.scrolled(self.scroll_fraction)
|
self.manager.scrolled(self.scroll_fraction)
|
||||||
|
|
||||||
|
|
||||||
def scroll_by(self, x=0, y=0, notify=True):
|
def scroll_by(self, x=0, y=0, notify=True):
|
||||||
old_pos = self.document.ypos
|
old_pos = self.document.ypos
|
||||||
self.document.scroll_by(x, y)
|
self.document.scroll_by(x, y)
|
||||||
if notify and self.manager is not None and self.document.ypos != old_pos:
|
if notify and self.manager is not None and self.document.ypos != old_pos:
|
||||||
self.manager.scrolled(self.scroll_fraction)
|
self.manager.scrolled(self.scroll_fraction)
|
||||||
|
|
||||||
def scroll_to(self, pos, notify=True):
|
def scroll_to(self, pos, notify=True):
|
||||||
old_pos = self.document.ypos
|
old_pos = self.document.ypos
|
||||||
if isinstance(pos, basestring):
|
if isinstance(pos, basestring):
|
||||||
@ -492,30 +492,30 @@ class DocumentView(QWebView):
|
|||||||
pos*(self.document.height-self.document.window_height))))
|
pos*(self.document.height-self.document.window_height))))
|
||||||
if notify and self.manager is not None and self.document.ypos != old_pos:
|
if notify and self.manager is not None and self.document.ypos != old_pos:
|
||||||
self.manager.scrolled(self.scroll_fraction)
|
self.manager.scrolled(self.scroll_fraction)
|
||||||
|
|
||||||
def multiplier(self):
|
def multiplier(self):
|
||||||
return self.document.mainFrame().textSizeMultiplier()
|
return self.document.mainFrame().textSizeMultiplier()
|
||||||
|
|
||||||
def magnify_fonts(self):
|
def magnify_fonts(self):
|
||||||
self.document.mainFrame().setTextSizeMultiplier(self.multiplier()+0.2)
|
self.document.mainFrame().setTextSizeMultiplier(self.multiplier()+0.2)
|
||||||
return self.document.scroll_fraction
|
return self.document.scroll_fraction
|
||||||
|
|
||||||
def shrink_fonts(self):
|
def shrink_fonts(self):
|
||||||
self.document.mainFrame().setTextSizeMultiplier(max(self.multiplier()-0.2, 0))
|
self.document.mainFrame().setTextSizeMultiplier(max(self.multiplier()-0.2, 0))
|
||||||
return self.document.scroll_fraction
|
return self.document.scroll_fraction
|
||||||
|
|
||||||
def changeEvent(self, event):
|
def changeEvent(self, event):
|
||||||
if event.type() == event.EnabledChange:
|
if event.type() == event.EnabledChange:
|
||||||
self.update()
|
self.update()
|
||||||
return QWebView.changeEvent(self, event)
|
return QWebView.changeEvent(self, event)
|
||||||
|
|
||||||
def paintEvent(self, event):
|
def paintEvent(self, event):
|
||||||
painter = QPainter(self)
|
painter = QPainter(self)
|
||||||
self.document.mainFrame().render(painter, event.region())
|
self.document.mainFrame().render(painter, event.region())
|
||||||
if not self.isEnabled():
|
if not self.isEnabled():
|
||||||
painter.fillRect(event.region().boundingRect(), self.DISABLED_BRUSH)
|
painter.fillRect(event.region().boundingRect(), self.DISABLED_BRUSH)
|
||||||
painter.end()
|
painter.end()
|
||||||
|
|
||||||
def wheelEvent(self, event):
|
def wheelEvent(self, event):
|
||||||
if event.delta() < -14:
|
if event.delta() < -14:
|
||||||
if self.document.at_bottom:
|
if self.document.at_bottom:
|
||||||
@ -533,7 +533,7 @@ class DocumentView(QWebView):
|
|||||||
if self.manager is not None:
|
if self.manager is not None:
|
||||||
self.manager.scrolled(self.scroll_fraction)
|
self.manager.scrolled(self.scroll_fraction)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def keyPressEvent(self, event):
|
def keyPressEvent(self, event):
|
||||||
key = event.key()
|
key = event.key()
|
||||||
if key in [Qt.Key_PageDown, Qt.Key_Space, Qt.Key_Down]:
|
if key in [Qt.Key_PageDown, Qt.Key_Space, Qt.Key_Down]:
|
||||||
@ -562,14 +562,14 @@ class DocumentView(QWebView):
|
|||||||
self.scroll_by(x=15)
|
self.scroll_by(x=15)
|
||||||
else:
|
else:
|
||||||
return QWebView.keyPressEvent(self, event)
|
return QWebView.keyPressEvent(self, event)
|
||||||
|
|
||||||
def resizeEvent(self, event):
|
def resizeEvent(self, event):
|
||||||
ret = QWebView.resizeEvent(self, event)
|
ret = QWebView.resizeEvent(self, event)
|
||||||
QTimer.singleShot(10, self.initialize_scrollbar)
|
QTimer.singleShot(10, self.initialize_scrollbar)
|
||||||
if self.manager is not None:
|
if self.manager is not None:
|
||||||
self.manager.viewport_resized(self.scroll_fraction)
|
self.manager.viewport_resized(self.scroll_fraction)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def mouseReleaseEvent(self, ev):
|
def mouseReleaseEvent(self, ev):
|
||||||
opos = self.document.ypos
|
opos = self.document.ypos
|
||||||
ret = QWebView.mouseReleaseEvent(self, ev)
|
ret = QWebView.mouseReleaseEvent(self, ev)
|
||||||
@ -578,4 +578,4 @@ class DocumentView(QWebView):
|
|||||||
self.manager.scrolled(self.scroll_fraction)
|
self.manager.scrolled(self.scroll_fraction)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ function find_enclosing_block(y) {
|
|||||||
if (min != 0 && min.height() < 200) break;
|
if (min != 0 && min.height() < 200) break;
|
||||||
}
|
}
|
||||||
if (y <= 0) return document.body;
|
if (y <= 0) return document.body;
|
||||||
if (min == 0) { return find_enclosing_block(x, y-20); }
|
if (min == 0) { return find_enclosing_block(y-20); }
|
||||||
return min;
|
return min;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ function enter_reference_mode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function leave_reference_mode() {
|
function leave_reference_mode() {
|
||||||
$("p").unbind("mouseenter mouseleave", toggle_reference);
|
$("p").unbind("mouseenter mouseleave", toggle_reference);
|
||||||
}
|
}
|
||||||
|
|
||||||
function goto_reference(ref) {
|
function goto_reference(ref) {
|
||||||
@ -118,4 +118,4 @@ $(document.body).click(function(e) {
|
|||||||
|
|
||||||
$(document).ready(enter_reference_mode);
|
$(document).ready(enter_reference_mode);
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
@ -27,7 +27,7 @@ from calibre.gui2.library import SearchBox
|
|||||||
from calibre.ebooks.metadata import MetaInformation
|
from calibre.ebooks.metadata import MetaInformation
|
||||||
|
|
||||||
class TOCItem(QStandardItem):
|
class TOCItem(QStandardItem):
|
||||||
|
|
||||||
def __init__(self, toc):
|
def __init__(self, toc):
|
||||||
QStandardItem.__init__(self, toc.text if toc.text else '')
|
QStandardItem.__init__(self, toc.text if toc.text else '')
|
||||||
self.abspath = toc.abspath
|
self.abspath = toc.abspath
|
||||||
@ -35,23 +35,23 @@ class TOCItem(QStandardItem):
|
|||||||
for t in toc:
|
for t in toc:
|
||||||
self.appendRow(TOCItem(t))
|
self.appendRow(TOCItem(t))
|
||||||
self.setFlags(Qt.ItemIsEnabled|Qt.ItemIsSelectable)
|
self.setFlags(Qt.ItemIsEnabled|Qt.ItemIsSelectable)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def type(cls):
|
def type(cls):
|
||||||
return QStandardItem.UserType+10
|
return QStandardItem.UserType+10
|
||||||
|
|
||||||
class TOC(QStandardItemModel):
|
class TOC(QStandardItemModel):
|
||||||
|
|
||||||
def __init__(self, toc):
|
def __init__(self, toc):
|
||||||
QStandardItemModel.__init__(self)
|
QStandardItemModel.__init__(self)
|
||||||
for t in toc:
|
for t in toc:
|
||||||
self.appendRow(TOCItem(t))
|
self.appendRow(TOCItem(t))
|
||||||
self.setHorizontalHeaderItem(0, QStandardItem(_('Table of Contents')))
|
self.setHorizontalHeaderItem(0, QStandardItem(_('Table of Contents')))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Worker(Thread):
|
class Worker(Thread):
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
try:
|
try:
|
||||||
Thread.run(self)
|
Thread.run(self)
|
||||||
@ -61,7 +61,7 @@ class Worker(Thread):
|
|||||||
self.traceback = traceback.format_exc()
|
self.traceback = traceback.format_exc()
|
||||||
|
|
||||||
class ProgressIndicator(QWidget):
|
class ProgressIndicator(QWidget):
|
||||||
|
|
||||||
def __init__(self, *args):
|
def __init__(self, *args):
|
||||||
QWidget.__init__(self, *args)
|
QWidget.__init__(self, *args)
|
||||||
self.setGeometry(0, 0, 300, 500)
|
self.setGeometry(0, 0, 300, 500)
|
||||||
@ -76,7 +76,7 @@ class ProgressIndicator(QWidget):
|
|||||||
self.status.font().setBold(True)
|
self.status.font().setBold(True)
|
||||||
self.status.font().setPointSize(self.font().pointSize()+6)
|
self.status.font().setPointSize(self.font().pointSize()+6)
|
||||||
self.setVisible(False)
|
self.setVisible(False)
|
||||||
|
|
||||||
def start(self, msg=''):
|
def start(self, msg=''):
|
||||||
view = self.parent()
|
view = self.parent()
|
||||||
pwidth, pheight = view.size().width(), view.size().height()
|
pwidth, pheight = view.size().width(), view.size().height()
|
||||||
@ -89,25 +89,25 @@ class ProgressIndicator(QWidget):
|
|||||||
self.status.setText(msg)
|
self.status.setText(msg)
|
||||||
self.setVisible(True)
|
self.setVisible(True)
|
||||||
self.movie.setPaused(False)
|
self.movie.setPaused(False)
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
if self.movie.state() == self.movie.Running:
|
if self.movie.state() == self.movie.Running:
|
||||||
self.movie.setPaused(True)
|
self.movie.setPaused(True)
|
||||||
self.setVisible(False)
|
self.setVisible(False)
|
||||||
|
|
||||||
class History(collections.deque):
|
class History(collections.deque):
|
||||||
|
|
||||||
def __init__(self, action_back, action_forward):
|
def __init__(self, action_back, action_forward):
|
||||||
self.action_back = action_back
|
self.action_back = action_back
|
||||||
self.action_forward = action_forward
|
self.action_forward = action_forward
|
||||||
collections.deque.__init__(self)
|
collections.deque.__init__(self)
|
||||||
self.pos = 0
|
self.pos = 0
|
||||||
self.set_actions()
|
self.set_actions()
|
||||||
|
|
||||||
def set_actions(self):
|
def set_actions(self):
|
||||||
self.action_back.setDisabled(self.pos < 1)
|
self.action_back.setDisabled(self.pos < 1)
|
||||||
self.action_forward.setDisabled(self.pos + 1 >= len(self))
|
self.action_forward.setDisabled(self.pos + 1 >= len(self))
|
||||||
|
|
||||||
def back(self, from_pos):
|
def back(self, from_pos):
|
||||||
if self.pos - 1 < 0: return None
|
if self.pos - 1 < 0: return None
|
||||||
if self.pos == len(self):
|
if self.pos == len(self):
|
||||||
@ -116,56 +116,56 @@ class History(collections.deque):
|
|||||||
self.pos -= 1
|
self.pos -= 1
|
||||||
self.set_actions()
|
self.set_actions()
|
||||||
return self[self.pos]
|
return self[self.pos]
|
||||||
|
|
||||||
def forward(self):
|
def forward(self):
|
||||||
if self.pos + 1 >= len(self): return None
|
if self.pos + 1 >= len(self): return None
|
||||||
self.pos += 1
|
self.pos += 1
|
||||||
self.set_actions()
|
self.set_actions()
|
||||||
return self[self.pos]
|
return self[self.pos]
|
||||||
|
|
||||||
def add(self, item):
|
def add(self, item):
|
||||||
while len(self) > self.pos+1:
|
while len(self) > self.pos+1:
|
||||||
self.pop()
|
self.pop()
|
||||||
self.append(item)
|
self.append(item)
|
||||||
self.pos += 1
|
self.pos += 1
|
||||||
self.set_actions()
|
self.set_actions()
|
||||||
|
|
||||||
class Metadata(QLabel):
|
class Metadata(QLabel):
|
||||||
|
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
QTextBrowser.__init__(self, parent.centralWidget())
|
QTextBrowser.__init__(self, parent.centralWidget())
|
||||||
self.view = parent.splitter
|
self.view = parent.splitter
|
||||||
self.setGeometry(self.view.geometry())
|
self.setGeometry(self.view.geometry())
|
||||||
self.setWordWrap(True)
|
self.setWordWrap(True)
|
||||||
self.setVisible(False)
|
self.setVisible(False)
|
||||||
|
|
||||||
def show_opf(self, opf):
|
def show_opf(self, opf):
|
||||||
mi = MetaInformation(opf)
|
mi = MetaInformation(opf)
|
||||||
html = '<h2 align="center">%s</h2>%s'%(_('Metadata'), u''.join(mi.to_html()))
|
html = '<h2 align="center">%s</h2>%s'%(_('Metadata'), u''.join(mi.to_html()))
|
||||||
self.setText(html)
|
self.setText(html)
|
||||||
|
|
||||||
def setVisible(self, x):
|
def setVisible(self, x):
|
||||||
self.setGeometry(self.view.geometry())
|
self.setGeometry(self.view.geometry())
|
||||||
QLabel.setVisible(self, x)
|
QLabel.setVisible(self, x)
|
||||||
|
|
||||||
def paintEvent(self, ev):
|
def paintEvent(self, ev):
|
||||||
p = QPainter(self)
|
p = QPainter(self)
|
||||||
p.fillRect(ev.region().boundingRect(), QBrush(QColor(200, 200, 200, 220), Qt.SolidPattern))
|
p.fillRect(ev.region().boundingRect(), QBrush(QColor(200, 200, 200, 220), Qt.SolidPattern))
|
||||||
p.end()
|
p.end()
|
||||||
QLabel.paintEvent(self, ev)
|
QLabel.paintEvent(self, ev)
|
||||||
|
|
||||||
|
|
||||||
class DoubleSpinBox(QDoubleSpinBox):
|
class DoubleSpinBox(QDoubleSpinBox):
|
||||||
|
|
||||||
def set_value(self, val):
|
def set_value(self, val):
|
||||||
self.blockSignals(True)
|
self.blockSignals(True)
|
||||||
self.setValue(val)
|
self.setValue(val)
|
||||||
self.blockSignals(False)
|
self.blockSignals(False)
|
||||||
|
|
||||||
class HelpfulLineEdit(QLineEdit):
|
class HelpfulLineEdit(QLineEdit):
|
||||||
|
|
||||||
HELP_TEXT = _('Go to...')
|
HELP_TEXT = _('Go to...')
|
||||||
|
|
||||||
def __init__(self, *args):
|
def __init__(self, *args):
|
||||||
QLineEdit.__init__(self, *args)
|
QLineEdit.__init__(self, *args)
|
||||||
self.default_palette = QApplication.palette(self)
|
self.default_palette = QApplication.palette(self)
|
||||||
@ -174,22 +174,22 @@ class HelpfulLineEdit(QLineEdit):
|
|||||||
self.connect(self, SIGNAL('editingFinished()'),
|
self.connect(self, SIGNAL('editingFinished()'),
|
||||||
lambda : self.emit(SIGNAL('goto(PyQt_PyObject)'), unicode(self.text())))
|
lambda : self.emit(SIGNAL('goto(PyQt_PyObject)'), unicode(self.text())))
|
||||||
self.clear_to_help_mode()
|
self.clear_to_help_mode()
|
||||||
|
|
||||||
def focusInEvent(self, ev):
|
def focusInEvent(self, ev):
|
||||||
self.setPalette(QApplication.palette(self))
|
self.setPalette(QApplication.palette(self))
|
||||||
if self.in_help_mode():
|
if self.in_help_mode():
|
||||||
self.setText('')
|
self.setText('')
|
||||||
return QLineEdit.focusInEvent(self, ev)
|
return QLineEdit.focusInEvent(self, ev)
|
||||||
|
|
||||||
def in_help_mode(self):
|
def in_help_mode(self):
|
||||||
return unicode(self.text()) == self.HELP_TEXT
|
return unicode(self.text()) == self.HELP_TEXT
|
||||||
|
|
||||||
def clear_to_help_mode(self):
|
def clear_to_help_mode(self):
|
||||||
self.setPalette(self.gray)
|
self.setPalette(self.gray)
|
||||||
self.setText(self.HELP_TEXT)
|
self.setText(self.HELP_TEXT)
|
||||||
|
|
||||||
class EbookViewer(MainWindow, Ui_EbookViewer):
|
class EbookViewer(MainWindow, Ui_EbookViewer):
|
||||||
|
|
||||||
def __init__(self, pathtoebook=None):
|
def __init__(self, pathtoebook=None):
|
||||||
MainWindow.__init__(self, None)
|
MainWindow.__init__(self, None)
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
@ -224,14 +224,14 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
self.action_quit = QAction(self)
|
self.action_quit = QAction(self)
|
||||||
self.addAction(self.action_quit)
|
self.addAction(self.action_quit)
|
||||||
self.action_quit.setShortcut(Qt.CTRL+Qt.Key_Q)
|
self.action_quit.setShortcut(Qt.CTRL+Qt.Key_Q)
|
||||||
self.connect(self.action_quit, SIGNAL('triggered(bool)'),
|
self.connect(self.action_quit, SIGNAL('triggered(bool)'),
|
||||||
lambda x:QApplication.instance().quit())
|
lambda x:QApplication.instance().quit())
|
||||||
self.action_copy.setDisabled(True)
|
self.action_copy.setDisabled(True)
|
||||||
self.action_metadata.setCheckable(True)
|
self.action_metadata.setCheckable(True)
|
||||||
self.action_metadata.setShortcut(Qt.CTRL+Qt.Key_I)
|
self.action_metadata.setShortcut(Qt.CTRL+Qt.Key_I)
|
||||||
self.action_table_of_contents.setCheckable(True)
|
self.action_table_of_contents.setCheckable(True)
|
||||||
self.action_reference_mode.setCheckable(True)
|
self.action_reference_mode.setCheckable(True)
|
||||||
self.connect(self.action_reference_mode, SIGNAL('triggered(bool)'),
|
self.connect(self.action_reference_mode, SIGNAL('triggered(bool)'),
|
||||||
lambda x: self.view.reference_mode(x))
|
lambda x: self.view.reference_mode(x))
|
||||||
self.connect(self.action_metadata, SIGNAL('triggered(bool)'), lambda x:self.metadata.setVisible(x))
|
self.connect(self.action_metadata, SIGNAL('triggered(bool)'), lambda x:self.metadata.setVisible(x))
|
||||||
self.connect(self.action_table_of_contents, SIGNAL('triggered(bool)'), lambda x:self.toc.setVisible(x))
|
self.connect(self.action_table_of_contents, SIGNAL('triggered(bool)'), lambda x:self.toc.setVisible(x))
|
||||||
@ -246,7 +246,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
lambda x:self.view.next_page())
|
lambda x:self.view.next_page())
|
||||||
self.connect(self.action_previous_page, SIGNAL('triggered(bool)'),
|
self.connect(self.action_previous_page, SIGNAL('triggered(bool)'),
|
||||||
lambda x:self.view.previous_page())
|
lambda x:self.view.previous_page())
|
||||||
self.connect(self.action_find_next, SIGNAL('triggered(bool)'),
|
self.connect(self.action_find_next, SIGNAL('triggered(bool)'),
|
||||||
lambda x:self.find(unicode(self.search.text()), True, repeat=True))
|
lambda x:self.find(unicode(self.search.text()), True, repeat=True))
|
||||||
self.connect(self.action_full_screen, SIGNAL('triggered(bool)'),
|
self.connect(self.action_full_screen, SIGNAL('triggered(bool)'),
|
||||||
self.toggle_fullscreen)
|
self.toggle_fullscreen)
|
||||||
@ -256,17 +256,16 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
self.connect(self.action_forward, SIGNAL('triggered(bool)'), self.forward)
|
self.connect(self.action_forward, SIGNAL('triggered(bool)'), self.forward)
|
||||||
self.connect(self.action_preferences, SIGNAL('triggered(bool)'), lambda x: self.view.config(self))
|
self.connect(self.action_preferences, SIGNAL('triggered(bool)'), lambda x: self.view.config(self))
|
||||||
self.connect(self.pos, SIGNAL('valueChanged(double)'), self.goto_page)
|
self.connect(self.pos, SIGNAL('valueChanged(double)'), self.goto_page)
|
||||||
self.connect(self.vertical_scrollbar, SIGNAL('valueChanged(int)'),
|
self.connect(self.vertical_scrollbar, SIGNAL('valueChanged(int)'),
|
||||||
lambda x: self.goto_page(x/100.))
|
lambda x: self.goto_page(x/100.))
|
||||||
self.connect(self.search, SIGNAL('search(PyQt_PyObject, PyQt_PyObject)'), self.find)
|
self.connect(self.search, SIGNAL('search(PyQt_PyObject, PyQt_PyObject)'), self.find)
|
||||||
self.connect(self.toc, SIGNAL('clicked(QModelIndex)'), self.toc_clicked)
|
self.connect(self.toc, SIGNAL('clicked(QModelIndex)'), self.toc_clicked)
|
||||||
self.connect(self.reference, SIGNAL('goto(PyQt_PyObject)'), self.goto)
|
self.connect(self.reference, SIGNAL('goto(PyQt_PyObject)'), self.goto)
|
||||||
|
|
||||||
|
|
||||||
self.bookmarks_menu = QMenu()
|
self.bookmarks_menu = QMenu()
|
||||||
self.action_bookmark.setMenu(self.bookmarks_menu)
|
self.action_bookmark.setMenu(self.bookmarks_menu)
|
||||||
self.set_bookmarks([])
|
self.set_bookmarks([])
|
||||||
|
|
||||||
if pathtoebook is not None:
|
if pathtoebook is not None:
|
||||||
f = functools.partial(self.load_ebook, pathtoebook)
|
f = functools.partial(self.load_ebook, pathtoebook)
|
||||||
QTimer.singleShot(50, f)
|
QTimer.singleShot(50, f)
|
||||||
@ -277,7 +276,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
self.tool_bar2.setContextMenuPolicy(Qt.PreventContextMenu)
|
self.tool_bar2.setContextMenuPolicy(Qt.PreventContextMenu)
|
||||||
self.tool_bar.widgetForAction(self.action_bookmark).setPopupMode(QToolButton.MenuButtonPopup)
|
self.tool_bar.widgetForAction(self.action_bookmark).setPopupMode(QToolButton.MenuButtonPopup)
|
||||||
self.action_full_screen.setCheckable(True)
|
self.action_full_screen.setCheckable(True)
|
||||||
|
|
||||||
self.print_menu = QMenu()
|
self.print_menu = QMenu()
|
||||||
self.print_menu.addAction(QIcon(':/images/print-preview.svg'), _('Print Preview'))
|
self.print_menu.addAction(QIcon(':/images/print-preview.svg'), _('Print Preview'))
|
||||||
self.action_print.setMenu(self.print_menu)
|
self.action_print.setMenu(self.print_menu)
|
||||||
@ -293,18 +292,18 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
self.showNormal()
|
self.showNormal()
|
||||||
else:
|
else:
|
||||||
self.showFullScreen()
|
self.showFullScreen()
|
||||||
|
|
||||||
def goto(self, ref):
|
def goto(self, ref):
|
||||||
if ref:
|
if ref:
|
||||||
tokens = ref.split('.')
|
tokens = ref.split('.')
|
||||||
if len(tokens) > 1:
|
if len(tokens) > 1:
|
||||||
spine_index = int(tokens[0]) -1
|
spine_index = int(tokens[0]) -1
|
||||||
if spine_index == self.current_index:
|
if spine_index == self.current_index:
|
||||||
self.view.goto(ref)
|
self.view.goto(ref)
|
||||||
else:
|
else:
|
||||||
self.pending_reference = ref
|
self.pending_reference = ref
|
||||||
self.load_path(self.iterator.spine[spine_index])
|
self.load_path(self.iterator.spine[spine_index])
|
||||||
|
|
||||||
def goto_bookmark(self, bm):
|
def goto_bookmark(self, bm):
|
||||||
m = bm[1].split('#')
|
m = bm[1].split('#')
|
||||||
if len(m) > 1:
|
if len(m) > 1:
|
||||||
@ -314,39 +313,39 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
else:
|
else:
|
||||||
self.pending_bookmark = bm
|
self.pending_bookmark = bm
|
||||||
self.load_path(self.iterator.spine[spine_index])
|
self.load_path(self.iterator.spine[spine_index])
|
||||||
|
|
||||||
def toc_clicked(self, index):
|
def toc_clicked(self, index):
|
||||||
item = self.toc_model.itemFromIndex(index)
|
item = self.toc_model.itemFromIndex(index)
|
||||||
url = QUrl.fromLocalFile(item.abspath)
|
url = QUrl.fromLocalFile(item.abspath)
|
||||||
if item.fragment:
|
if item.fragment:
|
||||||
url.setFragment(item.fragment)
|
url.setFragment(item.fragment)
|
||||||
self.link_clicked(url)
|
self.link_clicked(url)
|
||||||
|
|
||||||
def selection_changed(self, selected_text):
|
def selection_changed(self, selected_text):
|
||||||
self.selected_text = selected_text.strip()
|
self.selected_text = selected_text.strip()
|
||||||
self.action_copy.setEnabled(bool(self.selected_text))
|
self.action_copy.setEnabled(bool(self.selected_text))
|
||||||
|
|
||||||
def copy(self, x):
|
def copy(self, x):
|
||||||
if self.selected_text:
|
if self.selected_text:
|
||||||
QApplication.clipboard().setText(self.selected_text)
|
QApplication.clipboard().setText(self.selected_text)
|
||||||
|
|
||||||
def back(self, x):
|
def back(self, x):
|
||||||
pos = self.history.back(self.pos.value())
|
pos = self.history.back(self.pos.value())
|
||||||
if pos is not None:
|
if pos is not None:
|
||||||
self.goto_page(pos)
|
self.goto_page(pos)
|
||||||
|
|
||||||
|
|
||||||
def forward(self, x):
|
def forward(self, x):
|
||||||
pos = self.history.forward()
|
pos = self.history.forward()
|
||||||
if pos is not None:
|
if pos is not None:
|
||||||
self.goto_page(pos)
|
self.goto_page(pos)
|
||||||
|
|
||||||
def goto_start(self):
|
def goto_start(self):
|
||||||
self.goto_page(1)
|
self.goto_page(1)
|
||||||
|
|
||||||
def goto_end(self):
|
def goto_end(self):
|
||||||
self.goto_page(self.pos.maximum())
|
self.goto_page(self.pos.maximum())
|
||||||
|
|
||||||
def goto_page(self, new_page):
|
def goto_page(self, new_page):
|
||||||
if self.current_page is not None:
|
if self.current_page is not None:
|
||||||
for page in self.iterator.spine:
|
for page in self.iterator.spine:
|
||||||
@ -359,7 +358,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
self.view.scroll_to(frac)
|
self.view.scroll_to(frac)
|
||||||
else:
|
else:
|
||||||
self.load_path(page, pos=frac)
|
self.load_path(page, pos=frac)
|
||||||
|
|
||||||
def open_ebook(self, checked):
|
def open_ebook(self, checked):
|
||||||
files = choose_files(self, 'ebook viewer open dialog',
|
files = choose_files(self, 'ebook viewer open dialog',
|
||||||
_('Choose ebook'),
|
_('Choose ebook'),
|
||||||
@ -367,19 +366,19 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
select_only_single_file=True)
|
select_only_single_file=True)
|
||||||
if files:
|
if files:
|
||||||
self.load_ebook(files[0])
|
self.load_ebook(files[0])
|
||||||
|
|
||||||
def font_size_larger(self, checked):
|
def font_size_larger(self, checked):
|
||||||
frac = self.view.magnify_fonts()
|
frac = self.view.magnify_fonts()
|
||||||
self.action_font_size_larger.setEnabled(self.view.multiplier() < 3)
|
self.action_font_size_larger.setEnabled(self.view.multiplier() < 3)
|
||||||
self.action_font_size_smaller.setEnabled(self.view.multiplier() > 0.2)
|
self.action_font_size_smaller.setEnabled(self.view.multiplier() > 0.2)
|
||||||
self.set_page_number(frac)
|
self.set_page_number(frac)
|
||||||
|
|
||||||
def font_size_smaller(self, checked):
|
def font_size_smaller(self, checked):
|
||||||
frac = self.view.shrink_fonts()
|
frac = self.view.shrink_fonts()
|
||||||
self.action_font_size_larger.setEnabled(self.view.multiplier() < 3)
|
self.action_font_size_larger.setEnabled(self.view.multiplier() < 3)
|
||||||
self.action_font_size_smaller.setEnabled(self.view.multiplier() > 0.2)
|
self.action_font_size_smaller.setEnabled(self.view.multiplier() > 0.2)
|
||||||
self.set_page_number(frac)
|
self.set_page_number(frac)
|
||||||
|
|
||||||
def bookmark(self, *args):
|
def bookmark(self, *args):
|
||||||
title, ok = QInputDialog.getText(self, _('Add bookmark'), _('Enter title for bookmark:'))
|
title, ok = QInputDialog.getText(self, _('Add bookmark'), _('Enter title for bookmark:'))
|
||||||
title = unicode(title).strip()
|
title = unicode(title).strip()
|
||||||
@ -388,8 +387,8 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
bookmark = '%d#%s'%(self.current_index, pos)
|
bookmark = '%d#%s'%(self.current_index, pos)
|
||||||
self.iterator.add_bookmark((title, bookmark))
|
self.iterator.add_bookmark((title, bookmark))
|
||||||
self.set_bookmarks(self.iterator.bookmarks)
|
self.set_bookmarks(self.iterator.bookmarks)
|
||||||
|
|
||||||
|
|
||||||
def find(self, text, refinement, repeat=False):
|
def find(self, text, refinement, repeat=False):
|
||||||
if not text:
|
if not text:
|
||||||
return
|
return
|
||||||
@ -401,18 +400,18 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
if self.current_index > 0:
|
if self.current_index > 0:
|
||||||
index = self.iterator.search(text, 0)
|
index = self.iterator.search(text, 0)
|
||||||
if index is None:
|
if index is None:
|
||||||
info_dialog(self, _('No matches found'),
|
info_dialog(self, _('No matches found'),
|
||||||
_('No matches found for: %s')%text).exec_()
|
_('No matches found for: %s')%text).exec_()
|
||||||
return
|
return
|
||||||
return
|
return
|
||||||
self.pending_search = text
|
self.pending_search = text
|
||||||
self.load_path(self.iterator.spine[index])
|
self.load_path(self.iterator.spine[index])
|
||||||
|
|
||||||
def do_search(self, text):
|
def do_search(self, text):
|
||||||
self.pending_search = None
|
self.pending_search = None
|
||||||
if self.view.search(text):
|
if self.view.search(text):
|
||||||
self.scrolled(self.view.scroll_fraction)
|
self.scrolled(self.view.scroll_fraction)
|
||||||
|
|
||||||
def keyPressEvent(self, event):
|
def keyPressEvent(self, event):
|
||||||
if event.key() == Qt.Key_F3:
|
if event.key() == Qt.Key_F3:
|
||||||
text = unicode(self.search.text())
|
text = unicode(self.search.text())
|
||||||
@ -421,10 +420,10 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
self.search.setFocus(Qt.OtherFocusReason)
|
self.search.setFocus(Qt.OtherFocusReason)
|
||||||
else:
|
else:
|
||||||
return MainWindow.keyPressEvent(self, event)
|
return MainWindow.keyPressEvent(self, event)
|
||||||
|
|
||||||
def internal_link_clicked(self, frac):
|
def internal_link_clicked(self, frac):
|
||||||
self.history.add(self.pos.value())
|
self.history.add(self.pos.value())
|
||||||
|
|
||||||
def link_clicked(self, url):
|
def link_clicked(self, url):
|
||||||
path = os.path.abspath(unicode(url.toLocalFile()))
|
path = os.path.abspath(unicode(url.toLocalFile()))
|
||||||
frag = None
|
frag = None
|
||||||
@ -440,10 +439,10 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
self.view.scroll_to(frag)
|
self.view.scroll_to(frag)
|
||||||
else:
|
else:
|
||||||
QDesktopServices.openUrl(url)
|
QDesktopServices.openUrl(url)
|
||||||
|
|
||||||
def load_started(self):
|
def load_started(self):
|
||||||
self.open_progress_indicator(_('Loading flow...'))
|
self.open_progress_indicator(_('Loading flow...'))
|
||||||
|
|
||||||
def load_finished(self, ok):
|
def load_finished(self, ok):
|
||||||
self.close_progress_indicator()
|
self.close_progress_indicator()
|
||||||
path = self.view.path()
|
path = self.view.path()
|
||||||
@ -467,11 +466,11 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
self.goto_bookmark(self.pending_bookmark)
|
self.goto_bookmark(self.pending_bookmark)
|
||||||
self.pending_bookmark = None
|
self.pending_bookmark = None
|
||||||
return self.current_index
|
return self.current_index
|
||||||
|
|
||||||
def load_path(self, path, pos=0.0):
|
def load_path(self, path, pos=0.0):
|
||||||
self.open_progress_indicator(_('Laying out %s')%self.current_title)
|
self.open_progress_indicator(_('Laying out %s')%self.current_title)
|
||||||
self.view.load_path(path, pos=pos)
|
self.view.load_path(path, pos=pos)
|
||||||
|
|
||||||
def viewport_resized(self, frac):
|
def viewport_resized(self, frac):
|
||||||
new_page = self.pos.value()
|
new_page = self.pos.value()
|
||||||
if self.current_page is not None:
|
if self.current_page is not None:
|
||||||
@ -482,20 +481,20 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
self.view.scroll_to(frac, notify=False)
|
self.view.scroll_to(frac, notify=False)
|
||||||
else:
|
else:
|
||||||
self.set_page_number(frac)
|
self.set_page_number(frac)
|
||||||
|
|
||||||
def close_progress_indicator(self):
|
def close_progress_indicator(self):
|
||||||
self.pi.stop()
|
self.pi.stop()
|
||||||
for o in ('tool_bar', 'tool_bar2', 'view', 'horizontal_scrollbar', 'vertical_scrollbar'):
|
for o in ('tool_bar', 'tool_bar2', 'view', 'horizontal_scrollbar', 'vertical_scrollbar'):
|
||||||
getattr(self, o).setEnabled(True)
|
getattr(self, o).setEnabled(True)
|
||||||
self.unsetCursor()
|
self.unsetCursor()
|
||||||
self.view.setFocus(Qt.PopupFocusReason)
|
self.view.setFocus(Qt.PopupFocusReason)
|
||||||
|
|
||||||
def open_progress_indicator(self, msg=''):
|
def open_progress_indicator(self, msg=''):
|
||||||
self.pi.start(msg)
|
self.pi.start(msg)
|
||||||
for o in ('tool_bar', 'tool_bar2', 'view', 'horizontal_scrollbar', 'vertical_scrollbar'):
|
for o in ('tool_bar', 'tool_bar2', 'view', 'horizontal_scrollbar', 'vertical_scrollbar'):
|
||||||
getattr(self, o).setEnabled(False)
|
getattr(self, o).setEnabled(False)
|
||||||
self.setCursor(Qt.BusyCursor)
|
self.setCursor(Qt.BusyCursor)
|
||||||
|
|
||||||
def set_bookmarks(self, bookmarks):
|
def set_bookmarks(self, bookmarks):
|
||||||
self.bookmarks_menu.clear()
|
self.bookmarks_menu.clear()
|
||||||
self.bookmarks_menu.addAction(_("Manage Bookmarks"), self.manage_bookmarks)
|
self.bookmarks_menu.addAction(_("Manage Bookmarks"), self.manage_bookmarks)
|
||||||
@ -507,19 +506,19 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
else:
|
else:
|
||||||
self.bookmarks_menu.addAction(bm[0], partial(self.goto_bookmark, bm))
|
self.bookmarks_menu.addAction(bm[0], partial(self.goto_bookmark, bm))
|
||||||
return current_page
|
return current_page
|
||||||
|
|
||||||
def manage_bookmarks(self):
|
def manage_bookmarks(self):
|
||||||
bmm = BookmarkManager(self, self.iterator.bookmarks)
|
bmm = BookmarkManager(self, self.iterator.bookmarks)
|
||||||
if bmm.exec_() != BookmarkManager.Accepted:
|
if bmm.exec_() != BookmarkManager.Accepted:
|
||||||
return
|
return
|
||||||
|
|
||||||
bookmarks = bmm.get_bookmarks()
|
bookmarks = bmm.get_bookmarks()
|
||||||
|
|
||||||
if bookmarks != self.iterator.bookmarks:
|
if bookmarks != self.iterator.bookmarks:
|
||||||
self.iterator.set_bookmarks(bookmarks)
|
self.iterator.set_bookmarks(bookmarks)
|
||||||
self.iterator.save_bookmarks()
|
self.iterator.save_bookmarks()
|
||||||
self.set_bookmarks(bookmarks)
|
self.set_bookmarks(bookmarks)
|
||||||
|
|
||||||
def save_current_position(self):
|
def save_current_position(self):
|
||||||
try:
|
try:
|
||||||
pos = self.view.bookmark()
|
pos = self.view.bookmark()
|
||||||
@ -527,7 +526,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
self.iterator.add_bookmark(('calibre_current_page_bookmark', bookmark))
|
self.iterator.add_bookmark(('calibre_current_page_bookmark', bookmark))
|
||||||
except:
|
except:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
def load_ebook(self, pathtoebook):
|
def load_ebook(self, pathtoebook):
|
||||||
if self.iterator is not None:
|
if self.iterator is not None:
|
||||||
self.save_current_position()
|
self.save_current_position()
|
||||||
@ -543,7 +542,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
if isinstance(worker.exception, DRMError):
|
if isinstance(worker.exception, DRMError):
|
||||||
error_dialog(self, _('DRM Error'), _('<p>This book is protected by <a href="%s">DRM</a>')%'http://wiki.mobileread.com/wiki/DRM').exec_()
|
error_dialog(self, _('DRM Error'), _('<p>This book is protected by <a href="%s">DRM</a>')%'http://wiki.mobileread.com/wiki/DRM').exec_()
|
||||||
else:
|
else:
|
||||||
ConversionErrorDialog(self, _('Could not open ebook'),
|
ConversionErrorDialog(self, _('Could not open ebook'),
|
||||||
_('<b>%s</b><br/><p>%s</p>')%(worker.exception, worker.traceback.replace('\n', '<br>')), show=True)
|
_('<b>%s</b><br/><p>%s</p>')%(worker.exception, worker.traceback.replace('\n', '<br>')), show=True)
|
||||||
self.close_progress_indicator()
|
self.close_progress_indicator()
|
||||||
else:
|
else:
|
||||||
@ -571,37 +570,37 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
self.goto_bookmark(previous)
|
self.goto_bookmark(previous)
|
||||||
else:
|
else:
|
||||||
self.next_document()
|
self.next_document()
|
||||||
|
|
||||||
def set_vscrollbar_value(self, pagenum):
|
def set_vscrollbar_value(self, pagenum):
|
||||||
self.vertical_scrollbar.blockSignals(True)
|
self.vertical_scrollbar.blockSignals(True)
|
||||||
self.vertical_scrollbar.setValue(int(pagenum*100))
|
self.vertical_scrollbar.setValue(int(pagenum*100))
|
||||||
self.vertical_scrollbar.blockSignals(False)
|
self.vertical_scrollbar.blockSignals(False)
|
||||||
|
|
||||||
def set_page_number(self, frac):
|
def set_page_number(self, frac):
|
||||||
if getattr(self, 'current_page', None) is not None:
|
if getattr(self, 'current_page', None) is not None:
|
||||||
page = self.current_page.start_page + frac*float(self.current_page.pages-1)
|
page = self.current_page.start_page + frac*float(self.current_page.pages-1)
|
||||||
self.pos.set_value(page)
|
self.pos.set_value(page)
|
||||||
self.set_vscrollbar_value(page)
|
self.set_vscrollbar_value(page)
|
||||||
|
|
||||||
def scrolled(self, frac):
|
def scrolled(self, frac):
|
||||||
self.set_page_number(frac)
|
self.set_page_number(frac)
|
||||||
|
|
||||||
def next_document(self):
|
def next_document(self):
|
||||||
if self.current_index < len(self.iterator.spine) - 1:
|
if self.current_index < len(self.iterator.spine) - 1:
|
||||||
self.load_path(self.iterator.spine[self.current_index+1])
|
self.load_path(self.iterator.spine[self.current_index+1])
|
||||||
|
|
||||||
def previous_document(self):
|
def previous_document(self):
|
||||||
if self.current_index > 0:
|
if self.current_index > 0:
|
||||||
self.load_path(self.iterator.spine[self.current_index-1], pos=1.0)
|
self.load_path(self.iterator.spine[self.current_index-1], pos=1.0)
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def __exit__(self, *args):
|
def __exit__(self, *args):
|
||||||
if self.iterator is not None:
|
if self.iterator is not None:
|
||||||
self.save_current_position()
|
self.save_current_position()
|
||||||
self.iterator.__exit__(*args)
|
self.iterator.__exit__(*args)
|
||||||
|
|
||||||
|
|
||||||
def config(defaults=None):
|
def config(defaults=None):
|
||||||
desc = _('Options to control the ebook viewer')
|
desc = _('Options to control the ebook viewer')
|
||||||
@ -609,8 +608,8 @@ def config(defaults=None):
|
|||||||
c = Config('viewer', desc)
|
c = Config('viewer', desc)
|
||||||
else:
|
else:
|
||||||
c = StringConfig(defaults, desc)
|
c = StringConfig(defaults, desc)
|
||||||
|
|
||||||
c.add_opt('raise_window', ['--raise-window'], default=False,
|
c.add_opt('raise_window', ['--raise-window'], default=False,
|
||||||
help=_('If specified, viewer window will try to come to the '
|
help=_('If specified, viewer window will try to come to the '
|
||||||
'front when started.'))
|
'front when started.'))
|
||||||
return c
|
return c
|
||||||
@ -620,7 +619,7 @@ def option_parser():
|
|||||||
return c.option_parser(usage=_('''\
|
return c.option_parser(usage=_('''\
|
||||||
%prog [options] file
|
%prog [options] file
|
||||||
|
|
||||||
View an ebook.
|
View an ebook.
|
||||||
'''))
|
'''))
|
||||||
|
|
||||||
|
|
||||||
@ -639,7 +638,7 @@ def main(args=sys.argv):
|
|||||||
if opts.raise_window:
|
if opts.raise_window:
|
||||||
main.raise_()
|
main.raise_()
|
||||||
with main:
|
with main:
|
||||||
return app.exec_()
|
return app.exec_()
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -37,7 +37,7 @@ recipe_modules = ['recipe_' + r for r in (
|
|||||||
'new_york_review_of_books_no_sub', 'politico', 'adventuregamers',
|
'new_york_review_of_books_no_sub', 'politico', 'adventuregamers',
|
||||||
'mondedurable', 'instapaper', 'dnevnik_cro', 'vecernji_list',
|
'mondedurable', 'instapaper', 'dnevnik_cro', 'vecernji_list',
|
||||||
'nacional_cro', '24sata', 'dnevni_avaz', 'glas_srpske', '24sata_rs',
|
'nacional_cro', '24sata', 'dnevni_avaz', 'glas_srpske', '24sata_rs',
|
||||||
'krstarica', 'krstarica_en', 'tanjug',
|
'krstarica', 'krstarica_en', 'tanjug', 'laprensa_ni',
|
||||||
)]
|
)]
|
||||||
|
|
||||||
import re, imp, inspect, time, os
|
import re, imp, inspect, time, os
|
||||||
|
96
src/calibre/web/feeds/recipes/recipe_laprensa_ni.py
Normal file
96
src/calibre/web/feeds/recipes/recipe_laprensa_ni.py
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2009, Darko Miletic <darko.miletic at gmail.com>'
|
||||||
|
'''
|
||||||
|
laprensa.com.ni
|
||||||
|
'''
|
||||||
|
|
||||||
|
import locale
|
||||||
|
import time
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class LaPrensa_ni(BasicNewsRecipe):
|
||||||
|
title = 'La Prensa - Nicaragua'
|
||||||
|
__author__ = 'Darko Miletic'
|
||||||
|
description = 'LA PRENSA - EL Diario de los Nicaraguenses'
|
||||||
|
publisher = 'La Prensa'
|
||||||
|
category = 'Nicaragua, nicaragua, la prensa, La Prensa, prensa, Prensa, diario, Diario, periodico, noticias, internacional, economia, dinero, opinion, ultimas noticias, deportes, politica, managua, Managua, ultima hora, daily, newspaper, news, breaking news, urgente, tecnologia, tiempo, weather, buscador, magazine, Magazine, nosotras, Nosotras, journalism, clasificados, avisos, classified, ads, media, publicidad, arroba, arroba de oro'
|
||||||
|
oldest_article = 1
|
||||||
|
max_articles_per_feed = 100
|
||||||
|
no_stylesheets = True
|
||||||
|
use_embedded_content = False
|
||||||
|
encoding = 'cp1252'
|
||||||
|
remove_javascript = True
|
||||||
|
language = _('Spanish')
|
||||||
|
|
||||||
|
#Locale setting to get appropriate date/month values in Spanish
|
||||||
|
try:
|
||||||
|
#Windows seting for locale
|
||||||
|
locale.setlocale(locale.LC_TIME,'Spanish_Nicaragua')
|
||||||
|
except locale.Error:
|
||||||
|
#Linux setting for locale -- choose one appropriate for your distribution
|
||||||
|
try:
|
||||||
|
locale.setlocale(locale.LC_TIME,'es_NI')
|
||||||
|
except locale.Error:
|
||||||
|
try:
|
||||||
|
locale.setlocale(locale.LC_TIME,'es_ES')
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
current_index = time.strftime("http://www.laprensa.com.ni/archivo/%Y/%B/%d/noticias/")
|
||||||
|
|
||||||
|
html2lrf_options = [
|
||||||
|
'--comment', description
|
||||||
|
, '--category', category
|
||||||
|
, '--publisher', publisher
|
||||||
|
, '--ignore-tables'
|
||||||
|
]
|
||||||
|
|
||||||
|
html2epub_options = 'publisher="' + publisher + '"\ncomments="' + description + '"\ntags="' + category + '"\nlinearize_tables=True'
|
||||||
|
|
||||||
|
feeds = [(u'Portada', current_index + 'portada/')]
|
||||||
|
|
||||||
|
def print_version(self, url):
|
||||||
|
return url.replace('.shtml','_print.shtml')
|
||||||
|
|
||||||
|
def preprocess_html(self, soup):
|
||||||
|
del soup.body['onload']
|
||||||
|
mtag = '<meta http-equiv="Content-Language" content="es-NI"/>'
|
||||||
|
soup.head.insert(0,mtag)
|
||||||
|
atag = soup.find('span',attrs={'class':'mas_noticias'})
|
||||||
|
if atag:
|
||||||
|
atag.extract()
|
||||||
|
btag = soup.find('a',attrs={'href':'/archivo'})
|
||||||
|
if btag:
|
||||||
|
btag.extract()
|
||||||
|
for item in soup.findAll(style=True):
|
||||||
|
del item['style']
|
||||||
|
return soup
|
||||||
|
|
||||||
|
def parse_index(self):
|
||||||
|
totalfeeds = []
|
||||||
|
lfeeds = self.get_feeds()
|
||||||
|
for feedobj in lfeeds:
|
||||||
|
feedtitle, feedurl = feedobj
|
||||||
|
self.report_progress(0, _('Fetching feed')+' %s...'%(feedtitle if feedtitle else feedurl))
|
||||||
|
articles = []
|
||||||
|
soup = self.index_to_soup(feedurl)
|
||||||
|
for item in soup.findAll('a', attrs={'class':['titular','titulonotamed']}):
|
||||||
|
description = ''
|
||||||
|
url = feedurl + item['href']
|
||||||
|
title = self.tag_to_string(item)
|
||||||
|
date = time.strftime(self.timefmt)
|
||||||
|
articles.append({
|
||||||
|
'title' :title
|
||||||
|
,'date' :date
|
||||||
|
,'url' :url
|
||||||
|
,'description':description
|
||||||
|
})
|
||||||
|
totalfeeds.append((feedtitle, articles))
|
||||||
|
return totalfeeds
|
||||||
|
|
||||||
|
def cleanup(self):
|
||||||
|
#Going back to the default locale
|
||||||
|
locale.setlocale(locale.LC_TIME,'')
|
@ -26,7 +26,8 @@ def initview(request):
|
|||||||
5. The feeds for the site (ids)
|
5. The feeds for the site (ids)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
site_id, cachekey = fjlib.getcurrentsite(request.META['HTTP_HOST'], \
|
site_id, cachekey = fjlib.getcurrentsite(request.META.get('HTTP_HOST',
|
||||||
|
'planet.calibre-ebook.com'), \
|
||||||
request.META.get('REQUEST_URI', request.META.get('PATH_INFO', '/')), \
|
request.META.get('REQUEST_URI', request.META.get('PATH_INFO', '/')), \
|
||||||
request.META['QUERY_STRING'])
|
request.META['QUERY_STRING'])
|
||||||
response = fjcache.cache_get(site_id, cachekey)
|
response = fjcache.cache_get(site_id, cachekey)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
ssh divok "cd /usr/local/calibre && bzr pull"
|
ssh divok "cd /usr/local/calibre && bzr up"
|
||||||
ssh divok /etc/init.d/apache2 graceful
|
ssh divok /etc/init.d/apache2 graceful
|
||||||
|
@ -52,7 +52,7 @@
|
|||||||
<img
|
<img
|
||||||
src="{{ MEDIA_URL }}/img/faces/{{ item.subscriber.shortname}}.png" alt="" />
|
src="{{ MEDIA_URL }}/img/faces/{{ item.subscriber.shortname}}.png" alt="" />
|
||||||
<div class="url">
|
<div class="url">
|
||||||
{{ item.feed.title|safe }}
|
{{ item.feed.name|safe }}
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -667,9 +667,16 @@ class stage3(OptionlessCommand):
|
|||||||
def misc(cls):
|
def misc(cls):
|
||||||
check_call('ssh divok rm -f %s/calibre-\*.tar.gz'%DOWNLOADS, shell=True)
|
check_call('ssh divok rm -f %s/calibre-\*.tar.gz'%DOWNLOADS, shell=True)
|
||||||
check_call('scp dist/calibre-*.tar.gz divok:%s/'%DOWNLOADS, shell=True)
|
check_call('scp dist/calibre-*.tar.gz divok:%s/'%DOWNLOADS, shell=True)
|
||||||
|
check_call('gpg --armor --detach-sign dist/calibre-*.tar.gz',
|
||||||
|
shell=True)
|
||||||
|
check_call('scp dist/calibre-*.tar.gz.asc divok:%s/signatures/'%DOWNLOADS,
|
||||||
|
shell=True)
|
||||||
check_call('''rm -rf dist/* build/*''', shell=True)
|
check_call('''rm -rf dist/* build/*''', shell=True)
|
||||||
check_call('ssh divok bzr update /var/www/calibre.kovidgoyal.net/calibre/',
|
check_call('ssh divok bzr update /var/www/calibre.kovidgoyal.net/calibre/',
|
||||||
shell=True)
|
shell=True)
|
||||||
|
check_call('ssh divok bzr update /usr/local/calibre',
|
||||||
|
shell=True)
|
||||||
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
OptionlessCommand.run(self)
|
OptionlessCommand.run(self)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user