mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Sync to trunk.
This commit is contained in:
commit
ae6a168551
43
recipes/ivanamilakovic.recipe
Normal file
43
recipes/ivanamilakovic.recipe
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
|
||||||
|
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2012, Darko Miletic <darko.miletic at gmail.com>'
|
||||||
|
'''
|
||||||
|
ivanamilakovic.blogspot.com
|
||||||
|
'''
|
||||||
|
|
||||||
|
import re
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class IvanaMilakovic(BasicNewsRecipe):
|
||||||
|
title = u'Ivana Milaković'
|
||||||
|
__author__ = 'Darko Miletic'
|
||||||
|
description = u'Hronika mačijeg škrabala - priče, inspiracija, knjige, pisanje, prevodi...'
|
||||||
|
oldest_article = 80
|
||||||
|
max_articles_per_feed = 100
|
||||||
|
language = 'sr'
|
||||||
|
encoding = 'utf-8'
|
||||||
|
no_stylesheets = True
|
||||||
|
use_embedded_content = True
|
||||||
|
publication_type = 'blog'
|
||||||
|
extra_css = """
|
||||||
|
@font-face {font-family: "sans1";src:url(res:///opt/sony/ebook/FONT/tt0003m_.ttf)}
|
||||||
|
body{font-family: Arial,Tahoma,Helvetica,FreeSans,sans1,sans-serif}
|
||||||
|
img{margin-bottom: 0.8em; border: 1px solid #333333; padding: 4px }
|
||||||
|
"""
|
||||||
|
|
||||||
|
conversion_options = {
|
||||||
|
'comment' : description
|
||||||
|
, 'tags' : 'knjige, blog, srbija, sf'
|
||||||
|
, 'publisher': 'Ivana Milakovic'
|
||||||
|
, 'language' : language
|
||||||
|
}
|
||||||
|
|
||||||
|
preprocess_regexps = [(re.compile(u'\u0110'), lambda match: u'\u00D0')]
|
||||||
|
|
||||||
|
feeds = [(u'Posts', u'http://ivanamilakovic.blogspot.com/feeds/posts/default')]
|
||||||
|
|
||||||
|
def preprocess_html(self, soup):
|
||||||
|
for item in soup.findAll(style=True):
|
||||||
|
del item['style']
|
||||||
|
return self.adeify_images(soup)
|
42
recipes/klubknjige.recipe
Normal file
42
recipes/klubknjige.recipe
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2012, Darko Miletic <darko.miletic at gmail.com>'
|
||||||
|
'''
|
||||||
|
klub-knjige.blogspot.com
|
||||||
|
'''
|
||||||
|
|
||||||
|
import re
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class KlubKnjige(BasicNewsRecipe):
|
||||||
|
title = 'Klub knjige'
|
||||||
|
__author__ = 'Darko Miletic'
|
||||||
|
description = 'literarni blog'
|
||||||
|
oldest_article = 30
|
||||||
|
max_articles_per_feed = 100
|
||||||
|
language = 'sr'
|
||||||
|
encoding = 'utf-8'
|
||||||
|
no_stylesheets = True
|
||||||
|
use_embedded_content = True
|
||||||
|
publication_type = 'blog'
|
||||||
|
extra_css = """
|
||||||
|
@font-face {font-family: "sans1";src:url(res:///opt/sony/ebook/FONT/tt0003m_.ttf)}
|
||||||
|
body{font-family: Arial,Tahoma,Helvetica,FreeSans,sans1,sans-serif}
|
||||||
|
img{margin-bottom: 0.8em; border: 1px solid #333333; padding: 4px }
|
||||||
|
"""
|
||||||
|
|
||||||
|
conversion_options = {
|
||||||
|
'comment' : description
|
||||||
|
, 'tags' : 'knjige, blog, srbija, sf'
|
||||||
|
, 'publisher': 'Klub Knjige'
|
||||||
|
, 'language' : language
|
||||||
|
}
|
||||||
|
|
||||||
|
preprocess_regexps = [(re.compile(u'\u0110'), lambda match: u'\u00D0')]
|
||||||
|
|
||||||
|
feeds = [(u'Posts', u'http://klub-knjige.blogspot.com/feeds/posts/default')]
|
||||||
|
|
||||||
|
def preprocess_html(self, soup):
|
||||||
|
for item in soup.findAll(style=True):
|
||||||
|
del item['style']
|
||||||
|
return self.adeify_images(soup)
|
@ -3,7 +3,6 @@ __copyright__ = '2011'
|
|||||||
'''
|
'''
|
||||||
lemonde.fr
|
lemonde.fr
|
||||||
'''
|
'''
|
||||||
import re
|
|
||||||
from calibre.web.feeds.recipes import BasicNewsRecipe
|
from calibre.web.feeds.recipes import BasicNewsRecipe
|
||||||
|
|
||||||
class LeMonde(BasicNewsRecipe):
|
class LeMonde(BasicNewsRecipe):
|
||||||
@ -41,77 +40,8 @@ class LeMonde(BasicNewsRecipe):
|
|||||||
|
|
||||||
remove_empty_feeds = True
|
remove_empty_feeds = True
|
||||||
|
|
||||||
filterDuplicates = True
|
auto_cleanup = True
|
||||||
|
|
||||||
def preprocess_html(self, soup):
|
|
||||||
for alink in soup.findAll('a'):
|
|
||||||
if alink.string is not None:
|
|
||||||
tstr = alink.string
|
|
||||||
alink.replaceWith(tstr)
|
|
||||||
return self.adeify_images(soup)
|
|
||||||
|
|
||||||
preprocess_regexps = [
|
|
||||||
(re.compile(r'([0-9])%'), lambda m: m.group(1) + ' %'),
|
|
||||||
(re.compile(r'([0-9])([0-9])([0-9]) ([0-9])([0-9])([0-9])'), lambda m: m.group(1) + m.group(2) + m.group(3) + ' ' + m.group(4) + m.group(5) + m.group(6)),
|
|
||||||
(re.compile(r'([0-9]) ([0-9])([0-9])([0-9])'), lambda m: m.group(1) + ' ' + m.group(2) + m.group(3) + m.group(4)),
|
|
||||||
(re.compile(r'<span>'), lambda match: ' <span>'),
|
|
||||||
(re.compile(r'\("'), lambda match: '(« '),
|
|
||||||
(re.compile(r'"\)'), lambda match: ' »)'),
|
|
||||||
(re.compile(r'“'), lambda match: '(« '),
|
|
||||||
(re.compile(r'”'), lambda match: ' »)'),
|
|
||||||
(re.compile(r'>\''), lambda match: '>‘'),
|
|
||||||
(re.compile(r' \''), lambda match: ' ‘'),
|
|
||||||
(re.compile(r'\''), lambda match: '’'),
|
|
||||||
(re.compile(r'"<em>'), lambda match: '<em>« '),
|
|
||||||
(re.compile(r'"<em>"</em><em>'), lambda match: '<em>« '),
|
|
||||||
(re.compile(r'"<a href='), lambda match: '« <a href='),
|
|
||||||
(re.compile(r'</em>"'), lambda match: ' »</em>'),
|
|
||||||
(re.compile(r'</a>"'), lambda match: ' »</a>'),
|
|
||||||
(re.compile(r'"</'), lambda match: ' »</'),
|
|
||||||
(re.compile(r'>"'), lambda match: '>« '),
|
|
||||||
(re.compile(r'"<'), lambda match: ' »<'),
|
|
||||||
(re.compile(r'’"'), lambda match: '’« '),
|
|
||||||
(re.compile(r' "'), lambda match: ' « '),
|
|
||||||
(re.compile(r'" '), lambda match: ' » '),
|
|
||||||
(re.compile(r'"\.'), lambda match: ' ».'),
|
|
||||||
(re.compile(r'",'), lambda match: ' »,'),
|
|
||||||
(re.compile(r'"\?'), lambda match: ' »?'),
|
|
||||||
(re.compile(r'":'), lambda match: ' »:'),
|
|
||||||
(re.compile(r'";'), lambda match: ' »;'),
|
|
||||||
(re.compile(r'"\!'), lambda match: ' »!'),
|
|
||||||
(re.compile(r' :'), lambda match: ' :'),
|
|
||||||
(re.compile(r' ;'), lambda match: ' ;'),
|
|
||||||
(re.compile(r' \?'), lambda match: ' ?'),
|
|
||||||
(re.compile(r' \!'), lambda match: ' !'),
|
|
||||||
(re.compile(r'\s»'), lambda match: ' »'),
|
|
||||||
(re.compile(r'«\s'), lambda match: '« '),
|
|
||||||
(re.compile(r' %'), lambda match: ' %'),
|
|
||||||
(re.compile(r'\.jpg » border='), lambda match: '.jpg'),
|
|
||||||
(re.compile(r'\.png » border='), lambda match: '.png'),
|
|
||||||
(re.compile(r' – '), lambda match: ' – '),
|
|
||||||
(re.compile(r' – '), lambda match: ' – '),
|
|
||||||
(re.compile(r' - '), lambda match: ' – '),
|
|
||||||
(re.compile(r' -,'), lambda match: ' –,'),
|
|
||||||
(re.compile(r'»:'), lambda match: '» :'),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
keep_only_tags = [
|
|
||||||
dict(name='div', attrs={'class':['contenu']})
|
|
||||||
]
|
|
||||||
remove_tags = [dict(name='div', attrs={'class':['LM_atome']})]
|
|
||||||
remove_tags_after = [dict(id='appel_temoignage')]
|
|
||||||
|
|
||||||
def get_article_url(self, article):
|
|
||||||
url = article.get('guid', None)
|
|
||||||
if '/chat/' in url or '.blog' in url or '/video/' in url or '/sport/' in url or '/portfolio/' in url or '/visuel/' in url :
|
|
||||||
url = None
|
|
||||||
return url
|
|
||||||
|
|
||||||
# def get_article_url(self, article):
|
|
||||||
# link = article.get('link')
|
|
||||||
# if 'blog' not in link and ('chat' not in link):
|
|
||||||
# return link
|
|
||||||
|
|
||||||
feeds = [
|
feeds = [
|
||||||
('A la une', 'http://www.lemonde.fr/rss/une.xml'),
|
('A la une', 'http://www.lemonde.fr/rss/une.xml'),
|
||||||
@ -137,3 +67,10 @@ class LeMonde(BasicNewsRecipe):
|
|||||||
|
|
||||||
return cover_url
|
return cover_url
|
||||||
|
|
||||||
|
def get_article_url(self, article):
|
||||||
|
url = article.get('guid', None)
|
||||||
|
if '/chat/' in url or '.blog' in url or '/video/' in url or '/sport/' in url or '/portfolio/' in url or '/visuel/' in url :
|
||||||
|
url = None
|
||||||
|
return url
|
||||||
|
|
||||||
|
|
||||||
|
@ -381,12 +381,15 @@ def browser(honor_time=True, max_time=2, mobile_browser=False, user_agent=None):
|
|||||||
user_agent = USER_AGENT_MOBILE if mobile_browser else USER_AGENT
|
user_agent = USER_AGENT_MOBILE if mobile_browser else USER_AGENT
|
||||||
opener.addheaders = [('User-agent', user_agent)]
|
opener.addheaders = [('User-agent', user_agent)]
|
||||||
proxies = get_proxies()
|
proxies = get_proxies()
|
||||||
|
to_add = {}
|
||||||
http_proxy = proxies.get('http', None)
|
http_proxy = proxies.get('http', None)
|
||||||
if http_proxy:
|
if http_proxy:
|
||||||
opener.set_proxies({'http':http_proxy})
|
to_add['http'] = http_proxy
|
||||||
https_proxy = proxies.get('https', None)
|
https_proxy = proxies.get('https', None)
|
||||||
if https_proxy:
|
if https_proxy:
|
||||||
opener.set_proxies({'https':https_proxy})
|
to_add['https'] = https_proxy
|
||||||
|
if to_add:
|
||||||
|
opener.set_proxies(to_add)
|
||||||
|
|
||||||
return opener
|
return opener
|
||||||
|
|
||||||
|
@ -255,7 +255,10 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1">
|
<item row="3" column="1">
|
||||||
<widget class="QSpinBox" name="max_view_width">
|
<widget class="QSpinBox" name="max_fs_width">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Set the maximum width that the book's text and pictures will take when in fullscreen mode. This allows you to read the book text without it becoming too wide.</string>
|
||||||
|
</property>
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string> px</string>
|
<string> px</string>
|
||||||
</property>
|
</property>
|
||||||
@ -270,10 +273,10 @@
|
|||||||
<item row="3" column="0">
|
<item row="3" column="0">
|
||||||
<widget class="QLabel" name="label_7">
|
<widget class="QLabel" name="label_7">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Maximum &view width:</string>
|
<string>Maximum text width in &fullscreen:</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="buddy">
|
<property name="buddy">
|
||||||
<cstring>max_view_width</cstring>
|
<cstring>max_fs_width</cstring>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -350,7 +353,7 @@
|
|||||||
<tabstop>serif_family</tabstop>
|
<tabstop>serif_family</tabstop>
|
||||||
<tabstop>sans_family</tabstop>
|
<tabstop>sans_family</tabstop>
|
||||||
<tabstop>mono_family</tabstop>
|
<tabstop>mono_family</tabstop>
|
||||||
<tabstop>max_view_width</tabstop>
|
<tabstop>max_fs_width</tabstop>
|
||||||
<tabstop>opt_remember_window_size</tabstop>
|
<tabstop>opt_remember_window_size</tabstop>
|
||||||
<tabstop>buttonBox</tabstop>
|
<tabstop>buttonBox</tabstop>
|
||||||
</tabstops>
|
</tabstops>
|
||||||
|
@ -12,7 +12,7 @@ from PyQt4.Qt import (QSize, QSizePolicy, QUrl, SIGNAL, Qt, QTimer,
|
|||||||
QPainter, QPalette, QBrush, QFontDatabase, QDialog,
|
QPainter, QPalette, QBrush, QFontDatabase, QDialog,
|
||||||
QColor, QPoint, QImage, QRegion, QVariant, QIcon,
|
QColor, QPoint, QImage, QRegion, QVariant, QIcon,
|
||||||
QFont, pyqtSignature, QAction, QByteArray, QMenu,
|
QFont, pyqtSignature, QAction, QByteArray, QMenu,
|
||||||
pyqtSignal, QSwipeGesture)
|
pyqtSignal, QSwipeGesture, QApplication)
|
||||||
from PyQt4.QtWebKit import QWebPage, QWebView, QWebSettings
|
from PyQt4.QtWebKit import QWebPage, QWebView, QWebSettings
|
||||||
|
|
||||||
from calibre.utils.config import Config, StringConfig
|
from calibre.utils.config import Config, StringConfig
|
||||||
@ -46,8 +46,10 @@ def config(defaults=None):
|
|||||||
help=_('Remember last used window size'))
|
help=_('Remember last used window size'))
|
||||||
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.'))
|
||||||
c.add_opt('max_view_width', default=6000,
|
c.add_opt('max_fs_width', default=800,
|
||||||
help=_('Maximum width of the viewer window, in pixels.'))
|
help=_("Set the maximum width that the book's text and pictures will take"
|
||||||
|
" when in fullscreen mode. This allows you to read the book text"
|
||||||
|
" without it becoming too wide."))
|
||||||
c.add_opt('fit_images', default=True,
|
c.add_opt('fit_images', default=True,
|
||||||
help=_('Resize images larger than the viewer window to fit inside it'))
|
help=_('Resize images larger than the viewer window to fit inside it'))
|
||||||
c.add_opt('hyphenate', default=False, help=_('Hyphenate text'))
|
c.add_opt('hyphenate', default=False, help=_('Hyphenate text'))
|
||||||
@ -101,7 +103,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.'))
|
||||||
self.max_view_width.setValue(opts.max_view_width)
|
self.max_fs_width.setValue(opts.max_fs_width)
|
||||||
with zipfile.ZipFile(P('viewer/hyphenate/patterns.zip',
|
with zipfile.ZipFile(P('viewer/hyphenate/patterns.zip',
|
||||||
allow_user_override=False), 'r') as zf:
|
allow_user_override=False), 'r') as zf:
|
||||||
pats = [x.split('.')[0].replace('-', '_') for x in zf.namelist()]
|
pats = [x.split('.')[0].replace('-', '_') for x in zf.namelist()]
|
||||||
@ -144,7 +146,7 @@ class ConfigDialog(QDialog, Ui_Dialog):
|
|||||||
c.set('user_css', unicode(self.css.toPlainText()))
|
c.set('user_css', unicode(self.css.toPlainText()))
|
||||||
c.set('remember_window_size', self.opt_remember_window_size.isChecked())
|
c.set('remember_window_size', self.opt_remember_window_size.isChecked())
|
||||||
c.set('fit_images', self.opt_fit_images.isChecked())
|
c.set('fit_images', self.opt_fit_images.isChecked())
|
||||||
c.set('max_view_width', int(self.max_view_width.value()))
|
c.set('max_fs_width', int(self.max_fs_width.value()))
|
||||||
c.set('hyphenate', self.hyphenate.isChecked())
|
c.set('hyphenate', self.hyphenate.isChecked())
|
||||||
c.set('remember_current_page', self.opt_remember_current_page.isChecked())
|
c.set('remember_current_page', self.opt_remember_current_page.isChecked())
|
||||||
c.set('wheel_flips_pages', self.opt_wheel_flips_pages.isChecked())
|
c.set('wheel_flips_pages', self.opt_wheel_flips_pages.isChecked())
|
||||||
@ -192,6 +194,8 @@ class Document(QWebPage): # {{{
|
|||||||
self.loaded_javascript = False
|
self.loaded_javascript = False
|
||||||
self.js_loader = JavaScriptLoader(
|
self.js_loader = JavaScriptLoader(
|
||||||
dynamic_coffeescript=self.debug_javascript)
|
dynamic_coffeescript=self.debug_javascript)
|
||||||
|
self.initial_left_margin = self.initial_right_margin = u''
|
||||||
|
self.in_fullscreen_mode = False
|
||||||
|
|
||||||
self.setLinkDelegationPolicy(self.DelegateAllLinks)
|
self.setLinkDelegationPolicy(self.DelegateAllLinks)
|
||||||
self.scroll_marks = []
|
self.scroll_marks = []
|
||||||
@ -239,6 +243,9 @@ class Document(QWebPage): # {{{
|
|||||||
self.enable_page_flip = self.page_flip_duration > 0.1
|
self.enable_page_flip = self.page_flip_duration > 0.1
|
||||||
self.font_magnification_step = opts.font_magnification_step
|
self.font_magnification_step = opts.font_magnification_step
|
||||||
self.wheel_flips_pages = opts.wheel_flips_pages
|
self.wheel_flips_pages = opts.wheel_flips_pages
|
||||||
|
screen_width = QApplication.desktop().screenGeometry().width()
|
||||||
|
# Leave some space for the scrollbar and some border
|
||||||
|
self.max_fs_width = min(opts.max_fs_width, screen_width-50)
|
||||||
|
|
||||||
def fit_images(self):
|
def fit_images(self):
|
||||||
if self.do_fit_images:
|
if self.do_fit_images:
|
||||||
@ -274,6 +281,30 @@ class Document(QWebPage): # {{{
|
|||||||
self.set_bottom_padding(0)
|
self.set_bottom_padding(0)
|
||||||
self.fit_images()
|
self.fit_images()
|
||||||
self.init_hyphenate()
|
self.init_hyphenate()
|
||||||
|
self.initial_left_margin = unicode(self.javascript(
|
||||||
|
'document.body.style.marginLeft').toString())
|
||||||
|
self.initial_right_margin = unicode(self.javascript(
|
||||||
|
'document.body.style.marginRight').toString())
|
||||||
|
if self.in_fullscreen_mode:
|
||||||
|
self.switch_to_fullscreen_mode()
|
||||||
|
|
||||||
|
def switch_to_fullscreen_mode(self):
|
||||||
|
self.in_fullscreen_mode = True
|
||||||
|
self.javascript('''
|
||||||
|
var s = document.body.style;
|
||||||
|
s.maxWidth = "%dpx";
|
||||||
|
s.marginLeft = "auto";
|
||||||
|
s.marginRight = "auto";
|
||||||
|
'''%self.max_fs_width)
|
||||||
|
|
||||||
|
def switch_to_window_mode(self):
|
||||||
|
self.in_fullscreen_mode = False
|
||||||
|
self.javascript('''
|
||||||
|
var s = document.body.style;
|
||||||
|
s.maxWidth = "none";
|
||||||
|
s.marginLeft = "%s";
|
||||||
|
s.marginRight = "%s";
|
||||||
|
'''%(self.initial_left_margin, self.initial_right_margin))
|
||||||
|
|
||||||
@pyqtSignature("QString")
|
@pyqtSignature("QString")
|
||||||
def debug(self, msg):
|
def debug(self, msg):
|
||||||
@ -581,8 +612,8 @@ class DocumentView(QWebView): # {{{
|
|||||||
|
|
||||||
def config(self, parent=None):
|
def config(self, parent=None):
|
||||||
self.document.do_config(parent)
|
self.document.do_config(parent)
|
||||||
if self.manager is not None:
|
if self.document.in_fullscreen_mode:
|
||||||
self.manager.set_max_width()
|
self.document.switch_to_fullscreen_mode()
|
||||||
self.setFocus(Qt.OtherFocusReason)
|
self.setFocus(Qt.OtherFocusReason)
|
||||||
|
|
||||||
def bookmark(self):
|
def bookmark(self):
|
||||||
@ -602,6 +633,9 @@ class DocumentView(QWebView): # {{{
|
|||||||
menu.insertAction(list(menu.actions())[0], self.search_action)
|
menu.insertAction(list(menu.actions())[0], self.search_action)
|
||||||
menu.addSeparator()
|
menu.addSeparator()
|
||||||
menu.addAction(self.goto_location_action)
|
menu.addAction(self.goto_location_action)
|
||||||
|
if self.document.in_fullscreen_mode and self.manager is not None:
|
||||||
|
menu.addSeparator()
|
||||||
|
menu.addAction(self.manager.toggle_toolbar_action)
|
||||||
menu.exec_(ev.globalPos())
|
menu.exec_(ev.globalPos())
|
||||||
|
|
||||||
def lookup(self, *args):
|
def lookup(self, *args):
|
||||||
|
@ -5,11 +5,11 @@ import traceback, os, sys, functools, collections, re
|
|||||||
from functools import partial
|
from functools import partial
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
|
||||||
from PyQt4.Qt import QApplication, Qt, QIcon, QTimer, SIGNAL, QByteArray, \
|
from PyQt4.Qt import (QApplication, Qt, QIcon, QTimer, SIGNAL, QByteArray,
|
||||||
QDoubleSpinBox, QLabel, QTextBrowser, \
|
QSize, QDoubleSpinBox, QLabel, QTextBrowser, QPropertyAnimation,
|
||||||
QPainter, QBrush, QColor, QStandardItemModel, QPalette, \
|
QPainter, QBrush, QColor, QStandardItemModel, QPalette, QStandardItem,
|
||||||
QStandardItem, QUrl, QRegExpValidator, QRegExp, QLineEdit, \
|
QUrl, QRegExpValidator, QRegExp, QLineEdit, QToolButton, QMenu,
|
||||||
QToolButton, QMenu, QInputDialog, QAction, QKeySequence
|
QInputDialog, QAction, QKeySequence)
|
||||||
|
|
||||||
from calibre.gui2.viewer.main_ui import Ui_EbookViewer
|
from calibre.gui2.viewer.main_ui import Ui_EbookViewer
|
||||||
from calibre.gui2.viewer.printing import Printing
|
from calibre.gui2.viewer.printing import Printing
|
||||||
@ -55,8 +55,6 @@ class TOC(QStandardItemModel):
|
|||||||
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):
|
||||||
@ -292,6 +290,37 @@ 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.full_screen_label = QLabel('''
|
||||||
|
<center>
|
||||||
|
<h1>%s</h1>
|
||||||
|
<h3>%s</h3>
|
||||||
|
<h3>%s</h3>
|
||||||
|
</center>
|
||||||
|
'''%(_('Full screen mode'),
|
||||||
|
_('Right click to show controls'),
|
||||||
|
_('Press Esc to quit')),
|
||||||
|
self)
|
||||||
|
self.full_screen_label.setVisible(False)
|
||||||
|
self.full_screen_label.setStyleSheet('''
|
||||||
|
QLabel {
|
||||||
|
text-align: center;
|
||||||
|
background-color: white;
|
||||||
|
color: black;
|
||||||
|
border-width: 1px;
|
||||||
|
border-style: solid;
|
||||||
|
border-radius: 20px;
|
||||||
|
}
|
||||||
|
''')
|
||||||
|
self.toggle_toolbar_action = QAction(_('Show/hide controls'), self)
|
||||||
|
self.toggle_toolbar_action.triggered.connect(self.toggle_toolbars)
|
||||||
|
self.addAction(self.toggle_toolbar_action)
|
||||||
|
self.full_screen_label_anim = QPropertyAnimation(
|
||||||
|
self.full_screen_label, 'size')
|
||||||
|
self.esc_full_screen_action = a = QAction(self)
|
||||||
|
self.addAction(a)
|
||||||
|
a.setShortcut(Qt.Key_Escape)
|
||||||
|
a.setEnabled(False)
|
||||||
|
a.triggered.connect(self.action_full_screen.trigger)
|
||||||
|
|
||||||
self.print_menu = QMenu()
|
self.print_menu = QMenu()
|
||||||
self.print_menu.addAction(QIcon(I('print-preview.png')), _('Print Preview'))
|
self.print_menu.addAction(QIcon(I('print-preview.png')), _('Print Preview'))
|
||||||
@ -299,7 +328,6 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
self.tool_bar.widgetForAction(self.action_print).setPopupMode(QToolButton.MenuButtonPopup)
|
self.tool_bar.widgetForAction(self.action_print).setPopupMode(QToolButton.MenuButtonPopup)
|
||||||
self.connect(self.action_print, SIGNAL("triggered(bool)"), partial(self.print_book, preview=False))
|
self.connect(self.action_print, SIGNAL("triggered(bool)"), partial(self.print_book, preview=False))
|
||||||
self.connect(self.print_menu.actions()[0], SIGNAL("triggered(bool)"), partial(self.print_book, preview=True))
|
self.connect(self.print_menu.actions()[0], SIGNAL("triggered(bool)"), partial(self.print_book, preview=True))
|
||||||
self.set_max_width()
|
|
||||||
ca = self.view.copy_action
|
ca = self.view.copy_action
|
||||||
ca.setShortcut(QKeySequence.Copy)
|
ca.setShortcut(QKeySequence.Copy)
|
||||||
self.addAction(ca)
|
self.addAction(ca)
|
||||||
@ -313,6 +341,13 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
w = self.tool_bar.widgetForAction(self.action_open_ebook)
|
w = self.tool_bar.widgetForAction(self.action_open_ebook)
|
||||||
w.setPopupMode(QToolButton.MenuButtonPopup)
|
w.setPopupMode(QToolButton.MenuButtonPopup)
|
||||||
|
|
||||||
|
for x in ('tool_bar', 'tool_bar2'):
|
||||||
|
x = getattr(self, x)
|
||||||
|
for action in x.actions():
|
||||||
|
# So that the keyboard shortcuts for these actions will
|
||||||
|
# continue to function even when the toolbars are hidden
|
||||||
|
self.addAction(action)
|
||||||
|
|
||||||
self.restore_state()
|
self.restore_state()
|
||||||
|
|
||||||
def set_toc_visible(self, yes):
|
def set_toc_visible(self, yes):
|
||||||
@ -338,9 +373,18 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
count += 1
|
count += 1
|
||||||
|
|
||||||
def closeEvent(self, e):
|
def closeEvent(self, e):
|
||||||
|
if self.isFullScreen():
|
||||||
|
self.action_full_screen.trigger()
|
||||||
|
e.ignore()
|
||||||
|
return
|
||||||
self.save_state()
|
self.save_state()
|
||||||
return MainWindow.closeEvent(self, e)
|
return MainWindow.closeEvent(self, e)
|
||||||
|
|
||||||
|
def toggle_toolbars(self):
|
||||||
|
for x in ('tool_bar', 'tool_bar2'):
|
||||||
|
x = getattr(self, x)
|
||||||
|
x.setVisible(not x.isVisible())
|
||||||
|
|
||||||
def save_state(self):
|
def save_state(self):
|
||||||
state = bytearray(self.saveState(self.STATE_VERSION))
|
state = bytearray(self.saveState(self.STATE_VERSION))
|
||||||
vprefs['viewer_toolbar_state'] = state
|
vprefs['viewer_toolbar_state'] = state
|
||||||
@ -382,11 +426,6 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
self._lookup = None
|
self._lookup = None
|
||||||
self.dictionary_view.setHtml(html)
|
self.dictionary_view.setHtml(html)
|
||||||
|
|
||||||
def set_max_width(self):
|
|
||||||
from calibre.gui2.viewer.documentview import config
|
|
||||||
c = config().parse()
|
|
||||||
self.frame.setMaximumWidth(c.max_view_width)
|
|
||||||
|
|
||||||
def get_remember_current_page_opt(self):
|
def get_remember_current_page_opt(self):
|
||||||
from calibre.gui2.viewer.documentview import config
|
from calibre.gui2.viewer.documentview import config
|
||||||
c = config().parse()
|
c = config().parse()
|
||||||
@ -401,6 +440,46 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
else:
|
else:
|
||||||
self.showFullScreen()
|
self.showFullScreen()
|
||||||
|
|
||||||
|
def showFullScreen(self):
|
||||||
|
self.tool_bar.setVisible(False)
|
||||||
|
self.tool_bar2.setVisible(False)
|
||||||
|
self._original_frame_margins = (
|
||||||
|
self.centralwidget.layout().contentsMargins(),
|
||||||
|
self.frame.layout().contentsMargins())
|
||||||
|
self.frame.layout().setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.centralwidget.layout().setContentsMargins(0, 0, 0, 0)
|
||||||
|
|
||||||
|
super(EbookViewer, self).showFullScreen()
|
||||||
|
QTimer.singleShot(10, self.show_full_screen_label)
|
||||||
|
|
||||||
|
def show_full_screen_label(self):
|
||||||
|
f = self.full_screen_label
|
||||||
|
self.esc_full_screen_action.setEnabled(True)
|
||||||
|
f.setVisible(True)
|
||||||
|
height = 200
|
||||||
|
width = int(0.7*self.view.width())
|
||||||
|
f.resize(width, height)
|
||||||
|
f.move((self.view.width() - width)//2, (self.view.height()-height)//2)
|
||||||
|
a = self.full_screen_label_anim
|
||||||
|
a.setDuration(500)
|
||||||
|
a.setStartValue(QSize(width, 0))
|
||||||
|
a.setEndValue(QSize(width, height))
|
||||||
|
a.start()
|
||||||
|
QTimer.singleShot(2750, self.full_screen_label.hide)
|
||||||
|
self.view.document.switch_to_fullscreen_mode()
|
||||||
|
|
||||||
|
def showNormal(self):
|
||||||
|
self.esc_full_screen_action.setEnabled(False)
|
||||||
|
self.tool_bar.setVisible(True)
|
||||||
|
self.tool_bar2.setVisible(True)
|
||||||
|
self.full_screen_label.setVisible(False)
|
||||||
|
if hasattr(self, '_original_frame_margins'):
|
||||||
|
om = self._original_frame_margins
|
||||||
|
self.centralwidget.layout().setContentsMargins(om[0])
|
||||||
|
self.frame.layout().setContentsMargins(om[1])
|
||||||
|
super(EbookViewer, self).showNormal()
|
||||||
|
self.view.document.switch_to_window_mode()
|
||||||
|
|
||||||
def goto(self, ref):
|
def goto(self, ref):
|
||||||
if ref:
|
if ref:
|
||||||
tokens = ref.split('.')
|
tokens = ref.split('.')
|
||||||
|
@ -284,6 +284,9 @@
|
|||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Toggle full screen</string>
|
<string>Toggle full screen</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Toggle full screen (F11)</string>
|
||||||
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="action_print">
|
<action name="action_print">
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user