mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
sync with Kovid's branch
This commit is contained in:
commit
4d9f28773f
@ -19,6 +19,61 @@
|
|||||||
# new recipes:
|
# new recipes:
|
||||||
# - title:
|
# - title:
|
||||||
|
|
||||||
|
- version: 0.9.6
|
||||||
|
date: 2012-11-10
|
||||||
|
|
||||||
|
new features:
|
||||||
|
- title: "Experimental support for subsetting fonts"
|
||||||
|
description: "Subsetting a font means reducing the font to contain only the glyphs for the text actually present in the book. This can easily halve the size of the font. calibre can now do this for all embedded fonts during a conversion. Turn it on via the 'Subset all embedded fonts' option under the Look & Feel section of the conversion dialog. calibre can subset both TrueType and OpenType fonts. Note that this code is very new and likely has bugs, so please check the output if you turn on subsetting. The conversion log will have info about the subsetting operations."
|
||||||
|
type: major
|
||||||
|
|
||||||
|
- title: "EPUB Input: Try to workaround EPUBs that have missing or damaged ZIP central directories. calibre should now be able to read/convert such an EPUB file, provided it does not suffer from further corruption."
|
||||||
|
|
||||||
|
- title: "Allow using identifiers in save to disk templates."
|
||||||
|
tickets: [1074623]
|
||||||
|
|
||||||
|
- title: "calibredb: Add an option to not notify the GUI"
|
||||||
|
|
||||||
|
- title: "Catalogs: Fix long tags causing catalog generation to fail on windows. Add the ability to cross-reference authors, i.e. to relist the authors for a book with multiple authors separately."
|
||||||
|
tickets: [1074931]
|
||||||
|
|
||||||
|
- title: "Edit metadata dialog: Add a clear tags button to remove all tags with a single click"
|
||||||
|
|
||||||
|
- title: "Add search to the font family chooser dialog"
|
||||||
|
|
||||||
|
bug fixes:
|
||||||
|
- title: "Windows: Fix a long standing bug in the device eject code that for some reason only manifested in 0.9.5."
|
||||||
|
tickets: [1075782]
|
||||||
|
|
||||||
|
- title: "Get Books: Fix Amazon stores, Google Books store and libri.de"
|
||||||
|
|
||||||
|
- title: "Kobo driver: More fixes for on device book matching, and list books as being on device even if the Kobo has not yet indexed them. Also some performance improvements."
|
||||||
|
tickets: [1069617]
|
||||||
|
|
||||||
|
- title: "EPUB Output: Remove duplicate id and name attributes to eliminate pointless noise from the various epub check utilities"
|
||||||
|
|
||||||
|
- title: "Ask for confirmation before removing plugins"
|
||||||
|
|
||||||
|
- title: "Fix bulk convert queueing dialog becoming very long if any of the books have a very long title."
|
||||||
|
tickets: [1076191]
|
||||||
|
|
||||||
|
- title: "Fix deleting custom column tags like data from the Tag browser not updating the last modified timestamp for affected books"
|
||||||
|
tickets: [1075476]
|
||||||
|
|
||||||
|
- title: "When updating a previously broken plugin, do not show an error message because the previous version of the plugin cannot be loaded"
|
||||||
|
|
||||||
|
- title: "Fix regression that broke the Template Editor"
|
||||||
|
|
||||||
|
improved recipes:
|
||||||
|
- Various updated Polish recipes
|
||||||
|
- London Review of Books
|
||||||
|
- Yemen Times
|
||||||
|
|
||||||
|
new recipes:
|
||||||
|
- title: "Various Polish news sources"
|
||||||
|
author: Artur Stachecki
|
||||||
|
|
||||||
|
|
||||||
- version: 0.9.5
|
- version: 0.9.5
|
||||||
date: 2012-11-02
|
date: 2012-11-02
|
||||||
|
|
||||||
|
@ -721,8 +721,8 @@ You can switch |app| to using a backed up library folder by simply clicking the
|
|||||||
|
|
||||||
If you want to backup the |app| configuration/plugins, you have to backup the config directory. You can find this config directory via :guilabel:`Preferences->Miscellaneous`. Note that restoring configuration directories is not officially supported, but should work in most cases. Just copy the contents of the backup directory into the current configuration directory to restore.
|
If you want to backup the |app| configuration/plugins, you have to backup the config directory. You can find this config directory via :guilabel:`Preferences->Miscellaneous`. Note that restoring configuration directories is not officially supported, but should work in most cases. Just copy the contents of the backup directory into the current configuration directory to restore.
|
||||||
|
|
||||||
How do I use purchased EPUB books with |app|?
|
How do I use purchased EPUB books with |app| (or what do I do with .acsm files)?
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
Most purchased EPUB books have `DRM <http://drmfree.calibre-ebook.com/about#drm>`_. This prevents |app| from opening them. You can still use |app| to store and transfer them to your ebook reader. First, you must authorize your reader on a windows machine with Adobe Digital Editions. Once this is done, EPUB books transferred with |app| will work fine on your reader. When you purchase an epub book from a website, you will get an ".acsm" file. This file should be opened with Adobe Digital Editions, which will then download the actual ".epub" ebook. The ebook file will be stored in the folder "My Digital Editions", from where you can add it to |app|.
|
Most purchased EPUB books have `DRM <http://drmfree.calibre-ebook.com/about#drm>`_. This prevents |app| from opening them. You can still use |app| to store and transfer them to your ebook reader. First, you must authorize your reader on a windows machine with Adobe Digital Editions. Once this is done, EPUB books transferred with |app| will work fine on your reader. When you purchase an epub book from a website, you will get an ".acsm" file. This file should be opened with Adobe Digital Editions, which will then download the actual ".epub" ebook. The ebook file will be stored in the folder "My Digital Editions", from where you can add it to |app|.
|
||||||
|
|
||||||
I am getting a "Permission Denied" error?
|
I am getting a "Permission Denied" error?
|
||||||
|
@ -8,7 +8,6 @@ www.autosport.com
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
import re
|
|
||||||
|
|
||||||
class autosport(BasicNewsRecipe):
|
class autosport(BasicNewsRecipe):
|
||||||
title = u'Autosport'
|
title = u'Autosport'
|
||||||
@ -27,5 +26,5 @@ class autosport(BasicNewsRecipe):
|
|||||||
keep_only_tags.append(dict(name = 'td', attrs = {'class' : 'news_article_author'}))
|
keep_only_tags.append(dict(name = 'td', attrs = {'class' : 'news_article_author'}))
|
||||||
keep_only_tags.append(dict(name = 'td', attrs = {'class' : 'news_article_date'}))
|
keep_only_tags.append(dict(name = 'td', attrs = {'class' : 'news_article_date'}))
|
||||||
keep_only_tags.append(dict(name = 'p'))
|
keep_only_tags.append(dict(name = 'p'))
|
||||||
|
|
||||||
feeds = [(u'ALL NEWS', u'http://www.autosport.com/rss/allnews.xml')]
|
feeds = [(u'ALL NEWS', u'http://www.autosport.com/rss/allnews.xml')]
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
import re
|
|
||||||
|
|
||||||
class blognexto(BasicNewsRecipe):
|
class blognexto(BasicNewsRecipe):
|
||||||
title = 'BLOG.NEXTO.pl'
|
title = 'BLOG.NEXTO.pl'
|
||||||
|
@ -3,8 +3,7 @@
|
|||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
|
|
||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
import datetime
|
import datetime, re
|
||||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, NavigableString, Tag
|
|
||||||
|
|
||||||
|
|
||||||
class brewiarz(BasicNewsRecipe):
|
class brewiarz(BasicNewsRecipe):
|
||||||
@ -17,7 +16,7 @@ class brewiarz(BasicNewsRecipe):
|
|||||||
remove_javascript = True
|
remove_javascript = True
|
||||||
no_stylesheets = True
|
no_stylesheets = True
|
||||||
publication_type = 'newspaper'
|
publication_type = 'newspaper'
|
||||||
next_days = 1
|
next_days = 1
|
||||||
|
|
||||||
def parse_index(self):
|
def parse_index(self):
|
||||||
dec2rom_dict = {"01": "i", "02": "ii", "03": "iii", "04": "iv",
|
dec2rom_dict = {"01": "i", "02": "ii", "03": "iii", "04": "iv",
|
||||||
|
@ -3,13 +3,11 @@
|
|||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
|
|
||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
import re
|
|
||||||
|
|
||||||
|
|
||||||
class kerrang(BasicNewsRecipe):
|
class kerrang(BasicNewsRecipe):
|
||||||
title = u'Kerrang!'
|
title = u'Kerrang!'
|
||||||
__author__ = 'Artur Stachecki <artur.stachecki@gmail.com>'
|
__author__ = 'Artur Stachecki <artur.stachecki@gmail.com>'
|
||||||
language = 'en'
|
language = 'en_GB'
|
||||||
description = u'UK-based magazine devoted to rock music published by Bauer Media Group'
|
description = u'UK-based magazine devoted to rock music published by Bauer Media Group'
|
||||||
oldest_article = 7
|
oldest_article = 7
|
||||||
masthead_url = 'http://images.kerrang.com/design/kerrang/kerrangsite/logo.gif'
|
masthead_url = 'http://images.kerrang.com/design/kerrang/kerrangsite/logo.gif'
|
||||||
@ -29,8 +27,8 @@ class kerrang(BasicNewsRecipe):
|
|||||||
feeds = [(u'News', u'http://www.kerrang.com/blog/rss.xml')]
|
feeds = [(u'News', u'http://www.kerrang.com/blog/rss.xml')]
|
||||||
|
|
||||||
def preprocess_html(self, soup):
|
def preprocess_html(self, soup):
|
||||||
for alink in soup.findAll('a'):
|
for alink in soup.findAll('a'):
|
||||||
if alink.string is not None:
|
if alink.string is not None:
|
||||||
tstr = alink.string
|
tstr = alink.string
|
||||||
alink.replaceWith(tstr)
|
alink.replaceWith(tstr)
|
||||||
return soup
|
return soup
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
|
|
||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
import re
|
|
||||||
|
|
||||||
|
|
||||||
class leequipe(BasicNewsRecipe):
|
class leequipe(BasicNewsRecipe):
|
||||||
|
@ -8,7 +8,6 @@ http://www.mateusz.pl/czytania
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
import re
|
|
||||||
|
|
||||||
class czytania_mateusz(BasicNewsRecipe):
|
class czytania_mateusz(BasicNewsRecipe):
|
||||||
title = u'Czytania na ka\u017cdy dzie\u0144'
|
title = u'Czytania na ka\u017cdy dzie\u0144'
|
||||||
|
32
recipes/red_voltaire.recipe
Normal file
32
recipes/red_voltaire.recipe
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import re
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class RedVoltaireRecipe(BasicNewsRecipe):
|
||||||
|
title = u'Red Voltaire'
|
||||||
|
__author__ = 'atordo'
|
||||||
|
description = u'Red de prensa no alineada, especializada en el an\u00e1lisis de las relaciones internacionales'
|
||||||
|
oldest_article = 7
|
||||||
|
max_articles_per_feed = 30
|
||||||
|
auto_cleanup = False
|
||||||
|
no_stylesheets = True
|
||||||
|
language = 'es'
|
||||||
|
use_embedded_content = False
|
||||||
|
remove_javascript = True
|
||||||
|
cover_url = u'http://www.voltairenet.org/squelettes/elements/images/logo-voltairenet-org.png'
|
||||||
|
masthead_url = u'http://www.voltairenet.org/squelettes/elements/images/logo-voltairenet-org.png'
|
||||||
|
|
||||||
|
preprocess_regexps = [
|
||||||
|
(re.compile(r'<title>(?P<titulo>.+)</title>.+<span class="updated" title=".+"><time', re.IGNORECASE|re.DOTALL)
|
||||||
|
,lambda match:'</title></head><body><h1>'+match.group('titulo')+'</h1><time')
|
||||||
|
,(re.compile(r'<time datetime=.+pubdate>. (?P<fecha>.+)</time>.+<!------------------- COLONNE TEXTE ------------------->', re.IGNORECASE|re.DOTALL)
|
||||||
|
,lambda match:'<small>'+match.group('fecha')+'</small>')
|
||||||
|
,(re.compile(r'<aside>.+', re.IGNORECASE|re.DOTALL)
|
||||||
|
,lambda match:'</body></html>')
|
||||||
|
]
|
||||||
|
|
||||||
|
extra_css = '''
|
||||||
|
img{margin-bottom:0.4em; display:block; margin-left:auto; margin-right:auto}
|
||||||
|
'''
|
||||||
|
|
||||||
|
feeds = [u'http://www.voltairenet.org/spip.php?page=backend&id_secteur=1110&lang=es']
|
||||||
|
|
@ -8,12 +8,11 @@ www.rushisaband.com
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
import re
|
|
||||||
|
|
||||||
class rushisaband(BasicNewsRecipe):
|
class rushisaband(BasicNewsRecipe):
|
||||||
title = u'Rushisaband'
|
title = u'Rushisaband'
|
||||||
__author__ = 'MrStefan <mrstefaan@gmail.com>'
|
__author__ = 'MrStefan <mrstefaan@gmail.com>'
|
||||||
language = 'en'
|
language = 'en_GB'
|
||||||
description =u'A blog devoted to the band RUSH and its members, Neil Peart, Geddy Lee and Alex Lifeson'
|
description =u'A blog devoted to the band RUSH and its members, Neil Peart, Geddy Lee and Alex Lifeson'
|
||||||
remove_empty_feeds= True
|
remove_empty_feeds= True
|
||||||
oldest_article = 7
|
oldest_article = 7
|
||||||
@ -25,5 +24,5 @@ class rushisaband(BasicNewsRecipe):
|
|||||||
keep_only_tags.append(dict(name = 'h4'))
|
keep_only_tags.append(dict(name = 'h4'))
|
||||||
keep_only_tags.append(dict(name = 'h5'))
|
keep_only_tags.append(dict(name = 'h5'))
|
||||||
keep_only_tags.append(dict(name = 'p'))
|
keep_only_tags.append(dict(name = 'p'))
|
||||||
|
|
||||||
feeds = [(u'Rush is a Band', u'http://feeds2.feedburner.com/rushisaband/blog')]
|
feeds = [(u'Rush is a Band', u'http://feeds2.feedburner.com/rushisaband/blog')]
|
||||||
|
@ -8,7 +8,6 @@ http://www.rynekinfrastruktury.pl
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
import re
|
|
||||||
|
|
||||||
class prawica_recipe(BasicNewsRecipe):
|
class prawica_recipe(BasicNewsRecipe):
|
||||||
title = u'Rynek Infrastruktury'
|
title = u'Rynek Infrastruktury'
|
||||||
|
@ -8,7 +8,6 @@ rynek-kolejowy.pl
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
import re
|
|
||||||
|
|
||||||
class rynek_kolejowy(BasicNewsRecipe):
|
class rynek_kolejowy(BasicNewsRecipe):
|
||||||
title = u'Rynek Kolejowy'
|
title = u'Rynek Kolejowy'
|
||||||
@ -31,11 +30,11 @@ class rynek_kolejowy(BasicNewsRecipe):
|
|||||||
remove_tags.append(dict(name = 'div', attrs = {'class' : 'no-print'}))
|
remove_tags.append(dict(name = 'div', attrs = {'class' : 'no-print'}))
|
||||||
|
|
||||||
extra_css = '''.wiadomosc_title{ font-size: 1.4em; font-weight: bold; }'''
|
extra_css = '''.wiadomosc_title{ font-size: 1.4em; font-weight: bold; }'''
|
||||||
|
|
||||||
feeds = [(u'Wiadomości', u'http://www.rynek-kolejowy.pl/rss/rss.php')]
|
feeds = [(u'Wiadomości', u'http://www.rynek-kolejowy.pl/rss/rss.php')]
|
||||||
|
|
||||||
def print_version(self, url):
|
def print_version(self, url):
|
||||||
segment = url.split('/')
|
segment = url.split('/')
|
||||||
urlPart = segment[3]
|
urlPart = segment[3]
|
||||||
return 'http://www.rynek-kolejowy.pl/drukuj.php?id=' + urlPart
|
return 'http://www.rynek-kolejowy.pl/drukuj.php?id=' + urlPart
|
||||||
|
|
||||||
|
@ -3,8 +3,6 @@
|
|||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
|
|
||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
import re
|
|
||||||
|
|
||||||
|
|
||||||
class SATKurier(BasicNewsRecipe):
|
class SATKurier(BasicNewsRecipe):
|
||||||
title = u'SATKurier.pl'
|
title = u'SATKurier.pl'
|
||||||
@ -46,4 +44,4 @@ class SATKurier(BasicNewsRecipe):
|
|||||||
if alink.string is not None:
|
if alink.string is not None:
|
||||||
tstr = alink.string
|
tstr = alink.string
|
||||||
alink.replaceWith(tstr)
|
alink.replaceWith(tstr)
|
||||||
return soup
|
return soup
|
||||||
|
@ -14,26 +14,21 @@ class tvn24(BasicNewsRecipe):
|
|||||||
remove_empty_feeds = True
|
remove_empty_feeds = True
|
||||||
remove_javascript = True
|
remove_javascript = True
|
||||||
no_stylesheets = True
|
no_stylesheets = True
|
||||||
keep_only_tags=[
|
keep_only_tags=[
|
||||||
# dict(name='h1', attrs={'class':'size38 mt20 pb20'}),
|
# dict(name='h1', attrs={'class':'size38 mt20 pb20'}),
|
||||||
dict(name='div', attrs={'class':'mainContainer'}),
|
dict(name='div', attrs={'class':'mainContainer'}),
|
||||||
# dict(name='p'),
|
# dict(name='p'),
|
||||||
# dict(attrs={'class':['size18 mt10 mb15', 'bold topicSize1', 'fromUsers content', 'textArticleDefault']})
|
# dict(attrs={'class':['size18 mt10 mb15', 'bold topicSize1', 'fromUsers content', 'textArticleDefault']})
|
||||||
]
|
]
|
||||||
remove_tags=[
|
remove_tags=[
|
||||||
dict(attrs={'class':['commentsInfo', 'textSize', 'related newsNews align-right', 'box', 'watchMaterial text', 'related galleryGallery align-center', 'advert block-alignment-right', 'userActions', 'socialBookmarks', 'im yourArticle fl', 'dynamicButton addComment fl', 'innerArticleModule onRight cols externalContent', 'thumbsGallery', 'relatedObject customBlockquote align-right', 'lead', 'mainRightColumn', 'articleDateContainer borderGreyBottom', 'socialMediaContainer onRight loaded', 'quizContent', 'twitter', 'facebook', 'googlePlus', 'share', 'voteResult', 'reportTitleBar bgBlue_v4 mb15', 'innerVideoModule center']}),
|
dict(attrs={'class':['commentsInfo', 'textSize', 'related newsNews align-right', 'box', 'watchMaterial text', 'related galleryGallery align-center', 'advert block-alignment-right', 'userActions', 'socialBookmarks', 'im yourArticle fl', 'dynamicButton addComment fl', 'innerArticleModule onRight cols externalContent', 'thumbsGallery', 'relatedObject customBlockquote align-right', 'lead', 'mainRightColumn', 'articleDateContainer borderGreyBottom', 'socialMediaContainer onRight loaded', 'quizContent', 'twitter', 'facebook', 'googlePlus', 'share', 'voteResult', 'reportTitleBar bgBlue_v4 mb15', 'innerVideoModule center']}),
|
||||||
dict(name='article', attrs={'class':['singleArtPhotoCenter', 'singleArtPhotoRight', 'singleArtPhotoLeft']}),
|
dict(name='article', attrs={'class':['singleArtPhotoCenter', 'singleArtPhotoRight', 'singleArtPhotoLeft']}),
|
||||||
dict(name='section', attrs={'id':['forum', 'innerArticle', 'quiz toCenter', 'mb20']}),
|
dict(name='section', attrs={'id':['forum', 'innerArticle', 'quiz toCenter', 'mb20']}),
|
||||||
dict(name='div', attrs={'class':'socialMediaContainer big p20 mb20 borderGrey loaded'})
|
dict(name='div', attrs={'class':'socialMediaContainer big p20 mb20 borderGrey loaded'})
|
||||||
]
|
]
|
||||||
remove_tags_after=[dict(name='li', attrs={'class':'share'})]
|
remove_tags_after=[dict(name='li', attrs={'class':'share'})]
|
||||||
feeds = [(u'Najnowsze', u'http://www.tvn24.pl/najnowsze.xml'), ]
|
feeds = [(u'Najnowsze', u'http://www.tvn24.pl/najnowsze.xml'), ]
|
||||||
#(u'Polska', u'www.tvn24.pl/polska.xml'), (u'\u015awiat', u'http://www.tvn24.pl/swiat.xml'), (u'Sport', u'http://www.tvn24.pl/sport.xml'), (u'Biznes', u'http://www.tvn24.pl/biznes.xml'), (u'Meteo', u'http://www.tvn24.pl/meteo.xml'), (u'Micha\u0142ki', u'http://www.tvn24.pl/michalki.xml'), (u'Kultura', u'http://www.tvn24.pl/kultura.xml')]
|
#(u'Polska', u'www.tvn24.pl/polska.xml'), (u'\u015awiat', u'http://www.tvn24.pl/swiat.xml'), (u'Sport', u'http://www.tvn24.pl/sport.xml'), (u'Biznes', u'http://www.tvn24.pl/biznes.xml'), (u'Meteo', u'http://www.tvn24.pl/meteo.xml'), (u'Micha\u0142ki', u'http://www.tvn24.pl/michalki.xml'), (u'Kultura', u'http://www.tvn24.pl/kultura.xml')]
|
||||||
|
|
||||||
def preprocess_html(self, soup):
|
|
||||||
for item in soup.findAll(style=True):
|
|
||||||
del item['style']
|
|
||||||
return soup
|
|
||||||
|
|
||||||
def preprocess_html(self, soup):
|
def preprocess_html(self, soup):
|
||||||
for alink in soup.findAll('a'):
|
for alink in soup.findAll('a'):
|
||||||
|
1270
setup/iso_639/ca.po
1270
setup/iso_639/ca.po
File diff suppressed because it is too large
Load Diff
@ -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, 9, 5)
|
numeric_version = (0, 9, 6)
|
||||||
__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>"
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ from calibre.ebooks.metadata import author_to_author_sort
|
|||||||
class Book(Book_):
|
class Book(Book_):
|
||||||
|
|
||||||
def __init__(self, prefix, lpath, title=None, authors=None, mime=None, date=None, ContentType=None,
|
def __init__(self, prefix, lpath, title=None, authors=None, mime=None, date=None, ContentType=None,
|
||||||
thumbnail_name=None, size=0, other=None):
|
thumbnail_name=None, size=None, other=None):
|
||||||
# debug_print('Book::__init__ - title=', title)
|
# debug_print('Book::__init__ - title=', title)
|
||||||
show_debug = title is not None and title.lower().find("xxxxx") >= 0
|
show_debug = title is not None and title.lower().find("xxxxx") >= 0
|
||||||
if show_debug:
|
if show_debug:
|
||||||
@ -57,7 +57,7 @@ class Book(Book_):
|
|||||||
except:
|
except:
|
||||||
self.datetime = time.gmtime()
|
self.datetime = time.gmtime()
|
||||||
|
|
||||||
self.contentID = None
|
self.contentID = None
|
||||||
self.current_shelves = []
|
self.current_shelves = []
|
||||||
self.kobo_collections = []
|
self.kobo_collections = []
|
||||||
|
|
||||||
@ -65,7 +65,8 @@ class Book(Book_):
|
|||||||
self.thumbnail = ImageWrapper(thumbnail_name)
|
self.thumbnail = ImageWrapper(thumbnail_name)
|
||||||
|
|
||||||
if show_debug:
|
if show_debug:
|
||||||
debug_print("Book::__init__ - self=", self)
|
debug_print("Book::__init__ end - self=", self)
|
||||||
|
debug_print("Book::__init__ end - title=", title, 'authors=', authors)
|
||||||
|
|
||||||
|
|
||||||
class ImageWrapper(object):
|
class ImageWrapper(object):
|
||||||
|
@ -517,7 +517,7 @@ class KOBO(USBMS):
|
|||||||
lpath = lpath[1:]
|
lpath = lpath[1:]
|
||||||
#print "path: " + lpath
|
#print "path: " + lpath
|
||||||
book = self.book_class(prefix, lpath, other=info)
|
book = self.book_class(prefix, lpath, other=info)
|
||||||
if book.size is None:
|
if book.size is None or book.size == 0:
|
||||||
book.size = os.stat(self.normalize_path(path)).st_size
|
book.size = os.stat(self.normalize_path(path)).st_size
|
||||||
b = booklists[blist].add_book(book, replace_metadata=True)
|
b = booklists[blist].add_book(book, replace_metadata=True)
|
||||||
if b:
|
if b:
|
||||||
@ -667,6 +667,7 @@ class KOBO(USBMS):
|
|||||||
[_('Unknown')])
|
[_('Unknown')])
|
||||||
size = os.stat(cls.normalize_path(os.path.join(prefix, lpath))).st_size
|
size = os.stat(cls.normalize_path(os.path.join(prefix, lpath))).st_size
|
||||||
book = cls.book_class(prefix, lpath, title, authors, mime, date, ContentType, ImageID, size=size, other=mi)
|
book = cls.book_class(prefix, lpath, title, authors, mime, date, ContentType, ImageID, size=size, other=mi)
|
||||||
|
|
||||||
return book
|
return book
|
||||||
|
|
||||||
def get_device_paths(self):
|
def get_device_paths(self):
|
||||||
@ -1430,6 +1431,7 @@ class KOBOTOUCH(KOBO):
|
|||||||
idx = bl_cache.get(lpath, None)
|
idx = bl_cache.get(lpath, None)
|
||||||
if idx is not None:# and not (accessibility == 1 and isdownloaded == 'false'):
|
if idx is not None:# and not (accessibility == 1 and isdownloaded == 'false'):
|
||||||
if show_debug:
|
if show_debug:
|
||||||
|
self.debug_index = idx
|
||||||
debug_print("KoboTouch:update_booklist - idx=%d"%idx)
|
debug_print("KoboTouch:update_booklist - idx=%d"%idx)
|
||||||
debug_print('KoboTouch:update_booklist - bl[idx].device_collections=', bl[idx].device_collections)
|
debug_print('KoboTouch:update_booklist - bl[idx].device_collections=', bl[idx].device_collections)
|
||||||
debug_print('KoboTouch:update_booklist - playlist_map=', playlist_map)
|
debug_print('KoboTouch:update_booklist - playlist_map=', playlist_map)
|
||||||
@ -1464,13 +1466,13 @@ class KOBOTOUCH(KOBO):
|
|||||||
bl[idx].device_collections = playlist_map.get(lpath,[])
|
bl[idx].device_collections = playlist_map.get(lpath,[])
|
||||||
bl[idx].current_shelves = bookshelves
|
bl[idx].current_shelves = bookshelves
|
||||||
bl[idx].kobo_collections = kobo_collections
|
bl[idx].kobo_collections = kobo_collections
|
||||||
changed = True
|
|
||||||
|
|
||||||
if show_debug:
|
if show_debug:
|
||||||
debug_print('KoboTouch:update_booklist - updated bl[idx].device_collections=', bl[idx].device_collections)
|
debug_print('KoboTouch:update_booklist - updated bl[idx].device_collections=', bl[idx].device_collections)
|
||||||
debug_print('KoboTouch:update_booklist - playlist_map=', playlist_map, 'changed=', changed)
|
debug_print('KoboTouch:update_booklist - playlist_map=', playlist_map, 'changed=', changed)
|
||||||
# debug_print('KoboTouch:update_booklist - book=', bl[idx])
|
# debug_print('KoboTouch:update_booklist - book=', bl[idx])
|
||||||
debug_print("KoboTouch:update_booklist - book class=%s"%bl[idx].__class__)
|
debug_print("KoboTouch:update_booklist - book class=%s"%bl[idx].__class__)
|
||||||
|
debug_print("KoboTouch:update_booklist - book title=%s"%bl[idx].title)
|
||||||
else:
|
else:
|
||||||
if show_debug:
|
if show_debug:
|
||||||
debug_print('KoboTouch:update_booklist - idx is none')
|
debug_print('KoboTouch:update_booklist - idx is none')
|
||||||
@ -1494,7 +1496,7 @@ class KOBOTOUCH(KOBO):
|
|||||||
if show_debug:
|
if show_debug:
|
||||||
debug_print('KoboTouch:update_booklist - class:', book.__class__)
|
debug_print('KoboTouch:update_booklist - class:', book.__class__)
|
||||||
# debug_print(' resolution:', book.__class__.__mro__)
|
# debug_print(' resolution:', book.__class__.__mro__)
|
||||||
debug_print(" contentid:'%s'"%book.contentID)
|
debug_print(" contentid: '%s'"%book.contentID)
|
||||||
debug_print(" title:'%s'"%book.title)
|
debug_print(" title:'%s'"%book.title)
|
||||||
debug_print(" the book:", book)
|
debug_print(" the book:", book)
|
||||||
debug_print(" author_sort:'%s'"%book.author_sort)
|
debug_print(" author_sort:'%s'"%book.author_sort)
|
||||||
@ -1512,6 +1514,7 @@ class KOBOTOUCH(KOBO):
|
|||||||
changed = True
|
changed = True
|
||||||
if show_debug:
|
if show_debug:
|
||||||
debug_print(' book.device_collections', book.device_collections)
|
debug_print(' book.device_collections', book.device_collections)
|
||||||
|
debug_print(' book.title', book.title)
|
||||||
except: # Probably a path encoding error
|
except: # Probably a path encoding error
|
||||||
import traceback
|
import traceback
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
@ -1534,6 +1537,7 @@ class KOBOTOUCH(KOBO):
|
|||||||
# debug_print("KoboTouch:get_bookshelvesforbook - count bookshelves=" + unicode(count_bookshelves))
|
# debug_print("KoboTouch:get_bookshelvesforbook - count bookshelves=" + unicode(count_bookshelves))
|
||||||
return bookshelves
|
return bookshelves
|
||||||
|
|
||||||
|
self.debug_index = 0
|
||||||
import sqlite3 as sqlite
|
import sqlite3 as sqlite
|
||||||
with closing(sqlite.connect(
|
with closing(sqlite.connect(
|
||||||
self.normalize_path(self._main_prefix +
|
self.normalize_path(self._main_prefix +
|
||||||
@ -1635,8 +1639,11 @@ class KOBOTOUCH(KOBO):
|
|||||||
# Do the operation in reverse order so indices remain valid
|
# Do the operation in reverse order so indices remain valid
|
||||||
for idx in sorted(bl_cache.itervalues(), reverse=True):
|
for idx in sorted(bl_cache.itervalues(), reverse=True):
|
||||||
if idx is not None:
|
if idx is not None:
|
||||||
need_sync = True
|
if not os.path.exists(self.normalize_path(os.path.join(prefix, bl[idx].lpath))):
|
||||||
del bl[idx]
|
need_sync = True
|
||||||
|
del bl[idx]
|
||||||
|
# else:
|
||||||
|
# debug_print("KoboTouch:books - Book in mtadata.calibre, on file system but not database - bl[idx].title:'%s'"%bl[idx].title)
|
||||||
|
|
||||||
#print "count found in cache: %d, count of files in metadata: %d, need_sync: %s" % \
|
#print "count found in cache: %d, count of files in metadata: %d, need_sync: %s" % \
|
||||||
# (len(bl_cache), len(bl), need_sync)
|
# (len(bl_cache), len(bl), need_sync)
|
||||||
@ -1650,6 +1657,7 @@ class KOBOTOUCH(KOBO):
|
|||||||
USBMS.sync_booklists(self, (None, bl, None))
|
USBMS.sync_booklists(self, (None, bl, None))
|
||||||
else:
|
else:
|
||||||
USBMS.sync_booklists(self, (bl, None, None))
|
USBMS.sync_booklists(self, (bl, None, None))
|
||||||
|
debug_print("KoboTouch:books - have done sync_booklists")
|
||||||
|
|
||||||
self.report_progress(1.0, _('Getting list of books on device...'))
|
self.report_progress(1.0, _('Getting list of books on device...'))
|
||||||
debug_print("KoboTouch:books - end - oncard='%s'"%oncard)
|
debug_print("KoboTouch:books - end - oncard='%s'"%oncard)
|
||||||
@ -1894,7 +1902,7 @@ class KOBOTOUCH(KOBO):
|
|||||||
# debug_print("KoboTouch:update_device_database_collections - self.bookshelvelist=", self.bookshelvelist)
|
# debug_print("KoboTouch:update_device_database_collections - self.bookshelvelist=", self.bookshelvelist)
|
||||||
# Process any collections that exist
|
# Process any collections that exist
|
||||||
for category, books in collections.items():
|
for category, books in collections.items():
|
||||||
debug_print("KoboTouch:update_device_database_collections - category='%s'"%category)
|
debug_print("KoboTouch:update_device_database_collections - category='%s' books=%d"%(category, len(books)))
|
||||||
if create_bookshelves and not (category in supportedcategories or category in readstatuslist or category in accessibilitylist):
|
if create_bookshelves and not (category in supportedcategories or category in readstatuslist or category in accessibilitylist):
|
||||||
self.check_for_bookshelf(connection, category)
|
self.check_for_bookshelf(connection, category)
|
||||||
# if category in self.bookshelvelist:
|
# if category in self.bookshelvelist:
|
||||||
@ -1906,9 +1914,11 @@ class KOBOTOUCH(KOBO):
|
|||||||
debug_print(' Title="%s"'%book.title, 'category="%s"'%category)
|
debug_print(' Title="%s"'%book.title, 'category="%s"'%category)
|
||||||
# debug_print(book)
|
# debug_print(book)
|
||||||
debug_print(' class=%s'%book.__class__)
|
debug_print(' class=%s'%book.__class__)
|
||||||
# debug_print(' resolution:', book.__class__.__mro__)
|
|
||||||
# debug_print(' subclasses:', book.__class__.__subclasses__())
|
|
||||||
debug_print(' book.contentID="%s"'%book.contentID)
|
debug_print(' book.contentID="%s"'%book.contentID)
|
||||||
|
debug_print(' book.application_id="%s"'%book.application_id)
|
||||||
|
|
||||||
|
if book.application_id is None:
|
||||||
|
continue
|
||||||
|
|
||||||
category_added = False
|
category_added = False
|
||||||
|
|
||||||
@ -1924,7 +1934,7 @@ class KOBOTOUCH(KOBO):
|
|||||||
if category not in book.device_collections:
|
if category not in book.device_collections:
|
||||||
if show_debug:
|
if show_debug:
|
||||||
debug_print(' Setting bookshelf on device')
|
debug_print(' Setting bookshelf on device')
|
||||||
self.set_bookshelf(connection, book.contentID, category)
|
self.set_bookshelf(connection, book, category)
|
||||||
category_added = True
|
category_added = True
|
||||||
elif category in readstatuslist.keys():
|
elif category in readstatuslist.keys():
|
||||||
# Manage ReadStatus
|
# Manage ReadStatus
|
||||||
@ -1956,12 +1966,10 @@ class KOBOTOUCH(KOBO):
|
|||||||
else: # No collections
|
else: # No collections
|
||||||
# Since no collections exist the ReadStatus needs to be reset to 0 (Unread)
|
# Since no collections exist the ReadStatus needs to be reset to 0 (Unread)
|
||||||
debug_print("No Collections - reseting ReadStatus")
|
debug_print("No Collections - reseting ReadStatus")
|
||||||
if oncard == 'carda':
|
|
||||||
debug_print("Booklists=", booklists)
|
|
||||||
if self.dbversion < 53:
|
if self.dbversion < 53:
|
||||||
self.reset_readstatus(connection, oncard)
|
self.reset_readstatus(connection, oncard)
|
||||||
if self.dbversion >= 14:
|
if self.dbversion >= 14:
|
||||||
debug_print("No Collections - reseting FavouritesIndex")
|
debug_print("No Collections - resetting FavouritesIndex")
|
||||||
self.reset_favouritesindex(connection, oncard)
|
self.reset_favouritesindex(connection, oncard)
|
||||||
|
|
||||||
if self.supports_bookshelves():
|
if self.supports_bookshelves():
|
||||||
@ -2189,16 +2197,23 @@ class KOBOTOUCH(KOBO):
|
|||||||
|
|
||||||
return bookshelves
|
return bookshelves
|
||||||
|
|
||||||
def set_bookshelf(self, connection, ContentID, bookshelf):
|
def set_bookshelf(self, connection, book, shelfName):
|
||||||
show_debug = self.is_debugging_title(ContentID)
|
show_debug = self.is_debugging_title(book.title)
|
||||||
if show_debug:
|
if show_debug:
|
||||||
debug_print('KoboTouch:set_bookshelf ContentID=' + ContentID)
|
debug_print('KoboTouch:set_bookshelf book.ContentID="%s"'%book.contentID)
|
||||||
test_query = 'SELECT 1 FROM ShelfContent WHERE ShelfName = ? and ContentId = ?'
|
debug_print('KoboTouch:set_bookshelf book.current_shelves="%s"'%book.current_shelves)
|
||||||
test_values = (bookshelf, ContentID, )
|
|
||||||
|
if shelfName in book.current_shelves:
|
||||||
|
if show_debug:
|
||||||
|
debug_print(' book already on shelf.')
|
||||||
|
return
|
||||||
|
|
||||||
|
test_query = 'SELECT _IsDeleted FROM ShelfContent WHERE ShelfName = ? and ContentId = ?'
|
||||||
|
test_values = (shelfName, book.contentID, )
|
||||||
addquery = 'INSERT INTO ShelfContent ("ShelfName","ContentId","DateModified","_IsDeleted","_IsSynced") VALUES (?, ?, ?, "false", "false")'
|
addquery = 'INSERT INTO ShelfContent ("ShelfName","ContentId","DateModified","_IsDeleted","_IsSynced") VALUES (?, ?, ?, "false", "false")'
|
||||||
add_values = (bookshelf, ContentID, time.strftime(self.TIMESTAMP_STRING, time.gmtime()), )
|
add_values = (shelfName, book.contentID, time.strftime(self.TIMESTAMP_STRING, time.gmtime()), )
|
||||||
updatequery = 'UPDATE ShelfContent SET _IsDeleted = "false" WHERE ShelfName = ? and ContentId = ?'
|
updatequery = 'UPDATE ShelfContent SET _IsDeleted = "false" WHERE ShelfName = ? and ContentId = ?'
|
||||||
update_values = (bookshelf, ContentID, )
|
update_values = (shelfName, book.contentID, )
|
||||||
|
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
cursor.execute(test_query, test_values)
|
cursor.execute(test_query, test_values)
|
||||||
@ -2208,9 +2223,9 @@ class KOBOTOUCH(KOBO):
|
|||||||
debug_print(' Did not find a record - adding')
|
debug_print(' Did not find a record - adding')
|
||||||
cursor.execute(addquery, add_values)
|
cursor.execute(addquery, add_values)
|
||||||
connection.commit()
|
connection.commit()
|
||||||
else:
|
elif result[0] == 'true':
|
||||||
if show_debug:
|
if show_debug:
|
||||||
debug_print(' Found a record - updating')
|
debug_print(' Found a record - updating - result=', result)
|
||||||
cursor.execute(updatequery, update_values)
|
cursor.execute(updatequery, update_values)
|
||||||
connection.commit()
|
connection.commit()
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import os
|
|||||||
|
|
||||||
import cStringIO
|
import cStringIO
|
||||||
|
|
||||||
|
from calibre.constants import isosx
|
||||||
from calibre.devices.usbms.driver import USBMS
|
from calibre.devices.usbms.driver import USBMS
|
||||||
|
|
||||||
class NOOK(USBMS):
|
class NOOK(USBMS):
|
||||||
@ -84,6 +85,8 @@ class NOOK_COLOR(NOOK):
|
|||||||
description = _('Communicate with the Nook Color, TSR and Tablet eBook readers.')
|
description = _('Communicate with the Nook Color, TSR and Tablet eBook readers.')
|
||||||
|
|
||||||
PRODUCT_ID = [0x002, 0x003, 0x004]
|
PRODUCT_ID = [0x002, 0x003, 0x004]
|
||||||
|
if isosx:
|
||||||
|
PRODUCT_ID.append(0x005) # Nook HD+
|
||||||
BCD = [0x216]
|
BCD = [0x216]
|
||||||
|
|
||||||
WINDOWS_MAIN_MEM = WINDOWS_CARD_A_MEM = ['EBOOK_DISK', 'NOOK_TABLET',
|
WINDOWS_MAIN_MEM = WINDOWS_CARD_A_MEM = ['EBOOK_DISK', 'NOOK_TABLET',
|
||||||
|
@ -14,6 +14,7 @@ device. This class handles device detection.
|
|||||||
import os, subprocess, time, re, sys, glob
|
import os, subprocess, time, re, sys, glob
|
||||||
from itertools import repeat
|
from itertools import repeat
|
||||||
|
|
||||||
|
from calibre import prints, as_unicode
|
||||||
from calibre.devices.interface import DevicePlugin
|
from calibre.devices.interface import DevicePlugin
|
||||||
from calibre.devices.errors import DeviceError
|
from calibre.devices.errors import DeviceError
|
||||||
from calibre.devices.usbms.deviceconfig import DeviceConfig
|
from calibre.devices.usbms.deviceconfig import DeviceConfig
|
||||||
@ -903,7 +904,7 @@ class Device(DeviceConfig, DevicePlugin):
|
|||||||
winutil.eject_drive(bytes(d)[0])
|
winutil.eject_drive(bytes(d)[0])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
try:
|
try:
|
||||||
prints(as_unicode(e))
|
prints("Eject failed:", as_unicode(e))
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -144,6 +144,22 @@ class EPUBOutput(OutputFormatPlugin):
|
|||||||
for u in XPath('//h:u')(root):
|
for u in XPath('//h:u')(root):
|
||||||
u.tag = 'span'
|
u.tag = 'span'
|
||||||
u.set('style', 'text-decoration:underline')
|
u.set('style', 'text-decoration:underline')
|
||||||
|
|
||||||
|
seen_ids, seen_names = set(), set()
|
||||||
|
for x in XPath('//*[@id or @name]')(root):
|
||||||
|
eid, name = x.get('id', None), x.get('name', None)
|
||||||
|
if eid:
|
||||||
|
if eid in seen_ids:
|
||||||
|
del x.attrib['id']
|
||||||
|
else:
|
||||||
|
seen_ids.add(eid)
|
||||||
|
if name:
|
||||||
|
if name in seen_names:
|
||||||
|
del x.attrib['name']
|
||||||
|
else:
|
||||||
|
seen_names.add(name)
|
||||||
|
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
def convert(self, oeb, output_path, input_plugin, opts, log):
|
def convert(self, oeb, output_path, input_plugin, opts, log):
|
||||||
|
@ -210,9 +210,7 @@ OptionRecommendation(name='subset_embedded_fonts',
|
|||||||
'Subset all embedded fonts. Every embedded font is reduced '
|
'Subset all embedded fonts. Every embedded font is reduced '
|
||||||
'to contain only the glyphs used in this document. This decreases '
|
'to contain only the glyphs used in this document. This decreases '
|
||||||
'the size of the font files. Useful if you are embedding a '
|
'the size of the font files. Useful if you are embedding a '
|
||||||
'particularly large font with lots of unused glyphs. Note that '
|
'particularly large font with lots of unused glyphs.')
|
||||||
'subsetting is only supported for fonts that contain TrueType '
|
|
||||||
'outlines, not Postscript outlines.')
|
|
||||||
),
|
),
|
||||||
|
|
||||||
OptionRecommendation(name='linearize_tables',
|
OptionRecommendation(name='linearize_tables',
|
||||||
|
@ -89,7 +89,7 @@ class SubsetFonts(object):
|
|||||||
except (IndexError, KeyError, AttributeError, TypeError, ValueError):
|
except (IndexError, KeyError, AttributeError, TypeError, ValueError):
|
||||||
val = None if q in {'src', 'font-family'} else default
|
val = None if q in {'src', 'font-family'} else default
|
||||||
if q in {'font-weight', 'font-stretch', 'font-style'}:
|
if q in {'font-weight', 'font-stretch', 'font-style'}:
|
||||||
val = val.lower() if val else val
|
val = unicode(val).lower() if (val or val == 0) else val
|
||||||
if val == 'inherit':
|
if val == 'inherit':
|
||||||
val = default
|
val = default
|
||||||
if q == 'font-weight':
|
if q == 'font-weight':
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>655</width>
|
<width>699</width>
|
||||||
<height>619</height>
|
<height>619</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
@ -411,7 +411,7 @@
|
|||||||
<item row="6" column="3" colspan="2">
|
<item row="6" column="3" colspan="2">
|
||||||
<widget class="QCheckBox" name="opt_subset_embedded_fonts">
|
<widget class="QCheckBox" name="opt_subset_embedded_fonts">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Subset all embedded fonts</string>
|
<string>&Subset all embedded fonts (Experimental)</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -7,8 +7,8 @@ __docformat__ = 'restructuredtext en'
|
|||||||
|
|
||||||
import functools
|
import functools
|
||||||
|
|
||||||
from PyQt4.Qt import Qt, QStackedWidget, QMenu, \
|
from PyQt4.Qt import (Qt, QStackedWidget, QMenu, QTimer,
|
||||||
QSize, QSizePolicy, QStatusBar, QLabel, QFont
|
QSize, QSizePolicy, QStatusBar, QLabel, QFont)
|
||||||
|
|
||||||
from calibre.utils.config import prefs
|
from calibre.utils.config import prefs
|
||||||
from calibre.constants import (isosx, __appname__, preferred_encoding,
|
from calibre.constants import (isosx, __appname__, preferred_encoding,
|
||||||
@ -274,7 +274,7 @@ class LayoutMixin(object): # {{{
|
|||||||
|
|
||||||
m = self.library_view.model()
|
m = self.library_view.model()
|
||||||
if m.rowCount(None) > 0:
|
if m.rowCount(None) > 0:
|
||||||
self.library_view.set_current_row(0)
|
QTimer.singleShot(0, self.library_view.set_current_row)
|
||||||
m.current_changed(self.library_view.currentIndex(),
|
m.current_changed(self.library_view.currentIndex(),
|
||||||
self.library_view.currentIndex())
|
self.library_view.currentIndex())
|
||||||
self.library_view.setFocus(Qt.OtherFocusReason)
|
self.library_view.setFocus(Qt.OtherFocusReason)
|
||||||
|
@ -777,7 +777,7 @@ class BooksView(QTableView): # {{{
|
|||||||
self.scrollTo(self.model().index(row, i), self.PositionAtCenter)
|
self.scrollTo(self.model().index(row, i), self.PositionAtCenter)
|
||||||
break
|
break
|
||||||
|
|
||||||
def set_current_row(self, row, select=True):
|
def set_current_row(self, row=0, select=True):
|
||||||
if row > -1 and row < self.model().rowCount(QModelIndex()):
|
if row > -1 and row < self.model().rowCount(QModelIndex()):
|
||||||
h = self.horizontalHeader()
|
h = self.horizontalHeader()
|
||||||
logical_indices = list(range(h.count()))
|
logical_indices = list(range(h.count()))
|
||||||
|
@ -18,6 +18,7 @@ from calibre.customize.ui import (initialized_plugins, is_disabled, enable_plugi
|
|||||||
remove_plugin, NameConflict)
|
remove_plugin, NameConflict)
|
||||||
from calibre.gui2 import (NONE, error_dialog, info_dialog, choose_files,
|
from calibre.gui2 import (NONE, error_dialog, info_dialog, choose_files,
|
||||||
question_dialog, gprefs)
|
question_dialog, gprefs)
|
||||||
|
from calibre.gui2.dialogs.confirm_delete import confirm
|
||||||
from calibre.utils.search_query_parser import SearchQueryParser
|
from calibre.utils.search_query_parser import SearchQueryParser
|
||||||
from calibre.utils.icu import lower
|
from calibre.utils.icu import lower
|
||||||
from calibre.constants import iswindows
|
from calibre.constants import iswindows
|
||||||
@ -363,6 +364,12 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
if plugin.do_user_config(self.gui):
|
if plugin.do_user_config(self.gui):
|
||||||
self._plugin_model.refresh_plugin(plugin)
|
self._plugin_model.refresh_plugin(plugin)
|
||||||
elif op == 'remove':
|
elif op == 'remove':
|
||||||
|
if not confirm('<p>' +
|
||||||
|
_('Are you sure you want to remove the plugin: %s?')%
|
||||||
|
'<b>{0}</b>'.format(plugin.name),
|
||||||
|
'confirm_plugin_removal_msg', parent=self):
|
||||||
|
return
|
||||||
|
|
||||||
msg = _('Plugin <b>{0}</b> successfully removed').format(plugin.name)
|
msg = _('Plugin <b>{0}</b> successfully removed').format(plugin.name)
|
||||||
if remove_plugin(plugin):
|
if remove_plugin(plugin):
|
||||||
self._plugin_model.populate()
|
self._plugin_model.populate()
|
||||||
|
@ -196,6 +196,8 @@ class QueueBulk(QProgressDialog):
|
|||||||
dtitle = unicode(mi.title)
|
dtitle = unicode(mi.title)
|
||||||
except:
|
except:
|
||||||
dtitle = repr(mi.title)
|
dtitle = repr(mi.title)
|
||||||
|
if len(dtitle) > 50:
|
||||||
|
dtitle = dtitle[:50].rpartition(' ')[0]+'...'
|
||||||
self.setLabelText(_('Queueing ')+dtitle)
|
self.setLabelText(_('Queueing ')+dtitle)
|
||||||
desc = _('Convert book %(num)d of %(tot)d (%(title)s)') % dict(
|
desc = _('Convert book %(num)d of %(tot)d (%(title)s)') % dict(
|
||||||
num=self.i, tot=len(self.book_ids), title=dtitle)
|
num=self.i, tot=len(self.book_ids), title=dtitle)
|
||||||
|
@ -54,6 +54,8 @@ class Printing(QObject):
|
|||||||
pr.height()/zoomy))
|
pr.height()/zoomy))
|
||||||
evaljs = self.mf.evaluateJavaScript
|
evaljs = self.mf.evaluateJavaScript
|
||||||
loop = QEventLoop(self)
|
loop = QEventLoop(self)
|
||||||
|
pagenum = 0
|
||||||
|
from_, to = printer.fromPage(), printer.toPage()
|
||||||
first = True
|
first = True
|
||||||
|
|
||||||
for path in self.iterator.spine:
|
for path in self.iterator.spine:
|
||||||
@ -74,10 +76,12 @@ class Printing(QObject):
|
|||||||
''')
|
''')
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
if not first:
|
pagenum += 1
|
||||||
printer.newPage()
|
if (pagenum >= from_ and (to == 0 or pagenum <= to)):
|
||||||
first = False
|
if not first:
|
||||||
self.mf.render(painter)
|
printer.newPage()
|
||||||
|
first = False
|
||||||
|
self.mf.render(painter)
|
||||||
nsl = evaljs('paged_display.next_screen_location()').toInt()
|
nsl = evaljs('paged_display.next_screen_location()').toInt()
|
||||||
if not nsl[1] or nsl[0] <= 0: break
|
if not nsl[1] or nsl[0] <= 0: break
|
||||||
evaljs('window.scrollTo(%d, 0)'%nsl[0])
|
evaljs('window.scrollTo(%d, 0)'%nsl[0])
|
||||||
|
@ -23,13 +23,16 @@ FIELDS = set(['title', 'authors', 'author_sort', 'publisher', 'rating',
|
|||||||
'formats', 'isbn', 'uuid', 'pubdate', 'cover', 'last_modified',
|
'formats', 'isbn', 'uuid', 'pubdate', 'cover', 'last_modified',
|
||||||
'identifiers'])
|
'identifiers'])
|
||||||
|
|
||||||
|
do_notify = True
|
||||||
def send_message(msg=''):
|
def send_message(msg=''):
|
||||||
|
global do_notify
|
||||||
|
if not do_notify:
|
||||||
|
return
|
||||||
prints('Notifying calibre of the change')
|
prints('Notifying calibre of the change')
|
||||||
from calibre.utils.ipc import RC
|
from calibre.utils.ipc import RC
|
||||||
import time
|
|
||||||
t = RC(print_error=False)
|
t = RC(print_error=False)
|
||||||
t.start()
|
t.start()
|
||||||
time.sleep(3)
|
t.join(3)
|
||||||
if t.done:
|
if t.done:
|
||||||
t.conn.send('refreshdb:'+msg)
|
t.conn.send('refreshdb:'+msg)
|
||||||
t.conn.close()
|
t.conn.close()
|
||||||
@ -42,16 +45,22 @@ def get_parser(usage):
|
|||||||
parser = OptionParser(usage)
|
parser = OptionParser(usage)
|
||||||
go = parser.add_option_group(_('GLOBAL OPTIONS'))
|
go = parser.add_option_group(_('GLOBAL OPTIONS'))
|
||||||
go.add_option('--library-path', '--with-library', default=None, help=_('Path to the calibre library. Default is to use the path stored in the settings.'))
|
go.add_option('--library-path', '--with-library', default=None, help=_('Path to the calibre library. Default is to use the path stored in the settings.'))
|
||||||
|
go.add_option('--dont-notify-gui', default=False, action='store_true',
|
||||||
|
help=_('Do not notify the running calibre GUI (if any) that the database has'
|
||||||
|
' changed. Use with care, as it can lead to database corruption!'))
|
||||||
|
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def get_db(dbpath, options):
|
def get_db(dbpath, options):
|
||||||
|
global do_notify
|
||||||
if options.library_path is not None:
|
if options.library_path is not None:
|
||||||
dbpath = options.library_path
|
dbpath = options.library_path
|
||||||
if dbpath is None:
|
if dbpath is None:
|
||||||
raise ValueError('No saved library path, either run the GUI or use the'
|
raise ValueError('No saved library path, either run the GUI or use the'
|
||||||
' --with-library option')
|
' --with-library option')
|
||||||
dbpath = os.path.abspath(dbpath)
|
dbpath = os.path.abspath(dbpath)
|
||||||
|
if options.dont_notify_gui:
|
||||||
|
do_notify = False
|
||||||
return LibraryDatabase2(dbpath)
|
return LibraryDatabase2(dbpath)
|
||||||
|
|
||||||
def do_list(db, fields, afields, sort_by, ascending, search_text, line_width, separator,
|
def do_list(db, fields, afields, sort_by, ascending, search_text, line_width, separator,
|
||||||
|
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
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