mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-06-23 15:30:45 -04:00
Merge from trunk
This commit is contained in:
commit
197c1b0543
@ -19,6 +19,54 @@
|
|||||||
# new recipes:
|
# new recipes:
|
||||||
# - title:
|
# - title:
|
||||||
|
|
||||||
|
- version: 0.8.61
|
||||||
|
date: 2012-07-20
|
||||||
|
|
||||||
|
new features:
|
||||||
|
- title: "E-book viewer: Add a paged mode that splits up the text into pages, like in a paper book instead of presenting it as a single column. To activate click the button with the yellow scroll icon in the top right corner."
|
||||||
|
type: major
|
||||||
|
description: "In paged mode, the ebook viewer no longer cuts off the last line of text at the bottom of the screen, and it respects CSS page-break directives. You can also set page margins and control the number of pages displayed on screen by clicking the Preferences button in the viewer and going to 'Text layout in paged mode'."
|
||||||
|
|
||||||
|
- title: "Digitally sign the calibre OS X and windows builds"
|
||||||
|
|
||||||
|
- title: "Get Books: Add Mills and Boon UK"
|
||||||
|
|
||||||
|
- title: "Various minor improvements to the Bulk metadata edit dialog"
|
||||||
|
tickets: [1025825, 1025838, 1025628]
|
||||||
|
|
||||||
|
- title: "Fix various regression in the auto-complete functionality for authors/series/tags etc introduced in 0.8.60"
|
||||||
|
|
||||||
|
- title: "Drivers for various new Android devices"
|
||||||
|
tickets: [1024934]
|
||||||
|
|
||||||
|
- title: "MOBI: Add support for the new language EXTH header field in MOBI files generated by kindlegen 2.5"
|
||||||
|
|
||||||
|
bug fixes:
|
||||||
|
- title: "KF8 Output: Fix calibre produced KF8 files not showing the 'Use publisher font' option on the Kindle Touch when they have embedded fonts"
|
||||||
|
|
||||||
|
- title: "Txt/fb2/rtf/pml/rb output: Fix non-visibile element's tail text (which should be visible) is being ignored when it shouldn't."
|
||||||
|
tickets: [1026541]
|
||||||
|
|
||||||
|
- title: "Book details panel: When displaying a link to amazon, use a country specific name like amazon.fr instead of using amazon.com for all countries"
|
||||||
|
|
||||||
|
- title: "Conversion: When splitting on page breaks, ignore page-breaks with values of auto and inherit. "
|
||||||
|
tickets: [1018875]
|
||||||
|
|
||||||
|
- title: "Metadata jacket: Specify foreground in addition to the background color for the title banner so that it remain readable if the user tries to monkey with the CSS in the viewer."
|
||||||
|
|
||||||
|
- title: "PDF Output: Fix rendering of cover as first age of PDF (ignore margins so that the image covers the entire page)"
|
||||||
|
|
||||||
|
- title: "Linux binaries: Bundle libglib to avoid incompatibilities with glib on various distros."
|
||||||
|
tickets: [1022019]
|
||||||
|
|
||||||
|
- title: "Fix find_identical_books() choking on books with too many authors"
|
||||||
|
|
||||||
|
|
||||||
|
improved recipes:
|
||||||
|
- Toronto Star
|
||||||
|
- American Prospect
|
||||||
|
- faz.net
|
||||||
|
|
||||||
- version: 0.8.60
|
- version: 0.8.60
|
||||||
date: 2012-07-13
|
date: 2012-07-13
|
||||||
|
|
||||||
|
@ -21,8 +21,12 @@ class anan(BasicNewsRecipe):
|
|||||||
remove_javascript = True
|
remove_javascript = True
|
||||||
encoding = 'utf-8'
|
encoding = 'utf-8'
|
||||||
|
|
||||||
remove_tags=[dict(name='a', attrs={'style':'width:110px; margin-top:0px;text-align:center;'}),
|
remove_tags=[
|
||||||
dict(name='a', attrs={'style':'width:110px; margin-top:0px; margin-right:20px;text-align:center;'})]
|
dict(name='a', attrs={'style':'width:110px; margin-top:0px;text-align:center;'}),
|
||||||
|
dict(name='a', attrs={'style':'width:110px; margin-top:0px; margin-right:20px;text-align:center;'}),
|
||||||
|
{'attrs':{'class':['article_links', 'header', 'body_right']}},
|
||||||
|
{'id':['crumbs']},
|
||||||
|
]
|
||||||
|
|
||||||
feeds = [ ('Anandtech', 'http://www.anandtech.com/rss/')]
|
feeds = [ ('Anandtech', 'http://www.anandtech.com/rss/')]
|
||||||
|
|
||||||
|
32
recipes/dot_net.recipe
Normal file
32
recipes/dot_net.recipe
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
import re
|
||||||
|
|
||||||
|
class NetMagazineRecipe (BasicNewsRecipe):
|
||||||
|
__author__ = u'Marc Busqué <marc@lamarciana.com>'
|
||||||
|
__url__ = 'http://www.lamarciana.com'
|
||||||
|
__version__ = '1.0'
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = u'2012, Marc Busqué <marc@lamarciana.com>'
|
||||||
|
title = u'.net magazine'
|
||||||
|
description = u'net is the world’s best-selling magazine for web designers and developers, featuring tutorials from leading agencies, interviews with the web’s biggest names, and agenda-setting features on the hottest issues affecting the internet today.'
|
||||||
|
language = 'en'
|
||||||
|
tags = 'web development, software'
|
||||||
|
oldest_article = 7
|
||||||
|
remove_empty_feeds = True
|
||||||
|
no_stylesheets = True
|
||||||
|
cover_url = u'http://media.netmagazine.futurecdn.net/sites/all/themes/netmag/logo.png'
|
||||||
|
keep_only_tags = [
|
||||||
|
dict(name='article', attrs={'class': re.compile('^node.*$', re.IGNORECASE)})
|
||||||
|
]
|
||||||
|
remove_tags = [
|
||||||
|
dict(name='span', attrs={'class': 'comment-count'}),
|
||||||
|
dict(name='div', attrs={'class': 'item-list share-links'}),
|
||||||
|
dict(name='footer'),
|
||||||
|
]
|
||||||
|
remove_attributes = ['border', 'cellspacing', 'align', 'cellpadding', 'colspan', 'valign', 'vspace', 'hspace', 'alt', 'width', 'height', 'style']
|
||||||
|
extra_css = 'img {max-width: 100%; display: block; margin: auto;} .captioned-image div {text-align: center; font-style: italic;}'
|
||||||
|
|
||||||
|
feeds = [
|
||||||
|
(u'.net', u'http://feeds.feedburner.com/net/topstories'),
|
||||||
|
]
|
33
recipes/list_apart.recipe
Normal file
33
recipes/list_apart.recipe
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class AListApart (BasicNewsRecipe):
|
||||||
|
__author__ = u'Marc Busqué <marc@lamarciana.com>'
|
||||||
|
__url__ = 'http://www.lamarciana.com'
|
||||||
|
__version__ = '1.0'
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = u'2012, Marc Busqué <marc@lamarciana.com>'
|
||||||
|
title = u'A List Apart'
|
||||||
|
description = u'A List Apart Magazine (ISSN: 1534-0295) explores the design, development, and meaning of web content, with a special focus on web standards and best practices.'
|
||||||
|
language = 'en'
|
||||||
|
tags = 'web development, software'
|
||||||
|
oldest_article = 120
|
||||||
|
remove_empty_feeds = True
|
||||||
|
no_stylesheets = True
|
||||||
|
encoding = 'utf8'
|
||||||
|
cover_url = u'http://alistapart.com/pix/alalogo.gif'
|
||||||
|
keep_only_tags = [
|
||||||
|
dict(name='div', attrs={'id': 'content'})
|
||||||
|
]
|
||||||
|
remove_tags = [
|
||||||
|
dict(name='ul', attrs={'id': 'metastuff'}),
|
||||||
|
dict(name='div', attrs={'class': 'discuss'}),
|
||||||
|
dict(name='div', attrs={'class': 'discuss'}),
|
||||||
|
dict(name='div', attrs={'id': 'learnmore'}),
|
||||||
|
]
|
||||||
|
remove_attributes = ['border', 'cellspacing', 'align', 'cellpadding', 'colspan', 'valign', 'vspace', 'hspace', 'alt', 'width', 'height']
|
||||||
|
extra_css = u'img {max-width: 100%; display: block; margin: auto;} #authorbio img {float: left; margin-right: 2%;}'
|
||||||
|
|
||||||
|
feeds = [
|
||||||
|
(u'A List Apart', u'http://www.alistapart.com/site/rss'),
|
||||||
|
]
|
@ -1,25 +1,35 @@
|
|||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
class SanFranciscoBayGuardian(BasicNewsRecipe):
|
class SanFranciscoBayGuardian(BasicNewsRecipe):
|
||||||
title = u'San Francisco Bay Guardian'
|
title = u'San Francisco Bay Guardian'
|
||||||
language = 'en'
|
language = 'en'
|
||||||
__author__ = 'Krittika Goyal'
|
__author__ = 'Krittika Goyal'
|
||||||
oldest_article = 31 #days
|
oldest_article = 31 #days
|
||||||
max_articles_per_feed = 25
|
max_articles_per_feed = 25
|
||||||
|
#encoding = 'latin1'
|
||||||
|
|
||||||
no_stylesheets = True
|
no_stylesheets = True
|
||||||
|
#remove_tags_before = dict(name='div', attrs={'id':'story_header'})
|
||||||
|
#remove_tags_after = dict(name='div', attrs={'id':'shirttail'})
|
||||||
remove_tags = [
|
remove_tags = [
|
||||||
dict(name='iframe'),
|
dict(name='iframe'),
|
||||||
|
#dict(name='div', attrs={'class':'related-articles'}),
|
||||||
|
#dict(name='div', attrs={'id':['story_tools', 'toolbox', 'shirttail', 'comment_widget']}),
|
||||||
|
#dict(name='ul', attrs={'class':'article-tools'}),
|
||||||
|
#dict(name='ul', attrs={'id':'story_tabs'}),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
feeds = [
|
feeds = [
|
||||||
('sfbg', 'http://www.sfbg.com/rss.xml'),
|
('sfbg', 'http://www.sfbg.com/rss.xml'),
|
||||||
('politics', 'http://www.sfbg.com/politics/rss.xml'),
|
|
||||||
('blogs', 'http://www.sfbg.com/blog/rss.xml'),
|
|
||||||
('pixel_vision', 'http://www.sfbg.com/pixel_vision/rss.xml'),
|
|
||||||
('bruce', 'http://www.sfbg.com/bruce/rss.xml'),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
#def preprocess_html(self, soup):
|
||||||
|
#story = soup.find(name='div', attrs={'id':'story_body'})
|
||||||
|
#td = heading.findParent(name='td')
|
||||||
|
#td.extract()
|
||||||
|
#soup = BeautifulSoup('<html><head><title>t</title></head><body></body></html>')
|
||||||
|
#body = soup.find(name='body')
|
||||||
|
#body.insert(0, story)
|
||||||
|
#return soup
|
||||||
|
@ -1,50 +1,24 @@
|
|||||||
#!/usr/bin/env python
|
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
|
||||||
|
|
||||||
__license__ = 'GPL v3'
|
|
||||||
__copyright__ = '2009, Darko Miletic <darko.miletic at gmail.com>'
|
|
||||||
'''
|
|
||||||
www.smashingmagazine.com
|
|
||||||
'''
|
|
||||||
|
|
||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
class SmashingMagazine(BasicNewsRecipe):
|
class SmashingMagazine (BasicNewsRecipe):
|
||||||
title = 'Smashing Magazine'
|
__author__ = u'Marc Busqué <marc@lamarciana.com>'
|
||||||
__author__ = 'Darko Miletic'
|
__url__ = 'http://www.lamarciana.com'
|
||||||
description = 'We smash you with the information that will make your life easier, really'
|
__version__ = '1.0.1'
|
||||||
oldest_article = 20
|
__license__ = 'GPL v3'
|
||||||
language = 'en'
|
__copyright__ = u'2012, Marc Busqué <marc@lamarciana.com>'
|
||||||
max_articles_per_feed = 100
|
title = u'Smashing Magazine'
|
||||||
no_stylesheets = True
|
description = u'Founded in September 2006, Smashing Magazine delivers useful and innovative information to Web designers and developers. Our aim is to inform our readers about the latest trends and techniques in Web development. We try to persuade you not with the quantity but with the quality of the information we present. Smashing Magazine is and always has been independent.'
|
||||||
use_embedded_content = False
|
language = 'en'
|
||||||
publisher = 'Smashing Magazine'
|
tags = 'web development, software'
|
||||||
category = 'news, web, IT, css, javascript, html'
|
oldest_article = 7
|
||||||
encoding = 'utf-8'
|
remove_empty_feeds = True
|
||||||
|
no_stylesheets = True
|
||||||
|
encoding = 'utf8'
|
||||||
|
cover_url = u'http://media.smashingmagazine.com/themes/smashingv4/images/logo.png'
|
||||||
|
remove_attributes = ['border', 'cellspacing', 'align', 'cellpadding', 'colspan', 'valign', 'vspace', 'hspace', 'alt', 'width', 'height', 'style']
|
||||||
|
extra_css = u'body div table:first-child {display: none;} img {max-width: 100%; display: block; margin: auto;}'
|
||||||
|
|
||||||
conversion_options = {
|
feeds = [
|
||||||
'comments' : description
|
(u'Smashing Magazine', u'http://rss1.smashingmagazine.com/feed/'),
|
||||||
,'tags' : category
|
]
|
||||||
,'publisher' : publisher
|
|
||||||
}
|
|
||||||
|
|
||||||
keep_only_tags = [dict(name='div', attrs={'id':'leftcolumn'})]
|
|
||||||
remove_tags_after = dict(name='ul',attrs={'class':'social'})
|
|
||||||
remove_tags = [
|
|
||||||
dict(name=['link','object'])
|
|
||||||
,dict(name='h1',attrs={'class':'logo'})
|
|
||||||
,dict(name='div',attrs={'id':'booklogosec'})
|
|
||||||
,dict(attrs={'src':'http://media2.smashingmagazine.com/wp-content/uploads/images/the-smashing-book/smbook6.gif'})
|
|
||||||
]
|
|
||||||
|
|
||||||
feeds = [(u'Articles', u'http://rss1.smashingmagazine.com/feed/')]
|
|
||||||
|
|
||||||
def preprocess_html(self, soup):
|
|
||||||
for iter in soup.findAll('div',attrs={'class':'leftframe'}):
|
|
||||||
it = iter.find('h1')
|
|
||||||
if it == None:
|
|
||||||
iter.extract()
|
|
||||||
for item in soup.findAll('img'):
|
|
||||||
oldParent = item.parent
|
|
||||||
if oldParent.name == 'a':
|
|
||||||
oldParent.name = 'div'
|
|
||||||
return soup
|
|
||||||
|
Binary file not shown.
BIN
resources/images/scroll.png
Normal file
BIN
resources/images/scroll.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
@ -27,6 +27,7 @@
|
|||||||
*/
|
*/
|
||||||
.cbj_banner {
|
.cbj_banner {
|
||||||
background: #eee;
|
background: #eee;
|
||||||
|
color: black;
|
||||||
border: thin solid black;
|
border: thin solid black;
|
||||||
margin: 1em;
|
margin: 1em;
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
|
@ -37,6 +37,7 @@ class Win32(VMInstaller):
|
|||||||
SHUTDOWN_CMD = ['shutdown.exe', '-s', '-f', '-t', '0']
|
SHUTDOWN_CMD = ['shutdown.exe', '-s', '-f', '-t', '0']
|
||||||
|
|
||||||
def sign_msi(self):
|
def sign_msi(self):
|
||||||
|
print ('Signing .msi ...')
|
||||||
raw = open(self.VM).read()
|
raw = open(self.VM).read()
|
||||||
vmx = re.search(r'''launch_vmware\(['"](.+?)['"]''', raw).group(1)
|
vmx = re.search(r'''launch_vmware\(['"](.+?)['"]''', raw).group(1)
|
||||||
subprocess.check_call(['vmrun', '-T', 'ws', '-gu', 'kovid', '-gp',
|
subprocess.check_call(['vmrun', '-T', 'ws', '-gu', 'kovid', '-gp',
|
||||||
|
@ -4,7 +4,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__ = u'calibre'
|
__appname__ = u'calibre'
|
||||||
numeric_version = (0, 8, 60)
|
numeric_version = (0, 8, 61)
|
||||||
__version__ = u'.'.join(map(unicode, numeric_version))
|
__version__ = u'.'.join(map(unicode, numeric_version))
|
||||||
__author__ = u"Kovid Goyal <kovid@kovidgoyal.net>"
|
__author__ = u"Kovid Goyal <kovid@kovidgoyal.net>"
|
||||||
|
|
||||||
|
@ -212,7 +212,7 @@ class ANDROID(USBMS):
|
|||||||
'KTABLET_PC', 'INGENIC', 'GT-I9001_CARD', 'USB_2.0_DRIVER',
|
'KTABLET_PC', 'INGENIC', 'GT-I9001_CARD', 'USB_2.0_DRIVER',
|
||||||
'GT-S5830L_CARD', 'UNIVERSE', 'XT875', 'PRO', '.KOBO_VOX',
|
'GT-S5830L_CARD', 'UNIVERSE', 'XT875', 'PRO', '.KOBO_VOX',
|
||||||
'THINKPAD_TABLET', 'SGH-T989', 'YP-G70', 'STORAGE_DEVICE',
|
'THINKPAD_TABLET', 'SGH-T989', 'YP-G70', 'STORAGE_DEVICE',
|
||||||
'ADVANCED']
|
'ADVANCED', 'SGH-I727']
|
||||||
WINDOWS_CARD_A_MEM = ['ANDROID_PHONE', 'GT-I9000_CARD', 'SGH-I897',
|
WINDOWS_CARD_A_MEM = ['ANDROID_PHONE', 'GT-I9000_CARD', 'SGH-I897',
|
||||||
'FILE-STOR_GADGET', 'SGH-T959_CARD', 'SGH-T959', 'SAMSUNG_ANDROID', 'GT-P1000_CARD',
|
'FILE-STOR_GADGET', 'SGH-T959_CARD', 'SGH-T959', 'SAMSUNG_ANDROID', 'GT-P1000_CARD',
|
||||||
'A70S', 'A101IT', '7', 'INCREDIBLE', 'A7EB', 'SGH-T849_CARD',
|
'A70S', 'A101IT', '7', 'INCREDIBLE', 'A7EB', 'SGH-T849_CARD',
|
||||||
@ -221,7 +221,7 @@ class ANDROID(USBMS):
|
|||||||
'A1-07___C0541A4F', 'XT912', 'MB855', 'XT910', 'BOOK_A10_CARD',
|
'A1-07___C0541A4F', 'XT912', 'MB855', 'XT910', 'BOOK_A10_CARD',
|
||||||
'USB_2.0_DRIVER', 'I9100T', 'P999DW_SD_CARD', 'KTABLET_PC',
|
'USB_2.0_DRIVER', 'I9100T', 'P999DW_SD_CARD', 'KTABLET_PC',
|
||||||
'FILE-CD_GADGET', 'GT-I9001_CARD', 'USB_2.0_DRIVER', 'XT875',
|
'FILE-CD_GADGET', 'GT-I9001_CARD', 'USB_2.0_DRIVER', 'XT875',
|
||||||
'UMS_COMPOSITE', 'PRO', '.KOBO_VOX', 'SGH-T989_CARD']
|
'UMS_COMPOSITE', 'PRO', '.KOBO_VOX', 'SGH-T989_CARD', 'SGH-I727']
|
||||||
|
|
||||||
OSX_MAIN_MEM = 'Android Device Main Memory'
|
OSX_MAIN_MEM = 'Android Device Main Memory'
|
||||||
|
|
||||||
|
@ -601,17 +601,23 @@ class KOBO(USBMS):
|
|||||||
# Unsupported database
|
# Unsupported database
|
||||||
opts = self.settings()
|
opts = self.settings()
|
||||||
if not opts.extra_customization[self.OPT_SUPPORT_NEWER_FIRMWARE]:
|
if not opts.extra_customization[self.OPT_SUPPORT_NEWER_FIRMWARE]:
|
||||||
debug_print('The database has been upgraded past supported version')
|
|
||||||
debug_print('The database has been upgraded past supported version')
|
debug_print('The database has been upgraded past supported version')
|
||||||
self.report_progress(1.0, _('Removing books from device...'))
|
self.report_progress(1.0, _('Removing books from device...'))
|
||||||
from calibre.devices.errors import UserFeedback
|
from calibre.devices.errors import UserFeedback
|
||||||
raise UserFeedback(_("Kobo database version unsupported - See details"),
|
raise UserFeedback(_("Kobo database version unsupported - See details"),
|
||||||
_('Your Kobo is running an updated firmware/database version. '
|
_('Your Kobo is running an updated firmware/database version.'
|
||||||
'As Calibre has not been updated, database editing is disabled. '
|
' As calibre does not know about this updated firmware,'
|
||||||
'You can enable support for your Kobo in plugin preferences. '
|
' database editing is disabled, to prevent corruption.'
|
||||||
'Doing so may require you to perform a factory reset. '
|
' You can still send books to your Kobo with calibre, '
|
||||||
'Before selecting the "Attempt to support newer firmware" option '
|
' but deleting books and managing collections is disabled.'
|
||||||
'you should be familiar with restoring your Kobo to factory defaults.'),
|
' If you are willing to experiment and know how to reset'
|
||||||
|
' your Kobo to Factory defaults, you can override this'
|
||||||
|
' check by right clicking the device icon in calibre and'
|
||||||
|
' selecting "Configure this device" and then the '
|
||||||
|
' "Attempt to support newer firmware" option.'
|
||||||
|
' Doing so may require you to perform a factory reset of'
|
||||||
|
' your Kobo.'
|
||||||
|
),
|
||||||
UserFeedback.WARN)
|
UserFeedback.WARN)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
@ -280,17 +280,17 @@ class PRST1(USBMS):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
|
|
||||||
debug_print("Removing Orphaned Collection Records")
|
debug_print("Removing Orphaned Collection Records")
|
||||||
|
|
||||||
# Purge any collections references that point into the abyss
|
# Purge any collections references that point into the abyss
|
||||||
query = 'DELETE FROM collections WHERE content_id NOT IN (SELECT _id FROM books)'
|
query = 'DELETE FROM collections WHERE content_id NOT IN (SELECT _id FROM books)'
|
||||||
cursor.execute(query)
|
cursor.execute(query)
|
||||||
query = 'DELETE FROM collections WHERE collection_id NOT IN (SELECT _id FROM collection)'
|
query = 'DELETE FROM collections WHERE collection_id NOT IN (SELECT _id FROM collection)'
|
||||||
cursor.execute(query)
|
cursor.execute(query)
|
||||||
|
|
||||||
debug_print("Removing Orphaned Book Records")
|
debug_print("Removing Orphaned Book Records")
|
||||||
|
|
||||||
# Purge any references to books not in this database
|
# Purge any references to books not in this database
|
||||||
# Idea is to prevent any spill-over where these wind up applying to some other book
|
# Idea is to prevent any spill-over where these wind up applying to some other book
|
||||||
query = 'DELETE FROM %s WHERE content_id NOT IN (SELECT _id FROM books)'
|
query = 'DELETE FROM %s WHERE content_id NOT IN (SELECT _id FROM books)'
|
||||||
@ -301,7 +301,7 @@ class PRST1(USBMS):
|
|||||||
cursor.execute(query%'history')
|
cursor.execute(query%'history')
|
||||||
cursor.execute(query%'layout_cache')
|
cursor.execute(query%'layout_cache')
|
||||||
cursor.execute(query%'preference')
|
cursor.execute(query%'preference')
|
||||||
|
|
||||||
cursor.close()
|
cursor.close()
|
||||||
except DatabaseError:
|
except DatabaseError:
|
||||||
import traceback
|
import traceback
|
||||||
@ -320,7 +320,7 @@ class PRST1(USBMS):
|
|||||||
query = 'SELECT last_insert_rowid()'
|
query = 'SELECT last_insert_rowid()'
|
||||||
cursor.execute(query)
|
cursor.execute(query)
|
||||||
row = cursor.fetchone()
|
row = cursor.fetchone()
|
||||||
|
|
||||||
return long(row[0])
|
return long(row[0])
|
||||||
|
|
||||||
def get_database_min_id(self, source_id):
|
def get_database_min_id(self, source_id):
|
||||||
@ -376,6 +376,8 @@ class PRST1(USBMS):
|
|||||||
# Record what the max id being used is as well.
|
# Record what the max id being used is as well.
|
||||||
db_books = {}
|
db_books = {}
|
||||||
for i, row in enumerate(cursor):
|
for i, row in enumerate(cursor):
|
||||||
|
if row[0] is None:
|
||||||
|
continue
|
||||||
lpath = row[0].replace('\\', '/')
|
lpath = row[0].replace('\\', '/')
|
||||||
db_books[lpath] = row[1]
|
db_books[lpath] = row[1]
|
||||||
if row[1] < sequence_min:
|
if row[1] < sequence_min:
|
||||||
|
@ -352,13 +352,21 @@ class FB2MLizer(object):
|
|||||||
@return: List of string representing the XHTML converted to FB2 markup.
|
@return: List of string representing the XHTML converted to FB2 markup.
|
||||||
'''
|
'''
|
||||||
from calibre.ebooks.oeb.base import XHTML_NS, barename, namespace
|
from calibre.ebooks.oeb.base import XHTML_NS, barename, namespace
|
||||||
|
elem = elem_tree
|
||||||
|
|
||||||
# Ensure what we are converting is not a string and that the fist tag is part of the XHTML namespace.
|
# Ensure what we are converting is not a string and that the fist tag is part of the XHTML namespace.
|
||||||
if not isinstance(elem_tree.tag, basestring) or namespace(elem_tree.tag) != XHTML_NS:
|
if not isinstance(elem_tree.tag, basestring) or namespace(elem_tree.tag) != XHTML_NS:
|
||||||
|
p = elem.getparent()
|
||||||
|
if p is not None and isinstance(p.tag, basestring) and namespace(p.tag) == XHTML_NS \
|
||||||
|
and elem.tail:
|
||||||
|
return [elem.tail]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
style = stylizer.style(elem_tree)
|
style = stylizer.style(elem_tree)
|
||||||
if style['display'] in ('none', 'oeb-page-head', 'oeb-page-foot') or style['visibility'] == 'hidden':
|
if style['display'] in ('none', 'oeb-page-head', 'oeb-page-foot') \
|
||||||
|
or style['visibility'] == 'hidden':
|
||||||
|
if hasattr(elem, 'tail') and elem.tail:
|
||||||
|
return [elem.tail]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
# FB2 generated output.
|
# FB2 generated output.
|
||||||
|
@ -573,8 +573,13 @@ class Amazon(Source):
|
|||||||
else:
|
else:
|
||||||
url = 'http://www.amazon.%s/dp/%s'%(domain, asin)
|
url = 'http://www.amazon.%s/dp/%s'%(domain, asin)
|
||||||
if url:
|
if url:
|
||||||
idtype = 'amazon' if self.domain == 'com' else 'amazon_'+self.domain
|
idtype = 'amazon' if domain == 'com' else 'amazon_'+domain
|
||||||
return (idtype, asin, url)
|
return (idtype, asin, url)
|
||||||
|
|
||||||
|
def get_book_url_name(self, idtype, idval, url):
|
||||||
|
if idtype == 'amazon':
|
||||||
|
return self.name
|
||||||
|
return 'A' + idtype.replace('_', '.')[1:]
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -443,6 +443,12 @@ class Source(Plugin):
|
|||||||
'''
|
'''
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def get_book_url_name(self, idtype, idval, url):
|
||||||
|
'''
|
||||||
|
Return a human readable name from the return value of get_book_url().
|
||||||
|
'''
|
||||||
|
return self.name
|
||||||
|
|
||||||
def get_cached_cover_url(self, identifiers):
|
def get_cached_cover_url(self, identifiers):
|
||||||
'''
|
'''
|
||||||
Return cached cover URL for the book identified by
|
Return cached cover URL for the book identified by
|
||||||
|
@ -517,7 +517,7 @@ def urls_from_identifiers(identifiers): # {{{
|
|||||||
for plugin in all_metadata_plugins():
|
for plugin in all_metadata_plugins():
|
||||||
try:
|
try:
|
||||||
id_type, id_val, url = plugin.get_book_url(identifiers)
|
id_type, id_val, url = plugin.get_book_url(identifiers)
|
||||||
ans.append((plugin.name, id_type, id_val, url))
|
ans.append((plugin.get_book_url_name(id_type, id_val, url), id_type, id_val, url))
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
isbn = identifiers.get('isbn', None)
|
isbn = identifiers.get('isbn', None)
|
||||||
|
@ -26,16 +26,54 @@ class PagedDisplay
|
|||||||
this.current_margin_side = 0
|
this.current_margin_side = 0
|
||||||
this.is_full_screen_layout = false
|
this.is_full_screen_layout = false
|
||||||
this.max_col_width = -1
|
this.max_col_width = -1
|
||||||
|
this.document_margins = null
|
||||||
|
this.use_document_margins = false
|
||||||
|
|
||||||
|
read_document_margins: () ->
|
||||||
|
# Read page margins from the document. First checks for an @page rule.
|
||||||
|
# If that is not found, side margins are set to the side margins of the
|
||||||
|
# body element.
|
||||||
|
if this.document_margins is null
|
||||||
|
this.document_margins = {left:null, top:null, right:null, bottom:null}
|
||||||
|
tmp = document.createElement('div')
|
||||||
|
tmp.style.visibility = 'hidden'
|
||||||
|
tmp.style.position = 'absolute'
|
||||||
|
document.body.appendChild(tmp)
|
||||||
|
for sheet in document.styleSheets
|
||||||
|
for rule in sheet.rules
|
||||||
|
if rule.type == CSSRule.PAGE_RULE
|
||||||
|
for prop in ['left', 'top', 'bottom', 'right']
|
||||||
|
val = rule.style.getPropertyValue('margin-'+prop)
|
||||||
|
if val
|
||||||
|
tmp.style.height = val
|
||||||
|
pxval = parseInt(window.getComputedStyle(tmp).height)
|
||||||
|
if not isNaN(pxval)
|
||||||
|
this.document_margins[prop] = pxval
|
||||||
|
document.body.removeChild(tmp)
|
||||||
|
if this.document_margins.left is null
|
||||||
|
val = parseInt(window.getComputedStyle(document.body).marginLeft)
|
||||||
|
if not isNaN(val)
|
||||||
|
this.document_margins.left = val
|
||||||
|
if this.document_margins.right is null
|
||||||
|
val = parseInt(window.getComputedStyle(document.body).marginRight)
|
||||||
|
if not isNaN(val)
|
||||||
|
this.document_margins.right = val
|
||||||
|
|
||||||
set_geometry: (cols_per_screen=1, margin_top=20, margin_side=40, margin_bottom=20) ->
|
set_geometry: (cols_per_screen=1, margin_top=20, margin_side=40, margin_bottom=20) ->
|
||||||
this.margin_top = margin_top
|
|
||||||
this.margin_side = margin_side
|
|
||||||
this.margin_bottom = margin_bottom
|
|
||||||
this.cols_per_screen = cols_per_screen
|
this.cols_per_screen = cols_per_screen
|
||||||
|
if this.use_document_margins and this.document_margins != null
|
||||||
|
this.margin_top = this.document_margins.top or margin_top
|
||||||
|
this.margin_bottom = this.document_margins.bottom or margin_bottom
|
||||||
|
this.margin_side = this.document_margins.left or this.document_margins.right or margin_side
|
||||||
|
else
|
||||||
|
this.margin_top = margin_top
|
||||||
|
this.margin_side = margin_side
|
||||||
|
this.margin_bottom = margin_bottom
|
||||||
|
|
||||||
layout: () ->
|
layout: () ->
|
||||||
# start_time = new Date().getTime()
|
# start_time = new Date().getTime()
|
||||||
body_style = window.getComputedStyle(document.body)
|
body_style = window.getComputedStyle(document.body)
|
||||||
|
bs = document.body.style
|
||||||
# When laying body out in columns, webkit bleeds the top margin of the
|
# When laying body out in columns, webkit bleeds the top margin of the
|
||||||
# first block element out above the columns, leading to an extra top
|
# first block element out above the columns, leading to an extra top
|
||||||
# margin for the page. We compensate for that here. Computing the
|
# margin for the page. We compensate for that here. Computing the
|
||||||
@ -43,8 +81,10 @@ class PagedDisplay
|
|||||||
# it before the column layout is applied.
|
# it before the column layout is applied.
|
||||||
first_layout = false
|
first_layout = false
|
||||||
if not this.in_paged_mode
|
if not this.in_paged_mode
|
||||||
document.body.style.marginTop = '0px'
|
bs.setProperty('margin-top', '0px')
|
||||||
extra_margin = document.body.getBoundingClientRect().top
|
extra_margin = document.body.getBoundingClientRect().top
|
||||||
|
if extra_margin <= this.margin_top
|
||||||
|
extra_margin = 0
|
||||||
margin_top = (this.margin_top - extra_margin) + 'px'
|
margin_top = (this.margin_top - extra_margin) + 'px'
|
||||||
# Check if the current document is a full screen layout like
|
# Check if the current document is a full screen layout like
|
||||||
# cover, if so we treat it specially.
|
# cover, if so we treat it specially.
|
||||||
@ -78,7 +118,6 @@ class PagedDisplay
|
|||||||
this.screen_width = this.page_width * this.cols_per_screen
|
this.screen_width = this.page_width * this.cols_per_screen
|
||||||
|
|
||||||
fgcolor = body_style.getPropertyValue('color')
|
fgcolor = body_style.getPropertyValue('color')
|
||||||
bs = document.body.style
|
|
||||||
|
|
||||||
bs.setProperty('-webkit-column-gap', (2*sm)+'px')
|
bs.setProperty('-webkit-column-gap', (2*sm)+'px')
|
||||||
bs.setProperty('-webkit-column-width', col_width+'px')
|
bs.setProperty('-webkit-column-width', col_width+'px')
|
||||||
@ -101,7 +140,7 @@ class PagedDisplay
|
|||||||
# Convert page-breaks to column-breaks
|
# Convert page-breaks to column-breaks
|
||||||
for sheet in document.styleSheets
|
for sheet in document.styleSheets
|
||||||
for rule in sheet.rules
|
for rule in sheet.rules
|
||||||
if rule.type == 1 # CSSStyleRule
|
if rule.type == CSSRule.STYLE_RULE
|
||||||
for prop in ['page-break-before', 'page-break-after', 'page-break-inside']
|
for prop in ['page-break-before', 'page-break-after', 'page-break-inside']
|
||||||
val = rule.style.getPropertyValue(prop)
|
val = rule.style.getPropertyValue(prop)
|
||||||
if val
|
if val
|
||||||
@ -144,6 +183,19 @@ class PagedDisplay
|
|||||||
img.style.setProperty('max-width', max_width+'px')
|
img.style.setProperty('max-width', max_width+'px')
|
||||||
calibre_utils.store(img, 'width-limited', true)
|
calibre_utils.store(img, 'width-limited', true)
|
||||||
|
|
||||||
|
check_top_margin: () ->
|
||||||
|
# This is needed to handle the case when a descendant of body specifies
|
||||||
|
# a top margin as a percentage, which messes up the top margin
|
||||||
|
# calculations above
|
||||||
|
tm = document.body.getBoundingClientRect().top
|
||||||
|
if tm != this.margin_top
|
||||||
|
document.body.style.setProperty('margin-top', '0px')
|
||||||
|
tm = document.body.getBoundingClientRect().top
|
||||||
|
if tm <= this.margin_top
|
||||||
|
tm = 0
|
||||||
|
m = this.margin_top - tm
|
||||||
|
document.body.style.setProperty('margin-top', m+'px')
|
||||||
|
|
||||||
scroll_to_pos: (frac) ->
|
scroll_to_pos: (frac) ->
|
||||||
# Scroll to the position represented by frac (number between 0 and 1)
|
# Scroll to the position represented by frac (number between 0 and 1)
|
||||||
xpos = Math.floor(document.body.scrollWidth * frac)
|
xpos = Math.floor(document.body.scrollWidth * frac)
|
||||||
@ -348,4 +400,3 @@ if window?
|
|||||||
|
|
||||||
# TODO:
|
# TODO:
|
||||||
# Highlight on jump_to_anchor
|
# Highlight on jump_to_anchor
|
||||||
# Handle document specified margins and allow them to be overridden
|
|
||||||
|
@ -82,7 +82,7 @@ class Split(object):
|
|||||||
after = getattr(rule.style.getPropertyCSSValue(
|
after = getattr(rule.style.getPropertyCSSValue(
|
||||||
'page-break-after'), 'cssText', '').strip().lower()
|
'page-break-after'), 'cssText', '').strip().lower()
|
||||||
try:
|
try:
|
||||||
if before and before != 'avoid':
|
if before and before not in {'avoid', 'auto', 'inherit'}:
|
||||||
self.page_break_selectors.add((CSSSelector(rule.selectorText),
|
self.page_break_selectors.add((CSSSelector(rule.selectorText),
|
||||||
True))
|
True))
|
||||||
if self.remove_css_pagebreaks:
|
if self.remove_css_pagebreaks:
|
||||||
@ -90,7 +90,7 @@ class Split(object):
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
try:
|
try:
|
||||||
if after and after != 'avoid':
|
if after and after not in {'avoid', 'auto', 'inherit'}:
|
||||||
self.page_break_selectors.add((CSSSelector(rule.selectorText),
|
self.page_break_selectors.add((CSSSelector(rule.selectorText),
|
||||||
False))
|
False))
|
||||||
if self.remove_css_pagebreaks:
|
if self.remove_css_pagebreaks:
|
||||||
|
@ -202,6 +202,7 @@ class PDFWriter(QObject): # {{{
|
|||||||
paged_display.set_geometry(1, 0, 0, 0);
|
paged_display.set_geometry(1, 0, 0, 0);
|
||||||
paged_display.layout();
|
paged_display.layout();
|
||||||
paged_display.fit_images();
|
paged_display.fit_images();
|
||||||
|
paged_display.check_top_margin();
|
||||||
''')
|
''')
|
||||||
mf = self.view.page().mainFrame()
|
mf = self.view.page().mainFrame()
|
||||||
while True:
|
while True:
|
||||||
|
@ -220,8 +220,11 @@ class PMLMLizer(object):
|
|||||||
def dump_text(self, elem, stylizer, page, tag_stack=[]):
|
def dump_text(self, elem, stylizer, page, tag_stack=[]):
|
||||||
from calibre.ebooks.oeb.base import XHTML_NS, barename, namespace
|
from calibre.ebooks.oeb.base import XHTML_NS, barename, namespace
|
||||||
|
|
||||||
if not isinstance(elem.tag, basestring) \
|
if not isinstance(elem.tag, basestring) or namespace(elem.tag) != XHTML_NS:
|
||||||
or namespace(elem.tag) != XHTML_NS:
|
p = elem.getparent()
|
||||||
|
if p is not None and isinstance(p.tag, basestring) and namespace(p.tag) == XHTML_NS \
|
||||||
|
and elem.tail:
|
||||||
|
return [elem.tail]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
text = []
|
text = []
|
||||||
@ -230,6 +233,8 @@ class PMLMLizer(object):
|
|||||||
|
|
||||||
if style['display'] in ('none', 'oeb-page-head', 'oeb-page-foot') \
|
if style['display'] in ('none', 'oeb-page-head', 'oeb-page-foot') \
|
||||||
or style['visibility'] == 'hidden':
|
or style['visibility'] == 'hidden':
|
||||||
|
if hasattr(elem, 'tail') and elem.tail:
|
||||||
|
return [elem.tail]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
tag = barename(elem.tag)
|
tag = barename(elem.tag)
|
||||||
|
@ -142,8 +142,11 @@ class RBMLizer(object):
|
|||||||
def dump_text(self, elem, stylizer, page, tag_stack=[]):
|
def dump_text(self, elem, stylizer, page, tag_stack=[]):
|
||||||
from calibre.ebooks.oeb.base import XHTML_NS, barename, namespace
|
from calibre.ebooks.oeb.base import XHTML_NS, barename, namespace
|
||||||
|
|
||||||
if not isinstance(elem.tag, basestring) \
|
if not isinstance(elem.tag, basestring) or namespace(elem.tag) != XHTML_NS:
|
||||||
or namespace(elem.tag) != XHTML_NS:
|
p = elem.getparent()
|
||||||
|
if p is not None and isinstance(p.tag, basestring) and namespace(p.tag) == XHTML_NS \
|
||||||
|
and elem.tail:
|
||||||
|
return [elem.tail]
|
||||||
return [u'']
|
return [u'']
|
||||||
|
|
||||||
text = [u'']
|
text = [u'']
|
||||||
@ -151,6 +154,8 @@ class RBMLizer(object):
|
|||||||
|
|
||||||
if style['display'] in ('none', 'oeb-page-head', 'oeb-page-foot') \
|
if style['display'] in ('none', 'oeb-page-head', 'oeb-page-foot') \
|
||||||
or style['visibility'] == 'hidden':
|
or style['visibility'] == 'hidden':
|
||||||
|
if hasattr(elem, 'tail') and elem.tail:
|
||||||
|
return [elem.tail]
|
||||||
return [u'']
|
return [u'']
|
||||||
|
|
||||||
tag = barename(elem.tag)
|
tag = barename(elem.tag)
|
||||||
|
@ -229,6 +229,8 @@ class RTFMLizer(object):
|
|||||||
|
|
||||||
if style['display'] in ('none', 'oeb-page-head', 'oeb-page-foot') \
|
if style['display'] in ('none', 'oeb-page-head', 'oeb-page-foot') \
|
||||||
or style['visibility'] == 'hidden':
|
or style['visibility'] == 'hidden':
|
||||||
|
if hasattr(elem, 'tail') and elem.tail:
|
||||||
|
return elem.tail
|
||||||
return u''
|
return u''
|
||||||
|
|
||||||
tag = barename(elem.tag)
|
tag = barename(elem.tag)
|
||||||
|
@ -212,6 +212,10 @@ class SNBMLizer(object):
|
|||||||
|
|
||||||
if not isinstance(elem.tag, basestring) \
|
if not isinstance(elem.tag, basestring) \
|
||||||
or namespace(elem.tag) != XHTML_NS:
|
or namespace(elem.tag) != XHTML_NS:
|
||||||
|
p = elem.getparent()
|
||||||
|
if p is not None and isinstance(p.tag, basestring) and namespace(p.tag) == XHTML_NS \
|
||||||
|
and elem.tail:
|
||||||
|
return [elem.tail]
|
||||||
return ['']
|
return ['']
|
||||||
|
|
||||||
|
|
||||||
@ -225,6 +229,8 @@ class SNBMLizer(object):
|
|||||||
|
|
||||||
if style['display'] in ('none', 'oeb-page-head', 'oeb-page-foot') \
|
if style['display'] in ('none', 'oeb-page-head', 'oeb-page-foot') \
|
||||||
or style['visibility'] == 'hidden':
|
or style['visibility'] == 'hidden':
|
||||||
|
if hasattr(elem, 'tail') and elem.tail:
|
||||||
|
return [elem.tail]
|
||||||
return ['']
|
return ['']
|
||||||
|
|
||||||
tag = barename(elem.tag)
|
tag = barename(elem.tag)
|
||||||
|
@ -127,6 +127,8 @@ class MarkdownMLizer(OEB2HTML):
|
|||||||
# Ignore anything that is set to not be displayed.
|
# Ignore anything that is set to not be displayed.
|
||||||
if style['display'] in ('none', 'oeb-page-head', 'oeb-page-foot') \
|
if style['display'] in ('none', 'oeb-page-head', 'oeb-page-foot') \
|
||||||
or style['visibility'] == 'hidden':
|
or style['visibility'] == 'hidden':
|
||||||
|
if hasattr(elem, 'tail') and elem.tail:
|
||||||
|
return [elem.tail]
|
||||||
return ['']
|
return ['']
|
||||||
|
|
||||||
# Soft scene breaks.
|
# Soft scene breaks.
|
||||||
|
@ -241,6 +241,8 @@ class TextileMLizer(OEB2HTML):
|
|||||||
# Ignore anything that is set to not be displayed.
|
# Ignore anything that is set to not be displayed.
|
||||||
if style['display'] in ('none', 'oeb-page-head', 'oeb-page-foot') \
|
if style['display'] in ('none', 'oeb-page-head', 'oeb-page-foot') \
|
||||||
or style['visibility'] == 'hidden':
|
or style['visibility'] == 'hidden':
|
||||||
|
if hasattr(elem, 'tail') and elem.tail:
|
||||||
|
return [elem.tail]
|
||||||
return ['']
|
return ['']
|
||||||
|
|
||||||
# Soft scene breaks.
|
# Soft scene breaks.
|
||||||
|
@ -200,6 +200,8 @@ class TXTMLizer(object):
|
|||||||
|
|
||||||
if style['display'] in ('none', 'oeb-page-head', 'oeb-page-foot') \
|
if style['display'] in ('none', 'oeb-page-head', 'oeb-page-foot') \
|
||||||
or style['visibility'] == 'hidden':
|
or style['visibility'] == 'hidden':
|
||||||
|
if hasattr(elem, 'tail') and elem.tail:
|
||||||
|
return [elem.tail]
|
||||||
return ['']
|
return ['']
|
||||||
|
|
||||||
tag = barename(elem.tag)
|
tag = barename(elem.tag)
|
||||||
|
@ -139,6 +139,21 @@ class DeleteAction(InterfaceAction):
|
|||||||
return set([])
|
return set([])
|
||||||
return set(map(self.gui.library_view.model().id, rows))
|
return set(map(self.gui.library_view.model().id, rows))
|
||||||
|
|
||||||
|
def remove_format_by_id(self, book_id, fmt):
|
||||||
|
title = self.gui.current_db.title(book_id, index_is_id=True)
|
||||||
|
if not confirm('<p>'+(_(
|
||||||
|
'The %(fmt)s format will be <b>permanently deleted</b> from '
|
||||||
|
'%(title)s. Are you sure?')%dict(fmt=fmt, title=title))
|
||||||
|
+'</p>', 'library_delete_specific_format', self.gui):
|
||||||
|
return
|
||||||
|
|
||||||
|
self.gui.library_view.model().db.remove_format(book_id, fmt,
|
||||||
|
index_is_id=True, notify=False)
|
||||||
|
self.gui.library_view.model().refresh_ids([book_id])
|
||||||
|
self.gui.library_view.model().current_changed(self.gui.library_view.currentIndex(),
|
||||||
|
self.gui.library_view.currentIndex())
|
||||||
|
self.gui.tags_view.recount()
|
||||||
|
|
||||||
def delete_selected_formats(self, *args):
|
def delete_selected_formats(self, *args):
|
||||||
ids = self._get_selected_ids()
|
ids = self._get_selected_ids()
|
||||||
if not ids:
|
if not ids:
|
||||||
|
@ -5,8 +5,8 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
from PyQt4.Qt import (QPixmap, QSize, QWidget, Qt, pyqtSignal, QUrl,
|
from PyQt4.Qt import (QPixmap, QSize, QWidget, Qt, pyqtSignal, QUrl, QIcon,
|
||||||
QPropertyAnimation, QEasingCurve, QApplication, QFontInfo,
|
QPropertyAnimation, QEasingCurve, QApplication, QFontInfo, QAction,
|
||||||
QSizePolicy, QPainter, QRect, pyqtProperty, QLayout, QPalette, QMenu)
|
QSizePolicy, QPainter, QRect, pyqtProperty, QLayout, QPalette, QMenu)
|
||||||
from PyQt4.QtWebKit import QWebView
|
from PyQt4.QtWebKit import QWebView
|
||||||
|
|
||||||
@ -382,6 +382,7 @@ class CoverView(QWidget): # {{{
|
|||||||
class BookInfo(QWebView):
|
class BookInfo(QWebView):
|
||||||
|
|
||||||
link_clicked = pyqtSignal(object)
|
link_clicked = pyqtSignal(object)
|
||||||
|
remove_format = pyqtSignal(int, object)
|
||||||
|
|
||||||
def __init__(self, vertical, parent=None):
|
def __init__(self, vertical, parent=None):
|
||||||
QWebView.__init__(self, parent)
|
QWebView.__init__(self, parent)
|
||||||
@ -395,6 +396,16 @@ class BookInfo(QWebView):
|
|||||||
palette.setBrush(QPalette.Base, Qt.transparent)
|
palette.setBrush(QPalette.Base, Qt.transparent)
|
||||||
self.page().setPalette(palette)
|
self.page().setPalette(palette)
|
||||||
self.css = P('templates/book_details.css', data=True).decode('utf-8')
|
self.css = P('templates/book_details.css', data=True).decode('utf-8')
|
||||||
|
self.remove_format_action = QAction(QIcon(I('trash.png')),
|
||||||
|
'', self)
|
||||||
|
self.remove_format_action.current_fmt = None
|
||||||
|
self.remove_format_action.triggered.connect(self.remove_format_triggerred)
|
||||||
|
|
||||||
|
def remove_format_triggerred(self):
|
||||||
|
f = self.remove_format_action.current_fmt
|
||||||
|
if f:
|
||||||
|
book_id, fmt = f
|
||||||
|
self.remove_format.emit(book_id, fmt)
|
||||||
|
|
||||||
def link_activated(self, link):
|
def link_activated(self, link):
|
||||||
self._link_clicked = True
|
self._link_clicked = True
|
||||||
@ -420,6 +431,32 @@ class BookInfo(QWebView):
|
|||||||
else:
|
else:
|
||||||
ev.ignore()
|
ev.ignore()
|
||||||
|
|
||||||
|
def contextMenuEvent(self, ev):
|
||||||
|
p = self.page()
|
||||||
|
mf = p.mainFrame()
|
||||||
|
r = mf.hitTestContent(ev.pos())
|
||||||
|
url = unicode(r.linkUrl().toString()).strip()
|
||||||
|
menu = p.createStandardContextMenu()
|
||||||
|
ca = self.pageAction(p.Copy)
|
||||||
|
for action in list(menu.actions()):
|
||||||
|
if action is not ca:
|
||||||
|
menu.removeAction(action)
|
||||||
|
if not r.isNull() and url.startswith('format:'):
|
||||||
|
parts = url.split(':')
|
||||||
|
try:
|
||||||
|
book_id, fmt = int(parts[1]), parts[2]
|
||||||
|
except:
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
else:
|
||||||
|
self.remove_format_action.current_fmt = (book_id, fmt)
|
||||||
|
self.remove_format_action.setText(_('Delete the %s format')%parts[
|
||||||
|
2])
|
||||||
|
menu.addAction(self.remove_format_action)
|
||||||
|
if len(menu.actions()) > 0:
|
||||||
|
menu.exec_(ev.globalPos())
|
||||||
|
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
class DetailsLayout(QLayout): # {{{
|
class DetailsLayout(QLayout): # {{{
|
||||||
@ -513,6 +550,7 @@ class BookDetails(QWidget): # {{{
|
|||||||
show_book_info = pyqtSignal()
|
show_book_info = pyqtSignal()
|
||||||
open_containing_folder = pyqtSignal(int)
|
open_containing_folder = pyqtSignal(int)
|
||||||
view_specific_format = pyqtSignal(int, object)
|
view_specific_format = pyqtSignal(int, object)
|
||||||
|
remove_specific_format = pyqtSignal(int, object)
|
||||||
remote_file_dropped = pyqtSignal(object, object)
|
remote_file_dropped = pyqtSignal(object, object)
|
||||||
files_dropped = pyqtSignal(object, object)
|
files_dropped = pyqtSignal(object, object)
|
||||||
cover_changed = pyqtSignal(object, object)
|
cover_changed = pyqtSignal(object, object)
|
||||||
@ -579,6 +617,7 @@ class BookDetails(QWidget): # {{{
|
|||||||
self.book_info = BookInfo(vertical, self)
|
self.book_info = BookInfo(vertical, self)
|
||||||
self._layout.addWidget(self.book_info)
|
self._layout.addWidget(self.book_info)
|
||||||
self.book_info.link_clicked.connect(self.handle_click)
|
self.book_info.link_clicked.connect(self.handle_click)
|
||||||
|
self.book_info.remove_format.connect(self.remove_specific_format)
|
||||||
self.setCursor(Qt.PointingHandCursor)
|
self.setCursor(Qt.PointingHandCursor)
|
||||||
|
|
||||||
def handle_click(self, link):
|
def handle_click(self, link):
|
||||||
|
@ -934,6 +934,11 @@ class DeviceMixin(object): # {{{
|
|||||||
|
|
||||||
fmt = None
|
fmt = None
|
||||||
if specific:
|
if specific:
|
||||||
|
if (not self.device_connected or not self.device_manager or
|
||||||
|
self.device_manager.device is None):
|
||||||
|
error_dialog(self, _('No device'),
|
||||||
|
_('No device connected'), show=True)
|
||||||
|
return
|
||||||
formats = []
|
formats = []
|
||||||
aval_out_formats = available_output_formats()
|
aval_out_formats = available_output_formats()
|
||||||
format_count = {}
|
format_count = {}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
<ui version="4.0" >
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
<class>Dialog</class>
|
<class>Dialog</class>
|
||||||
<widget class="QDialog" name="Dialog" >
|
<widget class="QDialog" name="Dialog">
|
||||||
<property name="geometry" >
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
@ -9,51 +10,63 @@
|
|||||||
<height>300</height>
|
<height>300</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle" >
|
<property name="windowTitle">
|
||||||
<string>Are you sure?</string>
|
<string>Are you sure?</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowIcon" >
|
<property name="windowIcon">
|
||||||
<iconset resource="../../../../resources/images.qrc" >
|
<iconset resource="../../../../resources/images.qrc">
|
||||||
<normaloff>:/images/dialog_warning.png</normaloff>:/images/dialog_warning.png</iconset>
|
<normaloff>:/images/dialog_warning.png</normaloff>:/images/dialog_warning.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout" >
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="0" column="0" >
|
<item row="0" column="0">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout" >
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label" >
|
<widget class="QLabel" name="label">
|
||||||
<property name="pixmap" >
|
<property name="pixmap">
|
||||||
<pixmap resource="../../../../resources/images.qrc" >:/images/dialog_warning.png</pixmap>
|
<pixmap resource="../../../../resources/images.qrc">:/images/dialog_warning.png</pixmap>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="msg" >
|
<widget class="QLabel" name="msg">
|
||||||
<property name="text" >
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>300</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
<string>TextLabel</string>
|
<string>TextLabel</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="wordWrap" >
|
<property name="wordWrap">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0" >
|
<item row="1" column="0">
|
||||||
<widget class="QCheckBox" name="again" >
|
<widget class="QCheckBox" name="again">
|
||||||
<property name="text" >
|
<property name="text">
|
||||||
<string>&Show this warning again</string>
|
<string>&Show this warning again</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="checked" >
|
<property name="checked">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0" >
|
<item row="2" column="0">
|
||||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
<property name="orientation" >
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="standardButtons" >
|
<property name="standardButtons">
|
||||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
@ -61,7 +74,7 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="../../../../resources/images.qrc" />
|
<include location="../../../../resources/images.qrc"/>
|
||||||
</resources>
|
</resources>
|
||||||
<connections>
|
<connections>
|
||||||
<connection>
|
<connection>
|
||||||
@ -70,11 +83,11 @@
|
|||||||
<receiver>Dialog</receiver>
|
<receiver>Dialog</receiver>
|
||||||
<slot>accept()</slot>
|
<slot>accept()</slot>
|
||||||
<hints>
|
<hints>
|
||||||
<hint type="sourcelabel" >
|
<hint type="sourcelabel">
|
||||||
<x>248</x>
|
<x>248</x>
|
||||||
<y>254</y>
|
<y>254</y>
|
||||||
</hint>
|
</hint>
|
||||||
<hint type="destinationlabel" >
|
<hint type="destinationlabel">
|
||||||
<x>157</x>
|
<x>157</x>
|
||||||
<y>274</y>
|
<y>274</y>
|
||||||
</hint>
|
</hint>
|
||||||
@ -86,11 +99,11 @@
|
|||||||
<receiver>Dialog</receiver>
|
<receiver>Dialog</receiver>
|
||||||
<slot>reject()</slot>
|
<slot>reject()</slot>
|
||||||
<hints>
|
<hints>
|
||||||
<hint type="sourcelabel" >
|
<hint type="sourcelabel">
|
||||||
<x>316</x>
|
<x>316</x>
|
||||||
<y>260</y>
|
<y>260</y>
|
||||||
</hint>
|
</hint>
|
||||||
<hint type="destinationlabel" >
|
<hint type="destinationlabel">
|
||||||
<x>286</x>
|
<x>286</x>
|
||||||
<y>274</y>
|
<y>274</y>
|
||||||
</hint>
|
</hint>
|
||||||
|
@ -370,6 +370,8 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog):
|
|||||||
geom = gprefs.get('bulk_metadata_window_geometry', None)
|
geom = gprefs.get('bulk_metadata_window_geometry', None)
|
||||||
if geom is not None:
|
if geom is not None:
|
||||||
self.restoreGeometry(bytes(geom))
|
self.restoreGeometry(bytes(geom))
|
||||||
|
ct = gprefs.get('bulk_metadata_window_tab', 0)
|
||||||
|
self.central_widget.setCurrentIndex(ct)
|
||||||
self.languages.init_langs(self.db)
|
self.languages.init_langs(self.db)
|
||||||
self.languages.setEditText('')
|
self.languages.setEditText('')
|
||||||
self.authors.setFocus(Qt.OtherFocusReason)
|
self.authors.setFocus(Qt.OtherFocusReason)
|
||||||
@ -378,6 +380,7 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog):
|
|||||||
def save_state(self, *args):
|
def save_state(self, *args):
|
||||||
gprefs['bulk_metadata_window_geometry'] = \
|
gprefs['bulk_metadata_window_geometry'] = \
|
||||||
bytearray(self.saveGeometry())
|
bytearray(self.saveGeometry())
|
||||||
|
gprefs['bulk_metadata_window_tab'] = self.central_widget.currentIndex()
|
||||||
|
|
||||||
def do_apply_pubdate(self, *args):
|
def do_apply_pubdate(self, *args):
|
||||||
self.apply_pubdate.setChecked(True)
|
self.apply_pubdate.setChecked(True)
|
||||||
|
@ -265,6 +265,8 @@ class LayoutMixin(object): # {{{
|
|||||||
type=Qt.QueuedConnection)
|
type=Qt.QueuedConnection)
|
||||||
self.book_details.open_containing_folder.connect(self.iactions['View'].view_folder_for_id)
|
self.book_details.open_containing_folder.connect(self.iactions['View'].view_folder_for_id)
|
||||||
self.book_details.view_specific_format.connect(self.iactions['View'].view_format_by_id)
|
self.book_details.view_specific_format.connect(self.iactions['View'].view_format_by_id)
|
||||||
|
self.book_details.remove_specific_format.connect(
|
||||||
|
self.iactions['Remove Books'].remove_format_by_id)
|
||||||
|
|
||||||
m = self.library_view.model()
|
m = self.library_view.model()
|
||||||
if m.rowCount(None) > 0:
|
if m.rowCount(None) > 0:
|
||||||
|
@ -53,6 +53,11 @@ def config(defaults=None):
|
|||||||
'0 and 1.'))
|
'0 and 1.'))
|
||||||
c.add_opt('fullscreen_clock', default=False, action='store_true',
|
c.add_opt('fullscreen_clock', default=False, action='store_true',
|
||||||
help=_('Show a clock in fullscreen mode.'))
|
help=_('Show a clock in fullscreen mode.'))
|
||||||
|
c.add_opt('cols_per_screen', default=1)
|
||||||
|
c.add_opt('use_book_margins', default=False, action='store_true')
|
||||||
|
c.add_opt('top_margin', default=20)
|
||||||
|
c.add_opt('side_margin', default=40)
|
||||||
|
c.add_opt('bottom_margin', default=20)
|
||||||
|
|
||||||
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',
|
||||||
@ -120,6 +125,11 @@ class ConfigDialog(QDialog, Ui_Dialog):
|
|||||||
self.hyphenate_default_lang.setVisible(False)
|
self.hyphenate_default_lang.setVisible(False)
|
||||||
self.hyphenate_label.setVisible(False)
|
self.hyphenate_label.setVisible(False)
|
||||||
self.opt_fullscreen_clock.setChecked(opts.fullscreen_clock)
|
self.opt_fullscreen_clock.setChecked(opts.fullscreen_clock)
|
||||||
|
self.opt_cols_per_screen.setValue(opts.cols_per_screen)
|
||||||
|
self.opt_override_book_margins.setChecked(not opts.use_book_margins)
|
||||||
|
for x in ('top', 'bottom', 'side'):
|
||||||
|
getattr(self, 'opt_%s_margin'%x).setValue(getattr(opts,
|
||||||
|
x+'_margin'))
|
||||||
|
|
||||||
def accept(self, *args):
|
def accept(self, *args):
|
||||||
if self.shortcut_config.is_editing:
|
if self.shortcut_config.is_editing:
|
||||||
@ -152,6 +162,11 @@ class ConfigDialog(QDialog, Ui_Dialog):
|
|||||||
c.set('line_scrolling_stops_on_pagebreaks',
|
c.set('line_scrolling_stops_on_pagebreaks',
|
||||||
self.opt_line_scrolling_stops_on_pagebreaks.isChecked())
|
self.opt_line_scrolling_stops_on_pagebreaks.isChecked())
|
||||||
c.set('fullscreen_clock', self.opt_fullscreen_clock.isChecked())
|
c.set('fullscreen_clock', self.opt_fullscreen_clock.isChecked())
|
||||||
|
c.set('cols_per_screen', int(self.opt_cols_per_screen.value()))
|
||||||
|
c.set('use_book_margins', not
|
||||||
|
self.opt_override_book_margins.isChecked())
|
||||||
|
for x in ('top', 'bottom', 'side'):
|
||||||
|
c.set(x+'_margin', int(getattr(self, 'opt_%s_margin'%x).value()))
|
||||||
return QDialog.accept(self, *args)
|
return QDialog.accept(self, *args)
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,16 +18,6 @@
|
|||||||
<normaloff>:/images/config.png</normaloff>:/images/config.png</iconset>
|
<normaloff>:/images/config.png</normaloff>:/images/config.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_4">
|
<layout class="QGridLayout" name="gridLayout_4">
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="standardButtons">
|
|
||||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QTabWidget" name="tabs">
|
<widget class="QTabWidget" name="tabs">
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
@ -39,283 +29,482 @@
|
|||||||
</attribute>
|
</attribute>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="groupBox">
|
<widget class="QToolBox" name="toolBox">
|
||||||
<property name="title">
|
<property name="styleSheet">
|
||||||
<string>&Font options</string>
|
<string notr="true">QToolBox::tab {
|
||||||
|
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
|
||||||
|
stop: 0 #E1E1E1, stop: 0.4 #DDDDDD,
|
||||||
|
stop: 0.5 #D8D8D8, stop: 1.0 #D3D3D3);
|
||||||
|
border-radius: 5px;
|
||||||
|
color: black;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
QToolBox::tab:selected {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
QToolBox::tab:hover {
|
||||||
|
color: red;
|
||||||
|
font-style: italic;
|
||||||
|
}</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_3">
|
<property name="currentIndex">
|
||||||
<item row="0" column="0">
|
<number>0</number>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
</property>
|
||||||
<item row="0" column="0">
|
<widget class="QWidget" name="page">
|
||||||
<widget class="QLabel" name="label">
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>811</width>
|
||||||
|
<height>384</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<attribute name="label">
|
||||||
|
<string>&Font options</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QFormLayout" name="formLayout_2">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Se&rif family:</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>serif_family</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QFontComboBox" name="serif_family"/>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>&Sans family:</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>sans_family</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QFontComboBox" name="sans_family"/>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>&Monospace family:</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>mono_family</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QFontComboBox" name="mono_family"/>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>&Default font size:</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>default_font_size</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QSpinBox" name="default_font_size">
|
||||||
|
<property name="suffix">
|
||||||
|
<string> px</string>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>8</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>40</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="text">
|
||||||
|
<string>Monospace &font size:</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>mono_font_size</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QSpinBox" name="mono_font_size">
|
||||||
|
<property name="suffix">
|
||||||
|
<string> px</string>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>8</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>50</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="text">
|
||||||
|
<string>S&tandard font:</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>standard_font</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<widget class="QComboBox" name="standard_font">
|
||||||
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Se&rif family:</string>
|
<string>Serif</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="buddy">
|
</item>
|
||||||
<cstring>serif_family</cstring>
|
<item>
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QFontComboBox" name="serif_family"/>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label_2">
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Sans family:</string>
|
<string>Sans-serif</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="buddy">
|
</item>
|
||||||
<cstring>sans_family</cstring>
|
<item>
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QFontComboBox" name="sans_family"/>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="label_3">
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Monospace family:</string>
|
<string>Monospace</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="buddy">
|
</item>
|
||||||
<cstring>mono_family</cstring>
|
</widget>
|
||||||
</property>
|
</item>
|
||||||
</widget>
|
<item row="6" column="0">
|
||||||
</item>
|
<widget class="QLabel" name="label_12">
|
||||||
<item row="2" column="1">
|
<property name="text">
|
||||||
<widget class="QFontComboBox" name="mono_family"/>
|
<string>Font &magnification step size:</string>
|
||||||
</item>
|
</property>
|
||||||
<item row="3" column="0">
|
<property name="buddy">
|
||||||
<widget class="QLabel" name="label_4">
|
<cstring>opt_font_mag_step</cstring>
|
||||||
<property name="text">
|
</property>
|
||||||
<string>&Default font size:</string>
|
</widget>
|
||||||
</property>
|
</item>
|
||||||
<property name="buddy">
|
<item row="6" column="1">
|
||||||
<cstring>default_font_size</cstring>
|
<widget class="QSpinBox" name="opt_font_mag_step">
|
||||||
</property>
|
<property name="toolTip">
|
||||||
</widget>
|
<string>The amount by which the font size is increased/decreased
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="QSpinBox" name="default_font_size">
|
|
||||||
<property name="suffix">
|
|
||||||
<string> px</string>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<number>8</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>40</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0">
|
|
||||||
<widget class="QLabel" name="label_5">
|
|
||||||
<property name="text">
|
|
||||||
<string>Monospace &font size:</string>
|
|
||||||
</property>
|
|
||||||
<property name="buddy">
|
|
||||||
<cstring>mono_font_size</cstring>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1">
|
|
||||||
<widget class="QSpinBox" name="mono_font_size">
|
|
||||||
<property name="suffix">
|
|
||||||
<string> px</string>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<number>8</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>50</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="0">
|
|
||||||
<widget class="QLabel" name="label_6">
|
|
||||||
<property name="text">
|
|
||||||
<string>S&tandard font:</string>
|
|
||||||
</property>
|
|
||||||
<property name="buddy">
|
|
||||||
<cstring>standard_font</cstring>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="1">
|
|
||||||
<widget class="QComboBox" name="standard_font">
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Serif</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Sans-serif</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Monospace</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
|
||||||
<item row="5" column="0" colspan="2">
|
|
||||||
<widget class="QCheckBox" name="hyphenate">
|
|
||||||
<property name="text">
|
|
||||||
<string>H&yphenate (break line in the middle of large words)</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="1">
|
|
||||||
<widget class="QComboBox" name="hyphenate_default_lang">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>The default language to use for hyphenation rules. If the book does not specify a language, this will be used.</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="0">
|
|
||||||
<widget class="QLabel" name="hyphenate_label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Default &language for hyphenation:</string>
|
|
||||||
</property>
|
|
||||||
<property name="buddy">
|
|
||||||
<cstring>hyphenate_default_lang</cstring>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0">
|
|
||||||
<widget class="QLabel" name="label_11">
|
|
||||||
<property name="text">
|
|
||||||
<string>Page flip &duration:</string>
|
|
||||||
</property>
|
|
||||||
<property name="buddy">
|
|
||||||
<cstring>opt_page_flip_duration</cstring>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1">
|
|
||||||
<widget class="QDoubleSpinBox" name="opt_page_flip_duration">
|
|
||||||
<property name="specialValueText">
|
|
||||||
<string>disabled</string>
|
|
||||||
</property>
|
|
||||||
<property name="suffix">
|
|
||||||
<string> secs</string>
|
|
||||||
</property>
|
|
||||||
<property name="decimals">
|
|
||||||
<number>1</number>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<double>0.100000000000000</double>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<double>3.000000000000000</double>
|
|
||||||
</property>
|
|
||||||
<property name="singleStep">
|
|
||||||
<double>0.100000000000000</double>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<double>0.500000000000000</double>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<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">
|
|
||||||
<string> px</string>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<number>100</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>10000</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QLabel" name="label_7">
|
|
||||||
<property name="text">
|
|
||||||
<string>Maximum text width in &fullscreen:</string>
|
|
||||||
</property>
|
|
||||||
<property name="buddy">
|
|
||||||
<cstring>max_fs_width</cstring>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label_12">
|
|
||||||
<property name="text">
|
|
||||||
<string>Font &magnification step size:</string>
|
|
||||||
</property>
|
|
||||||
<property name="buddy">
|
|
||||||
<cstring>opt_font_mag_step</cstring>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QSpinBox" name="opt_font_mag_step">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>The amount by which the font size is increased/decreased
|
|
||||||
when you click the font size larger/smaller buttons</string>
|
when you click the font size larger/smaller buttons</string>
|
||||||
|
</property>
|
||||||
|
<property name="suffix">
|
||||||
|
<string>%</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="page_5">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>811</width>
|
||||||
|
<height>384</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<attribute name="label">
|
||||||
|
<string>Text &layout in paged mode</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QFormLayout" name="formLayout_5">
|
||||||
|
<property name="fieldGrowthPolicy">
|
||||||
|
<enum>QFormLayout::ExpandingFieldsGrow</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="suffix">
|
<item row="0" column="0" colspan="2">
|
||||||
<string>%</string>
|
<widget class="QLabel" name="label_8">
|
||||||
</property>
|
<property name="text">
|
||||||
</widget>
|
<string><p>These options only apply in "paged" mode, where the text is broken up into pages, as in a paper book. To get into this mode, use the button with the yellow scroll icon in the top right corner of the viewer window.</string>
|
||||||
</item>
|
</property>
|
||||||
<item row="7" column="0">
|
<property name="wordWrap">
|
||||||
<widget class="QCheckBox" name="opt_fit_images">
|
<bool>true</bool>
|
||||||
<property name="text">
|
</property>
|
||||||
<string>&Resize images larger than the viewer window (needs restart)</string>
|
</widget>
|
||||||
</property>
|
</item>
|
||||||
</widget>
|
<item row="1" column="0">
|
||||||
</item>
|
<widget class="QLabel" name="label_13">
|
||||||
<item row="8" column="0">
|
<property name="text">
|
||||||
<widget class="QCheckBox" name="opt_remember_window_size">
|
<string>The number of &pages of text to show on screen </string>
|
||||||
<property name="text">
|
</property>
|
||||||
<string>Remember last used &window size and layout</string>
|
<property name="buddy">
|
||||||
</property>
|
<cstring>opt_cols_per_screen</cstring>
|
||||||
</widget>
|
</property>
|
||||||
</item>
|
</widget>
|
||||||
<item row="7" column="1">
|
</item>
|
||||||
<widget class="QCheckBox" name="opt_wheel_flips_pages">
|
<item row="1" column="1">
|
||||||
<property name="text">
|
<widget class="QSpinBox" name="opt_cols_per_screen">
|
||||||
<string>Mouse &wheel flips pages</string>
|
<property name="suffix">
|
||||||
</property>
|
<string> page(s)</string>
|
||||||
</widget>
|
</property>
|
||||||
</item>
|
<property name="minimum">
|
||||||
<item row="8" column="1">
|
<number>1</number>
|
||||||
<widget class="QCheckBox" name="opt_remember_current_page">
|
</property>
|
||||||
<property name="text">
|
<property name="maximum">
|
||||||
<string>Remember the &current page when quitting</string>
|
<number>5</number>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="9" column="0">
|
<item row="2" column="0" colspan="2">
|
||||||
<widget class="QCheckBox" name="opt_line_scrolling_stops_on_pagebreaks">
|
<widget class="QCheckBox" name="opt_override_book_margins">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Line &scrolling stops at page breaks</string>
|
<string>&Override the page margin settings specified in the book</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
<property name="checked">
|
||||||
</item>
|
<bool>true</bool>
|
||||||
<item row="9" column="1">
|
</property>
|
||||||
<widget class="QCheckBox" name="opt_fullscreen_clock">
|
</widget>
|
||||||
<property name="text">
|
</item>
|
||||||
<string>Show &clock in full screen mode</string>
|
<item row="3" column="0">
|
||||||
</property>
|
<widget class="QLabel" name="label_18">
|
||||||
</widget>
|
<property name="text">
|
||||||
</item>
|
<string>&Top margin</string>
|
||||||
</layout>
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>opt_top_margin</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QSpinBox" name="opt_top_margin">
|
||||||
|
<property name="suffix">
|
||||||
|
<string> px</string>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QLabel" name="label_19">
|
||||||
|
<property name="text">
|
||||||
|
<string>&Side margin</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>opt_side_margin</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QSpinBox" name="opt_side_margin">
|
||||||
|
<property name="suffix">
|
||||||
|
<string> px</string>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QLabel" name="label_17">
|
||||||
|
<property name="text">
|
||||||
|
<string>&Bottom margin</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>opt_bottom_margin</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<widget class="QSpinBox" name="opt_bottom_margin">
|
||||||
|
<property name="suffix">
|
||||||
|
<string> px</string>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="page_2">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>811</width>
|
||||||
|
<height>384</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<attribute name="label">
|
||||||
|
<string>F&ull screen options</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QFormLayout" name="formLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_7">
|
||||||
|
<property name="text">
|
||||||
|
<string>Maximum text width in &fullscreen:</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>max_fs_width</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<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">
|
||||||
|
<string> px</string>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>100</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>10000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QCheckBox" name="opt_fullscreen_clock">
|
||||||
|
<property name="text">
|
||||||
|
<string>Show &clock in full screen mode</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="page_3">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>811</width>
|
||||||
|
<height>384</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<attribute name="label">
|
||||||
|
<string>Page Fl&ip options</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QFormLayout" name="formLayout_3">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_11">
|
||||||
|
<property name="text">
|
||||||
|
<string>Page flip &duration:</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>opt_page_flip_duration</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QDoubleSpinBox" name="opt_page_flip_duration">
|
||||||
|
<property name="specialValueText">
|
||||||
|
<string>disabled</string>
|
||||||
|
</property>
|
||||||
|
<property name="suffix">
|
||||||
|
<string> secs</string>
|
||||||
|
</property>
|
||||||
|
<property name="decimals">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<double>0.100000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<double>3.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<double>0.100000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<double>0.500000000000000</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0" colspan="2">
|
||||||
|
<widget class="QCheckBox" name="opt_wheel_flips_pages">
|
||||||
|
<property name="text">
|
||||||
|
<string>Mouse &wheel flips pages</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0" colspan="2">
|
||||||
|
<widget class="QCheckBox" name="opt_line_scrolling_stops_on_pagebreaks">
|
||||||
|
<property name="text">
|
||||||
|
<string>Line &scrolling stops at page breaks</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0" colspan="2">
|
||||||
|
<widget class="QCheckBox" name="opt_fit_images">
|
||||||
|
<property name="text">
|
||||||
|
<string>&Resize images larger than the viewer window (needs restart)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="page_4">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>811</width>
|
||||||
|
<height>384</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<attribute name="label">
|
||||||
|
<string>&Miscellaneous options</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QFormLayout" name="formLayout_4">
|
||||||
|
<item row="0" column="0" colspan="2">
|
||||||
|
<widget class="QCheckBox" name="hyphenate">
|
||||||
|
<property name="text">
|
||||||
|
<string>H&yphenate (break line in the middle of large words)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="hyphenate_label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Default &language for hyphenation:</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>hyphenate_default_lang</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QComboBox" name="hyphenate_default_lang">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>The default language to use for hyphenation rules. If the book does not specify a language, this will be used.</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0" colspan="2">
|
||||||
|
<widget class="QCheckBox" name="opt_remember_window_size">
|
||||||
|
<property name="text">
|
||||||
|
<string>Remember last used &window size and layout</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0" colspan="2">
|
||||||
|
<widget class="QCheckBox" name="opt_remember_current_page">
|
||||||
|
<property name="text">
|
||||||
|
<string>Remember the &current page when quitting</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
@ -361,14 +550,19 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<tabstops>
|
<tabstops>
|
||||||
<tabstop>serif_family</tabstop>
|
|
||||||
<tabstop>sans_family</tabstop>
|
|
||||||
<tabstop>mono_family</tabstop>
|
|
||||||
<tabstop>max_fs_width</tabstop>
|
|
||||||
<tabstop>opt_remember_window_size</tabstop>
|
|
||||||
<tabstop>buttonBox</tabstop>
|
<tabstop>buttonBox</tabstop>
|
||||||
</tabstops>
|
</tabstops>
|
||||||
<resources>
|
<resources>
|
||||||
@ -382,8 +576,8 @@
|
|||||||
<slot>accept()</slot>
|
<slot>accept()</slot>
|
||||||
<hints>
|
<hints>
|
||||||
<hint type="sourcelabel">
|
<hint type="sourcelabel">
|
||||||
<x>252</x>
|
<x>258</x>
|
||||||
<y>569</y>
|
<y>623</y>
|
||||||
</hint>
|
</hint>
|
||||||
<hint type="destinationlabel">
|
<hint type="destinationlabel">
|
||||||
<x>157</x>
|
<x>157</x>
|
||||||
@ -398,8 +592,8 @@
|
|||||||
<slot>reject()</slot>
|
<slot>reject()</slot>
|
||||||
<hints>
|
<hints>
|
||||||
<hint type="sourcelabel">
|
<hint type="sourcelabel">
|
||||||
<x>320</x>
|
<x>326</x>
|
||||||
<y>569</y>
|
<y>623</y>
|
||||||
</hint>
|
</hint>
|
||||||
<hint type="destinationlabel">
|
<hint type="destinationlabel">
|
||||||
<x>286</x>
|
<x>286</x>
|
||||||
@ -414,12 +608,60 @@
|
|||||||
<slot>setEnabled(bool)</slot>
|
<slot>setEnabled(bool)</slot>
|
||||||
<hints>
|
<hints>
|
||||||
<hint type="sourcelabel">
|
<hint type="sourcelabel">
|
||||||
<x>83</x>
|
<x>89</x>
|
||||||
<y>279</y>
|
<y>226</y>
|
||||||
</hint>
|
</hint>
|
||||||
<hint type="destinationlabel">
|
<hint type="destinationlabel">
|
||||||
<x>349</x>
|
<x>332</x>
|
||||||
<y>312</y>
|
<y>259</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>opt_override_book_margins</sender>
|
||||||
|
<signal>toggled(bool)</signal>
|
||||||
|
<receiver>opt_top_margin</receiver>
|
||||||
|
<slot>setEnabled(bool)</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>137</x>
|
||||||
|
<y>189</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>367</x>
|
||||||
|
<y>218</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>opt_override_book_margins</sender>
|
||||||
|
<signal>toggled(bool)</signal>
|
||||||
|
<receiver>opt_side_margin</receiver>
|
||||||
|
<slot>setEnabled(bool)</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>71</x>
|
||||||
|
<y>193</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>347</x>
|
||||||
|
<y>253</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>opt_override_book_margins</sender>
|
||||||
|
<signal>toggled(bool)</signal>
|
||||||
|
<receiver>opt_bottom_margin</receiver>
|
||||||
|
<slot>setEnabled(bool)</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>513</x>
|
||||||
|
<y>196</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>371</x>
|
||||||
|
<y>281</y>
|
||||||
</hint>
|
</hint>
|
||||||
</hints>
|
</hints>
|
||||||
</connection>
|
</connection>
|
||||||
|
@ -22,7 +22,6 @@ from calibre.gui2.viewer.javascript import JavaScriptLoader
|
|||||||
from calibre.gui2.viewer.position import PagePosition
|
from calibre.gui2.viewer.position import PagePosition
|
||||||
from calibre.gui2.viewer.config import config, ConfigDialog
|
from calibre.gui2.viewer.config import config, ConfigDialog
|
||||||
from calibre.ebooks.oeb.display.webview import load_html
|
from calibre.ebooks.oeb.display.webview import load_html
|
||||||
from calibre.utils.config import tweaks
|
|
||||||
from calibre.constants import isxp
|
from calibre.constants import isxp
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
@ -60,7 +59,7 @@ class Document(QWebPage): # {{{
|
|||||||
def __init__(self, shortcuts, parent=None, debug_javascript=False):
|
def __init__(self, shortcuts, parent=None, debug_javascript=False):
|
||||||
QWebPage.__init__(self, parent)
|
QWebPage.__init__(self, parent)
|
||||||
self.setObjectName("py_bridge")
|
self.setObjectName("py_bridge")
|
||||||
self.in_paged_mode = tweaks.get('viewer_test_paged_mode', False)
|
self.in_paged_mode = False
|
||||||
# Use this to pass arbitrary JSON encodable objects between python and
|
# Use this to pass arbitrary JSON encodable objects between python and
|
||||||
# javascript. In python get/set the value as: self.bridge_value. In
|
# javascript. In python get/set the value as: self.bridge_value. In
|
||||||
# javascript, get/set the value as: py_bridge.value
|
# javascript, get/set the value as: py_bridge.value
|
||||||
@ -135,6 +134,10 @@ class Document(QWebPage): # {{{
|
|||||||
# Leave some space for the scrollbar and some border
|
# Leave some space for the scrollbar and some border
|
||||||
self.max_fs_width = min(opts.max_fs_width, screen_width-50)
|
self.max_fs_width = min(opts.max_fs_width, screen_width-50)
|
||||||
self.fullscreen_clock = opts.fullscreen_clock
|
self.fullscreen_clock = opts.fullscreen_clock
|
||||||
|
self.use_book_margins = opts.use_book_margins
|
||||||
|
self.cols_per_screen = opts.cols_per_screen
|
||||||
|
self.side_margin = opts.side_margin
|
||||||
|
self.top_margin, self.bottom_margin = opts.top_margin, opts.bottom_margin
|
||||||
|
|
||||||
def fit_images(self):
|
def fit_images(self):
|
||||||
if self.do_fit_images and not self.in_paged_mode:
|
if self.do_fit_images and not self.in_paged_mode:
|
||||||
@ -180,6 +183,7 @@ class Document(QWebPage): # {{{
|
|||||||
fset=_pass_json_value_setter)
|
fset=_pass_json_value_setter)
|
||||||
|
|
||||||
def after_load(self):
|
def after_load(self):
|
||||||
|
self.javascript('window.paged_display.read_document_margins()')
|
||||||
self.set_bottom_padding(0)
|
self.set_bottom_padding(0)
|
||||||
self.fit_images()
|
self.fit_images()
|
||||||
self.init_hyphenate()
|
self.init_hyphenate()
|
||||||
@ -216,6 +220,14 @@ class Document(QWebPage): # {{{
|
|||||||
def switch_to_paged_mode(self, onresize=False):
|
def switch_to_paged_mode(self, onresize=False):
|
||||||
if onresize and not self.loaded_javascript:
|
if onresize and not self.loaded_javascript:
|
||||||
return
|
return
|
||||||
|
self.javascript('''
|
||||||
|
window.paged_display.use_document_margins = %s;
|
||||||
|
window.paged_display.set_geometry(%d, %d, %d, %d);
|
||||||
|
'''%(
|
||||||
|
('true' if self.use_book_margins else 'false'),
|
||||||
|
self.cols_per_screen, self.top_margin, self.side_margin,
|
||||||
|
self.bottom_margin
|
||||||
|
))
|
||||||
side_margin = self.javascript('window.paged_display.layout()', typ=int)
|
side_margin = self.javascript('window.paged_display.layout()', typ=int)
|
||||||
# Setup the contents size to ensure that there is a right most margin.
|
# Setup the contents size to ensure that there is a right most margin.
|
||||||
# Without this webkit renders the final column with no margin, as the
|
# Without this webkit renders the final column with no margin, as the
|
||||||
@ -229,6 +241,7 @@ class Document(QWebPage): # {{{
|
|||||||
sz.setWidth(scroll_width+side_margin)
|
sz.setWidth(scroll_width+side_margin)
|
||||||
self.setPreferredContentsSize(sz)
|
self.setPreferredContentsSize(sz)
|
||||||
self.javascript('window.paged_display.fit_images()')
|
self.javascript('window.paged_display.fit_images()')
|
||||||
|
self.javascript('window.paged_display.check_top_margin()')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def column_boundaries(self):
|
def column_boundaries(self):
|
||||||
@ -647,6 +660,7 @@ class DocumentView(QWebView): # {{{
|
|||||||
|
|
||||||
def load_path(self, path, pos=0.0):
|
def load_path(self, path, pos=0.0):
|
||||||
self.initial_pos = pos
|
self.initial_pos = pos
|
||||||
|
self.last_loaded_path = path
|
||||||
|
|
||||||
def callback(lu):
|
def callback(lu):
|
||||||
self.loading_url = lu
|
self.loading_url = lu
|
||||||
@ -654,7 +668,7 @@ class DocumentView(QWebView): # {{{
|
|||||||
self.manager.load_started()
|
self.manager.load_started()
|
||||||
|
|
||||||
load_html(path, self, codec=getattr(path, 'encoding', 'utf-8'), mime_type=getattr(path,
|
load_html(path, self, codec=getattr(path, 'encoding', 'utf-8'), mime_type=getattr(path,
|
||||||
'mime_type', None), pre_load_callback=callback)
|
'mime_type', 'text/html'), pre_load_callback=callback)
|
||||||
entries = set()
|
entries = set()
|
||||||
for ie in getattr(path, 'index_entries', []):
|
for ie in getattr(path, 'index_entries', []):
|
||||||
if ie.start_anchor:
|
if ie.start_anchor:
|
||||||
|
@ -152,6 +152,10 @@ class RecentAction(QAction):
|
|||||||
class EbookViewer(MainWindow, Ui_EbookViewer):
|
class EbookViewer(MainWindow, Ui_EbookViewer):
|
||||||
|
|
||||||
STATE_VERSION = 1
|
STATE_VERSION = 1
|
||||||
|
FLOW_MODE_TT = _('Switch to paged mode - where the text is broken up '
|
||||||
|
'into pages like a paper book')
|
||||||
|
PAGED_MODE_TT = _('Switch to flow mode - where the text is not broken up '
|
||||||
|
'into pages')
|
||||||
|
|
||||||
def __init__(self, pathtoebook=None, debug_javascript=False, open_at=None):
|
def __init__(self, pathtoebook=None, debug_javascript=False, open_at=None):
|
||||||
MainWindow.__init__(self, None)
|
MainWindow.__init__(self, None)
|
||||||
@ -168,6 +172,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
self.pending_anchor = None
|
self.pending_anchor = None
|
||||||
self.pending_reference = None
|
self.pending_reference = None
|
||||||
self.pending_bookmark = None
|
self.pending_bookmark = None
|
||||||
|
self.pending_restore = False
|
||||||
self.existing_bookmarks= []
|
self.existing_bookmarks= []
|
||||||
self.selected_text = None
|
self.selected_text = None
|
||||||
self.read_settings()
|
self.read_settings()
|
||||||
@ -339,6 +344,22 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
self.addAction(action)
|
self.addAction(action)
|
||||||
|
|
||||||
self.restore_state()
|
self.restore_state()
|
||||||
|
self.action_toggle_paged_mode.toggled[bool].connect(self.toggle_paged_mode)
|
||||||
|
|
||||||
|
def toggle_paged_mode(self, checked, at_start=False):
|
||||||
|
in_paged_mode = not self.action_toggle_paged_mode.isChecked()
|
||||||
|
self.view.document.in_paged_mode = in_paged_mode
|
||||||
|
self.action_toggle_paged_mode.setToolTip(self.FLOW_MODE_TT if
|
||||||
|
self.action_toggle_paged_mode.isChecked() else
|
||||||
|
self.PAGED_MODE_TT)
|
||||||
|
if at_start: return
|
||||||
|
self.reload()
|
||||||
|
|
||||||
|
def reload(self):
|
||||||
|
if hasattr(self, 'current_index') and self.current_index > -1:
|
||||||
|
self.view.document.page_position.save(overwrite=False)
|
||||||
|
self.pending_restore = True
|
||||||
|
self.load_path(self.view.last_loaded_path)
|
||||||
|
|
||||||
def set_toc_visible(self, yes):
|
def set_toc_visible(self, yes):
|
||||||
self.toc.setVisible(yes)
|
self.toc.setVisible(yes)
|
||||||
@ -394,6 +415,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
vprefs.set('viewer_splitter_state',
|
vprefs.set('viewer_splitter_state',
|
||||||
bytearray(self.splitter.saveState()))
|
bytearray(self.splitter.saveState()))
|
||||||
vprefs['multiplier'] = self.view.multiplier
|
vprefs['multiplier'] = self.view.multiplier
|
||||||
|
vprefs['in_paged_mode1'] = not self.action_toggle_paged_mode.isChecked()
|
||||||
|
|
||||||
def restore_state(self):
|
def restore_state(self):
|
||||||
state = vprefs.get('viewer_toolbar_state', None)
|
state = vprefs.get('viewer_toolbar_state', None)
|
||||||
@ -410,6 +432,10 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
# specific location, ensure they are visible.
|
# specific location, ensure they are visible.
|
||||||
self.tool_bar.setVisible(True)
|
self.tool_bar.setVisible(True)
|
||||||
self.tool_bar2.setVisible(True)
|
self.tool_bar2.setVisible(True)
|
||||||
|
self.action_toggle_paged_mode.setChecked(not vprefs.get('in_paged_mode1',
|
||||||
|
False))
|
||||||
|
self.toggle_paged_mode(self.action_toggle_paged_mode.isChecked(),
|
||||||
|
at_start=True)
|
||||||
|
|
||||||
def lookup(self, word):
|
def lookup(self, word):
|
||||||
self.dictionary_view.setHtml('<html><body><p>'+ \
|
self.dictionary_view.setHtml('<html><body><p>'+ \
|
||||||
@ -716,6 +742,8 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
if self.pending_bookmark is not None:
|
if self.pending_bookmark is not None:
|
||||||
self.goto_bookmark(self.pending_bookmark)
|
self.goto_bookmark(self.pending_bookmark)
|
||||||
self.pending_bookmark = None
|
self.pending_bookmark = None
|
||||||
|
if self.pending_restore:
|
||||||
|
self.view.document.page_position.restore()
|
||||||
return self.current_index
|
return self.current_index
|
||||||
|
|
||||||
def goto_next_section(self):
|
def goto_next_section(self):
|
||||||
|
@ -143,6 +143,7 @@
|
|||||||
</attribute>
|
</attribute>
|
||||||
<addaction name="action_find_next"/>
|
<addaction name="action_find_next"/>
|
||||||
<addaction name="action_find_previous"/>
|
<addaction name="action_find_previous"/>
|
||||||
|
<addaction name="action_toggle_paged_mode"/>
|
||||||
</widget>
|
</widget>
|
||||||
<action name="action_back">
|
<action name="action_back">
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
@ -309,6 +310,18 @@
|
|||||||
<string>Shift+F3</string>
|
<string>Shift+F3</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="action_toggle_paged_mode">
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../../resources/images.qrc">
|
||||||
|
<normaloff>:/images/scroll.png</normaloff>:/images/scroll.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Toggle Paged mode</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
|
@ -50,7 +50,8 @@ class PagePosition(object):
|
|||||||
def __exit__(self, *args):
|
def __exit__(self, *args):
|
||||||
self.restore()
|
self.restore()
|
||||||
|
|
||||||
def save(self):
|
def save(self, overwrite=True):
|
||||||
|
if not overwrite and self._cpos is not None: return
|
||||||
self._cpos = self.current_pos
|
self._cpos = self.current_pos
|
||||||
|
|
||||||
def restore(self):
|
def restore(self):
|
||||||
|
@ -71,6 +71,7 @@ class Printing(QObject):
|
|||||||
paged_display.set_geometry(1, 0, 0, 0);
|
paged_display.set_geometry(1, 0, 0, 0);
|
||||||
paged_display.layout();
|
paged_display.layout();
|
||||||
paged_display.fit_images();
|
paged_display.fit_images();
|
||||||
|
paged_display.check_top_margin();
|
||||||
''')
|
''')
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user