sync with Kovid's branch

This commit is contained in:
Tomasz Długosz 2012-11-07 20:05:55 +01:00
commit 5d9b34cd17
195 changed files with 8442 additions and 5194 deletions

View File

@ -37,6 +37,5 @@ nbproject/
calibre_plugins/
recipes/.git
recipes/.gitignore
recipes/tv_*.recipe
recipes/README
recipes/katalog_egazeciarz.recipe

View File

@ -28,6 +28,12 @@ License: LGPL-2.1+
The full text of the LGPL is distributed as in
/usr/share/common-licenses/LGPL-2.1 on Debian systems.
Files: src/calibre/utils/fonts/woff/*
Copyright: Jonathan Kew?
License: LGPL-2.1
The full text of the LGPL is distributed as in
/usr/share/common-licenses/LGPL-2.1 on Debian systems.
Files: src/calibre/ebooks/hyphenate.py
Copyright: Copyright (C) 1990, 2004, 2005 Gerard D.C. Kuiken.
License: other

View File

@ -19,6 +19,103 @@
# new recipes:
# - title:
- version: 0.9.5
date: 2012-11-02
new features:
- title: "Font embedding: Add support for the CSS 3 Fonts module, which means you can embed font families that have more that the usual four faces, with the full set of font-stretch and font-weight variations. Of course, whether the fonts actually show up on a reader will depend on the readers' support for CSS 3."
- title: "Sharing by email: Allow specifying an 'alias' or friendly name by which to identify each email recipient."
tickets: [1069076]
- title: "Embedding fonts: Allow adding ttf/otf font files to calibre directly to be used for embedding. That way the fonts do not have to be installed system wide. You can add a font to calibre via the 'Add fonts' button in the font chooser dialog for embedding fonts."
- title: "E-book viewer: Add the ability to rotate images to the popup image viewer."
tickets: [1073513]
- title: "Generate cover: Speedup searching the system for a font that can render special characters"
- title: "A new custom font scanner to locate all fonts on the system. Faster and less crash prone that fontconfig/freetype"
- title: "Font family chooser: Show the faces available for a family when clicking on the family"
bug fixes:
- title: "Get Books: Fix eHarlequin and Kobo stores."
tickets: [1072702]
- title: "Kobo driver: Fix a bug that could cause the on device book matching to fail in certain circumstances."
tickets: [1072437]
- title: "Kobo driver: When using a SD card do not delete shelves that contain on books on the card (there might be books in the shelf in the main memory)."
tickets: [1073792]
- title: "Workaround for bug in the windows API CreateHardLink function that breaks using calibre libraries on some networked filesystems."
- title: "Template editor: Use dummy metadata instead of blank/unknown values"
- title: "Windows: abort setting of title/author if any of the books' files are in use. Results in less surprising behavior than before, when the title/author would be changed, but the on disk location would not."
improved recipes:
- Financial Times UK
- Science AAAS
- The Atlantic
new recipes:
- title: "Pravda in english, italian and portuguese"
author: Darko Miletic
- title: "Delco Times"
author: Krittika Goyal
- version: 0.9.4
date: 2012-10-26
new features:
- title: "Conversion: Add an option to embed a font family into the book."
description: "The embedded font is used as the base font for all text that does not specify its own font family in the input document. Works only with output formats that support font embedding, principally EPUB/AZW3. Option is found under Look & Feel in the conversion dialog. You can ensure that the font is used for all text, regardless of the input document's styles by filtering out font family styles via the Filter Style Information option in the Conversion dialog."
type: major
- title: "When changing the title/author of a book, use hard links instead of copying the books' files, for a large speedup. Only works on filesystems that support hardlinks."
- title: "Linux installer: Resume interrupted downloads and verify the SHA-512 signature of the downloaded file before installing it."
bug fixes:
- title: "Windows: Check if any of the files of a book are in use before changing the title/author, this prevents the creation of duplicate files if one of the files is open in another program"
- title: "Kobo driver: Fix the ondevice status for some books getting lost."
tickets: [1069403]
- title: "Catalogs: Fix regression that broke use of prefix rules."
tickets: [1070086]
- title: "Tag Browser: Fix sorting incorrect for accented letters"
tickets: [1069835]
- title: "Make the bundled Liberation fonts available on all platforms for embedding"
- title: "Use mimetype for fonts from the EPUB 3 specification"
- title: "Get Books: Handle website change that broke the SONY Store plugin"
- title: "Generate cover: If the default font cannot render characters in the metadata (for example for east asian languages) try to automatically find a font on the system that is capable of rendering the characters"
- title: "Fix regression that broke certain types of CSS selectors."
tickets: [1068937]
- title: "Use font-weight:bold instead of font-weight:bolder for the <b> and <strong> tags as ADE cant handle bolder when embedded fonts are used"
improved recipes:
- New York Post
- PC World
- TIME Magazine
- Associated Press
new recipes:
- title: Yazihane
author: A Erdogan
- version: 0.9.3
date: 2012-10-19

View File

@ -72,13 +72,21 @@ After installing Bazaar, you can get the |app| source code with the command::
bzr branch lp:calibre
On Windows you will need the complete path name, that will be something like :file:`C:\\Program Files\\Bazaar\\bzr.exe`. To update a branch
to the latest code, use the command::
On Windows you will need the complete path name, that will be something like :file:`C:\\Program Files\\Bazaar\\bzr.exe`.
To update a branch to the latest code, use the command::
bzr merge
The calibre repository is huge so the branch operation above takes along time (about an hour). If you want to get the code faster, the sourcecode for the latest release is always available as an
`archive <http://status.calibre-ebook.com/dist/src>`_.
|app| is a very large project with a very long source control history, so the
above can take a while (10mins to an hour depending on your internet speed).
If you want to get the code faster, the sourcecode for the latest release is
always available as an `archive <http://status.calibre-ebook.com/dist/src>`_.
You can also use bzr to just download the source code, without the history,
using::
bzr branch --stacked lp:calibre
Submitting your changes to be included
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -109,7 +117,7 @@ Whenever you commit changes to your branch with the command::
bzr commit -m "Comment describing your change"
Kovid can merge it directly from your branch into the main |app| source tree. You should also keep an eye on the |app|
`development forum <http://www.mobileread.com/forums/forumdisplay.php?f=240>`. Before making major changes, you should
`development forum <http://www.mobileread.com/forums/forumdisplay.php?f=240>`_. Before making major changes, you should
discuss them in the forum or contact Kovid directly (his email address is all over the source code).
Windows development environment

View File

@ -327,9 +327,8 @@ You can browse your |app| collection on your Android device is by using the
calibre content server, which makes your collection available over the net.
First perform the following steps in |app|
* Set the :guilabel:`Preferred Output Format` in |app| to EPUB (The output format can be set under :guilabel:`Preferences->Interface->Behavior`)
* Set the output profile to Tablet (this will work for phones as well), under :guilabel:`Preferences->Conversion->Common Options->Page Setup`
* Convert the books you want to read on your device to EPUB format by selecting them and clicking the Convert button.
* Set the :guilabel:`Preferred Output Format` in |app| to EPUB for normal Android devices or MOBI for Kindles (The output format can be set under :guilabel:`Preferences->Interface->Behavior`)
* Convert the books you want to read on your device to EPUB/MOBI format by selecting them and clicking the Convert button.
* Turn on the Content Server in |app|'s preferences and leave |app| running.
Now on your Android device, open the browser and browse to
@ -557,6 +556,27 @@ There can be two reasons why |app| is showing a empty list of books:
* Your metadata.db file was deleted/corrupted. In this case, you can ask |app| to rebuild the metadata.db from its backups. Right click the |app| icon in the |app| toolbar (it will say 0 books underneath it) and select Library maintenance->Restore database. |app| will automatically rebuild metadata.db.
I am getting errors with my calibre library on a networked drive/NAS?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**Do not put your calibre library on a networked drive**.
A filesystem is a complex beast. Most network filesystems lack various
filesystem features that |app| uses. Some dont support file locking, some dont
support hardlinking, some are just flaky. Additionally, |app| is a single user
application, if you accidentally run two copies of |app| on the same networked
library, bad things will happen. Finally, different OSes impose different
limitations on filesystems, so if you share your networked drive across OSes,
once again, bad things *will happen*.
Consider using the |app| Content Server to make your books available on other
computers. Run |app| on a single computer and access it via the Content Server
or a Remote Desktop solution.
If you must share the actual library, use a file syncing tool like
DropBox or rsync or Microsoft SkyDrive instead of a networked drive. Even with
these tools there is danger of data corruption/loss, so only do this if you are
willing to live with that risk.
Content From The Web
---------------------
@ -638,6 +658,9 @@ There are three possible things I know of, that can cause this:
* You are using a Wacom branded mouse. There is an incompatibility between Wacom mice and the graphics toolkit |app| uses. Try using a non-Wacom mouse.
* If you use RoboForm, it is known to cause |app| to crash. Add |app| to
the blacklist of programs inside RoboForm to fix this.
* Sometimes if some software has installed lots of new files in your fonts folder, |app| can crash until it finishes indexing them. Just start |app|, then leave it alone for about 20 minutes, without clicking on anything. After that you should be able to use |app| as normal.
@ -674,7 +697,20 @@ If you still cannot get the installer to work and you are on windows, you can us
My antivirus program claims |app| is a virus/trojan?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Your antivirus program is wrong. Antivirus programs use heuristics, patterns of code that "looks suspicuous" to detect viruses. It's rather like racial profiling. |app| is a completely open source product. You can actually browse the source code yourself (or hire someone to do it for you) to verify that it is not a virus. Please report the false identification to whatever company you buy your antivirus software from. If the antivirus program is preventing you from downloading/installing |app|, disable it temporarily, install |app| and then re-enable it.
The first thing to check is that you are downloading |app| from the official
website: `<http://calibre-ebook.com/download>`_. |app| is a very popular program
and unscrupulous people try to setup websites offering it for download to fool
the unwary.
If you have the official download and your antivirus program is still claiming
|app| is a virus, then, your antivirus program is wrong. Antivirus programs use
heuristics, patterns of code that "look suspicious" to detect viruses. It's
rather like racial profiling. |app| is a completely open source product. You
can actually browse the source code yourself (or hire someone to do it for you)
to verify that it is not a virus. Please report the false identification to
whatever company you buy your antivirus software from. If the antivirus program
is preventing you from downloading/installing |app|, disable it temporarily,
install |app| and then re-enable it.
How do I backup |app|?
~~~~~~~~~~~~~~~~~~~~~~~~~~~

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

BIN
manual/images/sg_pref.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

View File

@ -65,7 +65,7 @@ You create the custom column in the usual way, using Preferences -> Add your own
Then after restarting |app|, you must tell |app| that the column is to be treated as a hierarchy. Go to Preferences -> Look and Feel -> Tag Browser and enter the lookup name "#genre" into the "Categories with hierarchical items" box. Press Apply, and you are done with setting up.
.. image:: images/sg_pref.jpg
.. image:: images/sg_pref.png
:align: center
At the point there are no genres in the column. We are left with the last step: how to apply a genre to a book. A genre does not exist in |app| until it appears on at least one book. To learn how to apply a genre for the first time, we must go into some detail about what a genre looks like in the metadata for a book.

View File

@ -38,8 +38,10 @@ class TheAtlantic(BasicNewsRecipe):
self.timefmt = ' [%s]'%ds
cover = soup.find('img', src=True, attrs={'class':'cover'})
if cover is not None:
self.cover_url = cover['src'].replace(' ', '%20')
self.cover_url = re.sub('\s','%20',re.sub('jpg.*','jpg',cover['src']))
self.log(self.cover_url)
feeds = []
seen_titles = set([])
@ -47,18 +49,16 @@ class TheAtlantic(BasicNewsRecipe):
section_title = self.tag_to_string(section.find('h2'))
self.log('Found section:', section_title)
articles = []
for post in section.findAll('div', attrs={'class':lambda x : x and
'post' in x}):
h = post.find(['h3', 'h4'])
title = self.tag_to_string(h)
for post in section.findAll('h3', attrs={'class':'headline'}):
a = post.find('a', href=True)
title = self.tag_to_string(a)
if title in seen_titles:
continue
seen_titles.add(title)
a = post.find('a', href=True)
url = a['href']
if url.startswith('/'):
url = 'http://www.theatlantic.com'+url
p = post.find('p', attrs={'class':'dek'})
p = post.parent.find('p', attrs={'class':'dek'})
desc = None
self.log('\tFound article:', title, 'at', url)
if p is not None:
@ -69,19 +69,29 @@ class TheAtlantic(BasicNewsRecipe):
if articles:
feeds.append((section_title, articles))
poems = []
self.log('Found section: Poems')
pd = soup.find('h2', text='Poetry').parent.parent
for poem in pd.findAll('h4'):
title = self.tag_to_string(poem)
url = poem.find('a')['href']
rightContent=soup.find('div', attrs = {'class':'rightContent'})
for module in rightContent.findAll('div', attrs={'class':'module'}):
section_title = self.tag_to_string(module.find('h2'))
articles = []
for post in module.findAll('div', attrs={'class':'post'}):
a = post.find('a', href=True)
title = self.tag_to_string(a)
if title in seen_titles:
continue
seen_titles.add(title)
url = a['href']
if url.startswith('/'):
url = 'http://www.theatlantic.com'+url
p = post.parent.find('p', attrs={'class':'dek'})
desc = None
self.log('\tFound article:', title, 'at', url)
poems.append({'title':title, 'url':url, 'description':'',
'date':''})
if poems:
feeds.append(('Poems', poems))
if p is not None:
desc = self.tag_to_string(p)
self.log('\t\t', desc)
articles.append({'title':title, 'url':url, 'description':desc, 'date':''})
if articles:
feeds.append((section_title, articles))
return feeds
@ -100,4 +110,3 @@ class TheAtlantic(BasicNewsRecipe):
table.replaceWith(div)
return soup

View File

@ -0,0 +1,26 @@
from calibre.web.feeds.news import BasicNewsRecipe
class HindustanTimes(BasicNewsRecipe):
title = u'Delcoe Times'
language = 'en'
__author__ = 'Krittika Goyal'
oldest_article = 1 #days
max_articles_per_feed = 25
#encoding = 'cp1252'
use_embedded_content = False
no_stylesheets = True
auto_cleanup = True
feeds = [
('News',
'http://www.delcotimes.com/?rss=news'),
('Sports',
'http://www.delcotimes.com/?rss=sports'),
('Business',
'http://business-news.thestreet.com/the-delaware-county-daily-times/rss/109393'),
('Entertainment',
'http://www.delcotimes.com/?rss=entertainment'),
]

View File

@ -55,7 +55,6 @@ class FinancialTimes(BasicNewsRecipe):
,dict(name='div' , attrs={'class':'standfirst'})
,dict(name='div' , attrs={'id' :'storyContent'})
,dict(name='div' , attrs={'class':['ft-story-body','index-detail']})
,dict(name='div' , attrs={'class':['ft-story-body','index-detail']})
,dict(name='h2' , attrs={'class':'entry-title'} )
,dict(name='span', attrs={'class':lambda x: x and 'posted-on' in x.split()} )
,dict(name='span', attrs={'class':'author_byline'} )
@ -91,7 +90,10 @@ class FinancialTimes(BasicNewsRecipe):
url = rawlink
if not rawlink.startswith('http://'):
url = self.PREFIX + rawlink
try:
urlverified = self.browser.open_novisit(url).geturl() # resolve redirect.
except:
continue
title = self.tag_to_string(item)
date = strftime(self.timefmt)
articles.append({
@ -175,3 +177,6 @@ class FinancialTimes(BasicNewsRecipe):
tfile.close()
self.temp_files.append(tfile)
return tfile.name
def cleanup(self):
self.browser.open('https://registration.ft.com/registration/login/logout?location=')

BIN
recipes/icons/pravda_en.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 538 B

BIN
recipes/icons/pravda_it.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 538 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 538 B

BIN
recipes/icons/pravda_ru.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 538 B

View File

@ -40,6 +40,6 @@ class LondonReviewOfBooks(BasicNewsRecipe):
soup = self.index_to_soup('http://www.lrb.co.uk/')
cover_item = soup.find('p',attrs={'class':'cover'})
if cover_item:
cover_url = 'http://www.lrb.co.uk' + cover_item.a.img['src']
cover_url = cover_item.a.img['src']
return cover_url

View File

@ -1,5 +1,4 @@
from calibre.web.feeds.news import BasicNewsRecipe
from calibre.ebooks.BeautifulSoup import BeautifulSoup
class NewYorkTimesBookReview(BasicNewsRecipe):
title = u'New York Times Book Review'
@ -7,50 +6,16 @@ class NewYorkTimesBookReview(BasicNewsRecipe):
__author__ = 'Krittika Goyal'
oldest_article = 8 #days
max_articles_per_feed = 1000
recursions = 2
#recursions = 2
#encoding = 'latin1'
use_embedded_content = False
no_stylesheets = True
auto_cleanup = True
remove_stylesheets = True
#remove_tags_before = dict(name='h1', attrs={'class':'heading'})
remove_tags_after = dict(name='div', attrs={'id':'authorId'})
remove_tags = [
dict(name='iframe'),
dict(name=['div', 'a'], attrs={'class':['enlargeThis', 'jumpLink']}),
dict(name='div', attrs={'id':['sidebarArticles', 'toolsRight']}),
#dict(name='ul', attrs={'class':'article-tools'}),
#dict(name='ul', attrs={'class':'articleTools'}),
]
match_regexps = [
r'http://www.nytimes.com/.+pagewanted=[2-9]+'
]
feeds = [
('New York Times Sunday Book Review',
'http://feeds.nytimes.com/nyt/rss/SundayBookReview'),
]
def preprocess_html(self, soup):
story = soup.find(name='div', attrs={'id':'article'})
#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)
#for x in soup.findAll(name='p', text=lambda x:x and '--&gt;' in x):
#p = x.findParent('p')
#if p is not None:
#p.extract()
return soup
def postprocess_html(self, soup, first):
for div in soup.findAll(id='pageLinks'):
div.extract()
if not first:
h1 = soup.find('h1')
if h1 is not None:
h1.extract()
t = soup.find(attrs={'class':'timestamp'})
if t is not None:
t.extract()
return soup

53
recipes/pravda_en.recipe Normal file
View File

@ -0,0 +1,53 @@
__license__ = 'GPL v3'
__copyright__ = '2012, Darko Miletic <darko.miletic at gmail.com>'
'''
english.pravda.ru
'''
from calibre.web.feeds.news import BasicNewsRecipe
class Pravda_eng(BasicNewsRecipe):
title = 'Pravda in English'
__author__ = 'Darko Miletic'
description = 'News from Russia and rest of the world'
publisher = 'PRAVDA.Ru'
category = 'news, politics, Russia'
oldest_article = 2
max_articles_per_feed = 200
no_stylesheets = True
encoding = 'utf8'
use_embedded_content = False
language = 'en_RU'
remove_empty_feeds = True
publication_type = 'newspaper'
masthead_url = 'http://english.pravda.ru/pix/logo.gif'
extra_css = """
body{font-family: Arial,sans-serif }
img{margin-bottom: 0.4em; display:block}
"""
conversion_options = {
'comment' : description
, 'tags' : category
, 'publisher' : publisher
, 'language' : language
}
remove_attributes=['lang', 'style']
keep_only_tags = [dict(name='div', attrs={'id':'article'})]
feeds = [
(u'World' , u'http://english.pravda.ru/world/export-articles.xml' )
,(u'Russia' , u'http://english.pravda.ru/russia/export-articles.xml' )
,(u'Society' , u'http://english.pravda.ru/society/export-articles.xml' )
,(u'Incidents', u'http://english.pravda.ru/hotspots/export-articles.xml' )
,(u'Opinion' , u'http://english.pravda.ru/opinion/export-articles.xml' )
,(u'Science' , u'http://english.pravda.ru/science/export-articles.xml' )
,(u'Business' , u'http://english.pravda.ru/business/export-articles.xml' )
,(u'Economics', u'http://english.pravda.ru/russia/economics/export-articles.xml')
,(u'Politics' , u'http://english.pravda.ru/russia/politics/export-articles.xml' )
]
def print_version(self, url):
return url + '?mode=print'

52
recipes/pravda_it.recipe Normal file
View File

@ -0,0 +1,52 @@
__license__ = 'GPL v3'
__copyright__ = '2012, Darko Miletic <darko.miletic at gmail.com>'
'''
italia.pravda.ru
'''
from calibre.web.feeds.news import BasicNewsRecipe
class Pravda_ita(BasicNewsRecipe):
title = 'Pravda in Italiano'
__author__ = 'Darko Miletic'
description = 'News from Russia and rest of the world'
publisher = 'PRAVDA.Ru'
category = 'news, politics, Russia'
oldest_article = 2
max_articles_per_feed = 200
no_stylesheets = True
encoding = 'utf8'
use_embedded_content = False
language = 'it'
remove_empty_feeds = True
publication_type = 'newspaper'
masthead_url = 'http://italia.pravda.ru/pix/logo.gif'
extra_css = """
body{font-family: Arial,sans-serif }
img{margin-bottom: 0.4em; display:block}
"""
conversion_options = {
'comment' : description
, 'tags' : category
, 'publisher' : publisher
, 'language' : language
}
remove_attributes=['lang', 'style']
keep_only_tags = [dict(name='div', attrs={'id':'article'})]
feeds = [
(u'Dal mondo' , u'http://italia.pravda.ru/world/export-articles.xml' )
,(u'Russia' , u'http://italia.pravda.ru/russia/export-articles.xml' )
,(u'Societa' , u'http://italia.pravda.ru/society/export-articles.xml' )
,(u'Avvenimenti', u'http://italia.pravda.ru/hotspots/export-articles.xml' )
,(u'Opinioni' , u'http://italia.pravda.ru/opinion/export-articles.xml' )
,(u'Scienza' , u'http://italia.pravda.ru/science/export-articles.xml' )
,(u'Economia' , u'http://italia.pravda.ru/russia/economics/export-articles.xml')
,(u'Politica' , u'http://italia.pravda.ru/russia/politics/export-articles.xml' )
]
def print_version(self, url):
return url + '?mode=print'

51
recipes/pravda_por.recipe Normal file
View File

@ -0,0 +1,51 @@
__license__ = 'GPL v3'
__copyright__ = '2012, Darko Miletic <darko.miletic at gmail.com>'
'''
port.pravda.ru
'''
from calibre.web.feeds.news import BasicNewsRecipe
class Pravda_port(BasicNewsRecipe):
title = u'Pravda em português'
__author__ = 'Darko Miletic'
description = 'News from Russia and rest of the world'
publisher = 'PRAVDA.Ru'
category = 'news, politics, Russia'
oldest_article = 2
max_articles_per_feed = 200
no_stylesheets = True
encoding = 'utf8'
use_embedded_content = False
language = 'pt'
remove_empty_feeds = True
publication_type = 'newspaper'
masthead_url = 'http://port.pravda.ru/pix/logo.gif'
extra_css = """
body{font-family: Arial,sans-serif }
img{margin-bottom: 0.4em; display:block}
"""
conversion_options = {
'comment' : description
, 'tags' : category
, 'publisher' : publisher
, 'language' : language
}
remove_attributes=['lang', 'style']
keep_only_tags = [dict(name='div', attrs={'id':'article'})]
feeds = [
(u'Mundo' , u'http://port.pravda.ru/mundo/export-articles.xml' )
,(u'Russia' , u'http://port.pravda.ru/russa/export-articles.xml' )
,(u'Sociedade' , u'http://port.pravda.ru/sociedade/export-articles.xml' )
,(u'Cultura' , u'http://port.pravda.ru/sociedade/cultura/export-articles.xml')
,(u'Ciencia' , u'http://port.pravda.ru/science/export-articles.xml' )
,(u'Desporto' , u'http://port.pravda.ru/desporto/export-articles.xml' )
,(u'CPLP' , u'http://port.pravda.ru/cplp/export-articles.xml' )
]
def print_version(self, url):
return url + '?mode=print'

50
recipes/pravda_ru.recipe Normal file
View File

@ -0,0 +1,50 @@
__license__ = 'GPL v3'
__copyright__ = '2012, Darko Miletic <darko.miletic at gmail.com>'
'''
www.pravda.ru
'''
from calibre.web.feeds.news import BasicNewsRecipe
class Pravda_ru(BasicNewsRecipe):
title = u'Правда'
__author__ = 'Darko Miletic'
description = u'Правда.Ру: Аналитика и новости'
publisher = 'PRAVDA.Ru'
category = 'news, politics, Russia'
oldest_article = 2
max_articles_per_feed = 200
no_stylesheets = True
encoding = 'utf8'
use_embedded_content = False
language = 'ru'
remove_empty_feeds = True
publication_type = 'newspaper'
masthead_url = 'http://www.pravda.ru/pix/logo.gif'
extra_css = """
body{font-family: Arial,sans-serif }
img{margin-bottom: 0.4em; display:block}
"""
conversion_options = {
'comment' : description
, 'tags' : category
, 'publisher' : publisher
, 'language' : language
}
remove_attributes=['lang', 'style']
keep_only_tags = [dict(name='div', attrs={'id':'article'})]
feeds = [
(u'Мир' , u'http://www.pravda.ru/world/export.xml' )
,(u'Религия' , u'http://www.pravda.ru/faith/export.xml' )
,(u'Общество' , u'http://www.pravda.ru/society/export.xml' )
,(u'Происшествия', u'http://www.pravda.ru/accidents/export.xml')
,(u'Наука' , u'http://www.pravda.ru/science/export.xml' )
,(u'Экономика' , u'http://www.pravda.ru/economics/export.xml')
,(u'Политика' , u'http://www.pravda.ru/politics/export.xml' )
]
def print_version(self, url):
return url + '?mode=print'

View File

@ -27,7 +27,7 @@ class ScienceAAS(BasicNewsRecipe):
br = BasicNewsRecipe.get_browser()
if self.username is not None and self.password is not None:
br.open(self.LOGIN)
br.select_form(nr=1)
br.select_form(nr=0)
br['username'] = self.username
br['code' ] = self.password
br.submit()

View File

@ -1,5 +1,4 @@
from calibre.web.feeds.news import BasicNewsRecipe
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
class YemenTimesRecipe(BasicNewsRecipe):
__license__ = 'GPL v3'
@ -13,7 +12,7 @@ class YemenTimesRecipe(BasicNewsRecipe):
category = u'News, Opinion, Yemen'
description = u'Award winning weekly from Yemen, promoting press freedom, professional journalism and the defense of human rights.'
oldest_article = 7
oldest_article = 10
max_articles_per_feed = 100
use_embedded_content = False
encoding = 'utf-8'
@ -21,27 +20,13 @@ class YemenTimesRecipe(BasicNewsRecipe):
remove_empty_feeds = True
no_stylesheets = True
remove_javascript = True
auto_cleanup = True
keep_only_tags = []
keep_only_tags.append(dict(name = 'div', attrs = {'id': 'ctl00_ContentPlaceHolder1_MAINNEWS0_Panel1',
'class': 'DMAIN2'}))
remove_attributes = ['style']
INDEX = 'http://www.yementimes.com/'
feeds = []
feeds.append((u'Our Viewpoint', u'http://www.yementimes.com/DEFAULTSUB.ASPX?pnc=6&pnm=OUR%20VIEWPOINT'))
feeds.append((u'Local News', u'http://www.yementimes.com/DEFAULTSUB.ASPX?pnc=3&pnm=Local%20news'))
feeds.append((u'Their News', u'http://www.yementimes.com/DEFAULTSUB.ASPX?pnc=80&pnm=Their%20News'))
feeds.append((u'Report', u'http://www.yementimes.com/DEFAULTSUB.ASPX?pnc=8&pnm=report'))
feeds.append((u'Health', u'http://www.yementimes.com/DEFAULTSUB.ASPX?pnc=51&pnm=health'))
feeds.append((u'Interview', u'http://www.yementimes.com/DEFAULTSUB.ASPX?pnc=77&pnm=interview'))
feeds.append((u'Opinion', u'http://www.yementimes.com/DEFAULTSUB.ASPX?pnc=7&pnm=opinion'))
feeds.append((u'Business', u'http://www.yementimes.com/DEFAULTSUB.ASPX?pnc=5&pnm=business'))
feeds.append((u'Op-Ed', u'http://www.yementimes.com/DEFAULTSUB.ASPX?pnc=81&pnm=Op-Ed'))
feeds.append((u'Culture', u'http://www.yementimes.com/DEFAULTSUB.ASPX?pnc=75&pnm=Culture'))
feeds.append((u'Readers View', u'http://www.yementimes.com/DEFAULTSUB.ASPX?pnc=4&pnm=Readers%20View'))
feeds.append((u'Variety', u'http://www.yementimes.com/DEFAULTSUB.ASPX?pnc=9&pnm=Variety'))
feeds.append((u'Education', u'http://www.yementimes.com/DEFAULTSUB.ASPX?pnc=57&pnm=Education'))
feeds = [
('News',
'http://www.yementimes.com/?tpl=1341'),
]
extra_css = '''
body {font-family:verdana, arial, helvetica, geneva, sans-serif;}
@ -53,73 +38,4 @@ class YemenTimesRecipe(BasicNewsRecipe):
conversion_options = {'comments': description, 'tags': category, 'language': 'en',
'publisher': publisher, 'linearize_tables': True}
def get_browser(self):
br = BasicNewsRecipe.get_browser()
br.set_handle_gzip(True)
return br
def parse_index(self):
answer = []
for feed_title, feed in self.feeds:
soup = self.index_to_soup(feed)
newsbox = soup.find('div', 'newsbox')
main = newsbox.findNextSibling('table')
articles = []
for li in main.findAll('li'):
title = self.tag_to_string(li.a)
url = self.INDEX + li.a['href']
articles.append({'title': title, 'date': None, 'url': url, 'description': '<br/>&nbsp;'})
answer.append((feed_title, articles))
return answer
def preprocess_html(self, soup):
freshSoup = self.getFreshSoup(soup)
headline = soup.find('div', attrs = {'id': 'DVMTIT'})
if headline:
div = headline.findNext('div', attrs = {'id': 'DVTOP'})
img = None
if div:
img = div.find('img')
headline.name = 'h1'
freshSoup.body.append(headline)
if img is not None:
freshSoup.body.append(img)
byline = soup.find('div', attrs = {'id': 'DVTIT'})
if byline:
date_el = byline.find('span')
if date_el:
pub_date = self.tag_to_string(date_el)
date = Tag(soup, 'div', attrs = [('class', 'yemen_date')])
date.append(pub_date)
date_el.extract()
raw = '<br/>'.join(['%s' % (part) for part in byline.findAll(text = True)])
author = BeautifulSoup('<div class="yemen_byline">' + raw + '</div>')
if date is not None:
freshSoup.body.append(date)
freshSoup.body.append(author)
story = soup.find('div', attrs = {'id': 'DVDET'})
if story:
for table in story.findAll('table'):
if table.find('img'):
table['class'] = 'yemen_caption'
freshSoup.body.append(story)
return freshSoup
def getFreshSoup(self, oldSoup):
freshSoup = BeautifulSoup('<html><head><title></title></head><body></body></html>')
if oldSoup.head.title:
freshSoup.head.title.append(self.tag_to_string(oldSoup.head.title))
return freshSoup

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -87,8 +87,6 @@ ft_libs = []
ft_inc_dirs = []
jpg_libs = []
jpg_lib_dirs = []
fc_inc = '/usr/include/fontconfig'
fc_lib = '/usr/lib'
podofo_inc = '/usr/include/podofo'
podofo_lib = '/usr/lib'
chmlib_inc_dirs = chmlib_lib_dirs = []
@ -107,8 +105,6 @@ if iswindows:
'source', 'i18n')]
icu_lib_dirs = [os.path.join(ICU, 'source', 'lib')]
sqlite_inc_dirs = [sw_inc_dir]
fc_inc = os.path.join(sw_inc_dir, 'fontconfig')
fc_lib = sw_lib_dir
chmlib_inc_dirs = consolidate('CHMLIB_INC_DIR', os.path.join(prefix,
'build', 'chmlib-0.40', 'src'))
chmlib_lib_dirs = consolidate('CHMLIB_LIB_DIR', os.path.join(prefix,
@ -131,8 +127,6 @@ if iswindows:
podofo_inc = os.path.join(sw_inc_dir, 'podofo')
podofo_lib = sw_lib_dir
elif isosx:
fc_inc = '/sw/include/fontconfig'
fc_lib = '/sw/lib'
podofo_inc = '/sw/podofo'
podofo_lib = '/sw/lib'
magick_inc_dirs = consolidate('MAGICK_INC',
@ -166,13 +160,6 @@ else:
ft_libs = pkgconfig_libs('freetype2', '', '')
fc_inc = os.environ.get('FC_INC_DIR', fc_inc)
fc_lib = os.environ.get('FC_LIB_DIR', fc_lib)
fc_error = None if os.path.exists(os.path.join(fc_inc, 'fontconfig.h')) else \
('fontconfig header files not found on your system. '
'Try setting the FC_INC_DIR and FC_LIB_DIR environment '
'variables.')
magick_error = None
if not magick_inc_dirs or not os.path.exists(os.path.join(magick_inc_dirs[0],
'wand')):

View File

@ -13,7 +13,7 @@ from multiprocessing import cpu_count
from PyQt4.pyqtconfig import QtGuiModuleMakefile
from setup import Command, islinux, isbsd, isosx, SRC, iswindows
from setup.build_environment import (fc_inc, fc_lib, chmlib_inc_dirs, fc_error,
from setup.build_environment import (chmlib_inc_dirs,
podofo_inc, podofo_lib, podofo_error, pyqt, OSX_SDK, NMAKE, QMAKE,
msvc, MT, win_inc, win_lib, win_ddk, magick_inc_dirs, magick_lib_dirs,
magick_libs, chmlib_lib_dirs, sqlite_inc_dirs, icu_inc_dirs,
@ -48,6 +48,9 @@ class Extension(object):
self.optional = kwargs.get('optional', False)
self.needs_ddk = kwargs.get('needs_ddk', False)
def preflight(self, obj_dir, compiler, linker, builder, cflags, ldflags):
pass
reflow_sources = glob.glob(os.path.join(SRC, 'calibre', 'ebooks', 'pdf', '*.cpp'))
reflow_headers = glob.glob(os.path.join(SRC, 'calibre', 'ebooks', 'pdf', '*.h'))
@ -59,7 +62,6 @@ if isosx:
icu_libs = ['icucore']
icu_cflags = ['-DU_DISABLE_RENAMING'] # Needed to use system libicucore.dylib
extensions = [
Extension('speedup',
@ -122,13 +124,6 @@ extensions = [
libraries=ft_libs,
lib_dirs=ft_lib_dirs),
Extension('fontconfig',
['calibre/utils/fonts/fontconfig.c'],
inc_dirs = [fc_inc],
libraries=['fontconfig'],
lib_dirs=[fc_lib],
error=fc_error),
Extension('woff',
['calibre/utils/fonts/woff/main.c',
'calibre/utils/fonts/woff/woff.c'],
@ -243,6 +238,7 @@ if isunix:
cc = os.environ.get('CC', 'gcc')
cxx = os.environ.get('CXX', 'g++')
cflags = os.environ.get('OVERRIDE_CFLAGS',
# '-Wall -DNDEBUG -ggdb -fno-strict-aliasing -pipe')
'-O3 -Wall -DNDEBUG -fno-strict-aliasing -pipe')
cflags = shlex.split(cflags) + ['-fPIC']
ldflags = os.environ.get('OVERRIDE_LDFLAGS', '-Wall')
@ -305,9 +301,6 @@ class Build(Command):
CFLAGS - Extra compiler flags
LDFLAGS - Extra linker flags
FC_INC_DIR - fontconfig header files
FC_LIB_DIR - fontconfig library
POPPLER_INC_DIR - poppler header files
POPPLER_LIB_DIR - poppler-qt4 library
@ -373,8 +366,9 @@ class Build(Command):
compiler = cxx if ext.needs_cxx else cc
linker = msvc.linker if iswindows else compiler
objects = []
einc = self.inc_dirs_to_cflags(ext.inc_dirs)
obj_dir = self.j(self.obj_dir, ext.name)
ext.preflight(obj_dir, compiler, linker, self, cflags, ldflags)
einc = self.inc_dirs_to_cflags(ext.inc_dirs)
if ext.needs_ddk:
ddk_flags = ['-I'+x for x in win_ddk]
cflags.extend(ddk_flags)
@ -395,7 +389,7 @@ class Build(Command):
dest = self.dest(ext)
elib = self.lib_dirs_to_ldflags(ext.lib_dirs)
xlib = self.libraries_to_ldflags(ext.libraries)
if self.newer(dest, objects):
if self.newer(dest, objects+ext.extra_objs):
print 'Linking', ext.name
cmd = [linker]
if iswindows:

View File

@ -15,8 +15,8 @@ from setup import __version__ as VERSION, __appname__ as APPNAME, basenames, \
LICENSE = open('LICENSE', 'rb').read()
MAGICK_HOME='@executable_path/../Frameworks/ImageMagick'
ENV = dict(
FC_CONFIG_DIR='@executable_path/../Resources/fonts',
FC_CONFIG_FILE='@executable_path/../Resources/fonts/fonts.conf',
FONTCONFIG_PATH='@executable_path/../Resources/fonts',
FONTCONFIG_FILE='@executable_path/../Resources/fonts/fonts.conf',
MAGICK_CONFIGURE_PATH=MAGICK_HOME+'/config',
MAGICK_CODER_MODULE_PATH=MAGICK_HOME+'/modules-Q16/coders',
MAGICK_CODER_FILTER_PATH=MAGICK_HOME+'/modules-Q16/filter',
@ -379,7 +379,7 @@ class Py2App(object):
@flush
def add_poppler(self):
info('\nAdding poppler')
for x in ('libpoppler.27.dylib',):
for x in ('libpoppler.28.dylib',):
self.install_dylib(os.path.join(SW, 'lib', x))
for x in ('pdftohtml', 'pdftoppm', 'pdfinfo'):
self.install_dylib(os.path.join(SW, 'bin', x), False)
@ -411,7 +411,6 @@ class Py2App(object):
raw = open(fc, 'rb').read()
raw = raw.replace('<dir>/usr/share/fonts</dir>', '''\
<dir>/Library/Fonts</dir>
<dir>/Network/Library/Fonts</dir>
<dir>/System/Library/Fonts</dir>
<dir>/usr/X11R6/lib/X11/fonts</dir>
<dir>/usr/share/fonts</dir>

View File

@ -281,8 +281,6 @@ class Win32Freeze(Command, WixMixIn):
for x in ('zlib1.dll', 'libxml2.dll'):
shutil.copy2(self.j(bindir, x+'.manifest'), self.dll_dir)
shutil.copytree(os.path.join(SW, 'etc', 'fonts'),
os.path.join(self.base, 'fontconfig'))
# Copy ImageMagick
for pat in ('*.dll', '*.xml'):
for f in glob.glob(self.j(IMAGEMAGICK, pat)):

View File

@ -276,27 +276,6 @@ cp build/kdewin32-msvc-0.3.9/build/bin/Release/*.exp lib/
cp -r build/kdewin32-msvc-0.3.9/include/msvc/ include/
cp build/kdewin32-msvc-0.3.9/include/*.h include/
fontconfig
---------------
Get it from http://www.winkde.org/pub/kde/ports/win32/repository/win32libs/
mkdir build
Remove subdirectory test from the bottom of CMakeLists.txt
run cmake
Set build type to release and project config to dll
Right click on the fontconfig project and select properties. Add sw/include/msvc to the include paths
Build only fontconfig
cp build/fontconfig-msvc-2.4.2-3/build/src/Release/*.dll bin
cp build/fontconfig-msvc-2.4.2-3/build/src/Release/*.lib lib
cp build/fontconfig-msvc-2.4.2-3/build/src/Release/*.exp lib
cp -r build/fontconfig-msvc-2.4.2-3/fontconfig/ include/
Also install the etc files from the font-config-bin archive from kde win32libs
It contains correct fonts.conf etc.
poppler
-------------

View File

@ -12,14 +12,14 @@ msgstr ""
"Report-Msgid-Bugs-To: Debian iso-codes team <pkg-isocodes-"
"devel@lists.alioth.debian.org>\n"
"POT-Creation-Date: 2011-11-25 14:01+0000\n"
"PO-Revision-Date: 2012-10-21 16:27+0000\n"
"PO-Revision-Date: 2012-10-28 09:28+0000\n"
"Last-Translator: Ferran Rius <frius64@hotmail.com>\n"
"Language-Team: Catalan <linux@softcatala.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-10-22 04:39+0000\n"
"X-Generator: Launchpad (build 16165)\n"
"X-Launchpad-Export-Date: 2012-10-29 04:59+0000\n"
"X-Generator: Launchpad (build 16194)\n"
"Language: ca\n"
#. name for aaa
@ -10536,43 +10536,43 @@ msgstr "Izere"
#. name for jaa
msgid "Jamamadí"
msgstr ""
msgstr "Jamamadí"
#. name for jab
msgid "Hyam"
msgstr ""
msgstr "Ham"
#. name for jac
msgid "Popti'"
msgstr ""
msgstr "Jacaltec"
#. name for jad
msgid "Jahanka"
msgstr ""
msgstr "Jahanka"
#. name for jae
msgid "Yabem"
msgstr ""
msgstr "Yabem"
#. name for jaf
msgid "Jara"
msgstr ""
msgstr "Jara"
#. name for jah
msgid "Jah Hut"
msgstr ""
msgstr "Jah Hut"
#. name for jaj
msgid "Zazao"
msgstr ""
msgstr "Zazao"
#. name for jak
msgid "Jakun"
msgstr ""
msgstr "Jakun"
#. name for jal
msgid "Yalahatan"
msgstr ""
msgstr "Jalahatan"
#. name for jam
msgid "Creole English; Jamaican"
@ -10580,31 +10580,31 @@ msgstr "Anglès crioll; Jamaica"
#. name for jao
msgid "Yanyuwa"
msgstr ""
msgstr "Yanyula"
#. name for jaq
msgid "Yaqay"
msgstr ""
msgstr "Yaqay"
#. name for jar
msgid "Jarawa (Nigeria)"
msgstr ""
msgstr "Jarawa (Nigèria)"
#. name for jas
msgid "Javanese; New Caledonian"
msgstr ""
msgstr "Javanès; Nova Caledònia"
#. name for jat
msgid "Jakati"
msgstr ""
msgstr "Jakati"
#. name for jau
msgid "Yaur"
msgstr ""
msgstr "Yaur"
#. name for jav
msgid "Javanese"
msgstr ""
msgstr "Javanès"
#. name for jax
msgid "Malay; Jambi"
@ -10612,11 +10612,11 @@ msgstr "Malai; Jambi"
#. name for jay
msgid "Yan-nhangu"
msgstr ""
msgstr "Jarnango"
#. name for jaz
msgid "Jawe"
msgstr ""
msgstr "Jawe"
#. name for jbe
msgid "Judeo-Berber"
@ -10624,27 +10624,27 @@ msgstr "Judeo-berber"
#. name for jbj
msgid "Arandai"
msgstr ""
msgstr "Arandai"
#. name for jbn
msgid "Nafusi"
msgstr ""
msgstr "Djerbi"
#. name for jbo
msgid "Lojban"
msgstr ""
msgstr "Lojban"
#. name for jbr
msgid "Jofotek-Bromnya"
msgstr ""
msgstr "Jofotek-Bromnya"
#. name for jbt
msgid "Jabutí"
msgstr ""
msgstr "Jaboti"
#. name for jbu
msgid "Jukun Takum"
msgstr ""
msgstr "Jukun Takum"
#. name for jcs
msgid "Jamaican Country Sign Language"
@ -10652,31 +10652,31 @@ msgstr "Llenguatge de signes del país jamaicà"
#. name for jct
msgid "Krymchak"
msgstr ""
msgstr "Judeocrimeà"
#. name for jda
msgid "Jad"
msgstr ""
msgstr "Jad"
#. name for jdg
msgid "Jadgali"
msgstr ""
msgstr "Jadgali"
#. name for jdt
msgid "Judeo-Tat"
msgstr ""
msgstr "Judeotat"
#. name for jeb
msgid "Jebero"
msgstr ""
msgstr "Jebero"
#. name for jee
msgid "Jerung"
msgstr ""
msgstr "Jerung"
#. name for jeg
msgid "Jeng"
msgstr ""
msgstr "Jeng"
#. name for jeh
msgid "Jeh"
@ -11012,7 +11012,7 @@ msgstr ""
#. name for jvn
msgid "Javanese; Caribbean"
msgstr ""
msgstr "Javanès; Carib"
#. name for jwi
msgid "Jwira-Pepesa"

View File

@ -9,14 +9,14 @@ msgstr ""
"Report-Msgid-Bugs-To: Debian iso-codes team <pkg-isocodes-"
"devel@lists.alioth.debian.org>\n"
"POT-Creation-Date: 2011-11-25 14:01+0000\n"
"PO-Revision-Date: 2012-04-18 13:08+0000\n"
"Last-Translator: Asier Iturralde Sarasola <Unknown>\n"
"PO-Revision-Date: 2012-10-29 14:16+0000\n"
"Last-Translator: gorkaazk <gorkaazkarate@euskalerria.org>\n"
"Language-Team: Euskara <itzulpena@comtropos.com>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-04-19 04:36+0000\n"
"X-Generator: Launchpad (build 15108)\n"
"X-Launchpad-Export-Date: 2012-10-30 04:44+0000\n"
"X-Generator: Launchpad (build 16206)\n"
"Language: eu\n"
#. name for aaa
@ -73,7 +73,7 @@ msgstr "Anambé"
#. name for aao
msgid "Arabic; Algerian Saharan"
msgstr ""
msgstr "Arabiera, Aljeriako Saharakoa"
#. name for aap
msgid "Arára; Pará"
@ -181,31 +181,32 @@ msgstr "Abazera"
#. name for abr
msgid "Abron"
msgstr ""
msgstr "Abron; (bono hizkuntza, Ghana)"
#. name for abs
msgid "Malay; Ambonese"
msgstr ""
msgstr "Malaysiera; (\"ambonese\" hizkuntza)"
#. name for abt
msgid "Ambulas"
msgstr ""
msgstr "Ambulas hizkuntza"
#. name for abu
msgid "Abure"
msgstr ""
"Abure hizkuntza (edo abonwa; edo akaplass) (Niger, Kongo, Boli-kosta)"
#. name for abv
msgid "Arabic; Baharna"
msgstr ""
msgstr "Arabiera; baharna"
#. name for abw
msgid "Pal"
msgstr ""
msgstr "Pal hizkuntza (Papua)"
#. name for abx
msgid "Inabaknon"
msgstr ""
msgstr "Inabaknon hizkuntza (edo abaknon, Filipina uharteak)"
#. name for aby
msgid "Aneme Wake"

View File

@ -690,29 +690,6 @@ def remove_bracketed_text(src,
buf.append(char)
return u''.join(buf)
def load_builtin_fonts():
# On linux these are loaded by fontconfig which means that
# they are available to Qt as well, since Qt uses fontconfig
from calibre.utils.fonts import fontconfig
fontconfig
families = {u'Liberation Serif', u'Liberation Sans', u'Liberation Mono'}
if iswindows or isosx:
import glob
from PyQt4.Qt import QFontDatabase
families = set()
for f in glob.glob(P('fonts/liberation/*.ttf')):
with open(f, 'rb') as s:
# Windows requires font files to be executable for them to be
# loaded successfully, so we use the in memory loader
fid = QFontDatabase.addApplicationFontFromData(s.read())
if fid > -1:
families |= set(map(unicode,
QFontDatabase.applicationFontFamilies(fid)))
return families
def ipython(user_ns=None):
from calibre.utils.ipython import ipython
ipython(user_ns=user_ns)

View File

@ -4,7 +4,7 @@ __license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
__docformat__ = 'restructuredtext en'
__appname__ = u'calibre'
numeric_version = (0, 9, 3)
numeric_version = (0, 9, 5)
__version__ = u'.'.join(map(unicode, numeric_version))
__author__ = u"Kovid Goyal <kovid@kovidgoyal.net>"
@ -36,6 +36,7 @@ isunix = isosx or islinux
isportable = os.environ.get('CALIBRE_PORTABLE_BUILD', None) is not None
ispy3 = sys.version_info.major > 2
isxp = iswindows and sys.getwindowsversion().major < 6
isworker = os.environ.has_key('CALIBRE_WORKER') or os.environ.has_key('CALIBRE_SIMPLE_WORKER')
try:
preferred_encoding = locale.getpreferredencoding()
@ -83,7 +84,6 @@ class Plugins(collections.Mapping):
'magick',
'podofo',
'cPalmdoc',
'fontconfig',
'progress_indicator',
'chmlib',
'chm_extra',

View File

@ -1394,6 +1394,16 @@ class StoreEKnigiStore(StoreBase):
formats = ['EPUB', 'PDF', 'HTML']
affiliate = True
class StoreEmpikStore(StoreBase):
name = 'Empik'
author = u'Tomasz Długosz'
description = u'Empik to marka o unikalnym dziedzictwie i legendarne miejsce, dawne “okno na świat”. Jest obecna w polskim krajobrazie kulturalnym od 60 lat (wcześniej jako Kluby Międzynarodowej Prasy i Książki).'
actual_plugin = 'calibre.gui2.store.stores.empik_plugin:EmpikStore'
headquarters = 'PL'
formats = ['EPUB', 'MOBI', 'PDF']
affiliate = True
class StoreEscapeMagazineStore(StoreBase):
name = 'EscapeMagazine'
author = u'Tomasz Długosz'
@ -1661,6 +1671,7 @@ plugins += [
StoreEbooksGratuitsStore,
StoreEHarlequinStore,
StoreEKnigiStore,
StoreEmpikStore,
StoreEscapeMagazineStore,
StoreFeedbooksStore,
StoreFoylesUKStore,

View File

@ -19,6 +19,8 @@ Run an embedded python interpreter.
''')
parser.add_option('-c', '--command', help='Run python code.', default=None)
parser.add_option('-e', '--exec-file', default=None, help='Run the python code in file.')
parser.add_option('-f', '--subset-font', default=False,
action='store_true', help='Subset the specified font')
parser.add_option('-d', '--debug-device-driver', default=False, action='store_true',
help='Debug the specified device driver.')
parser.add_option('-g', '--gui', default=False, action='store_true',
@ -209,6 +211,11 @@ def main(args=sys.argv):
execfile(ef, g)
return
if len(args) > 1 and args[1] in ('-f', '--subset-font'):
from calibre.utils.fonts.sfnt.subset import main
main(['subset-font']+args[2:])
return
opts, args = option_parser().parse_args(args)
if opts.gui:
from calibre.gui2.main import main

View File

@ -212,7 +212,7 @@ class ANDROID(USBMS):
'VIZIO', 'GOOGLE', 'FREESCAL', 'KOBO_INC', 'LENOVO', 'ROCKCHIP',
'POCKET', 'ONDA_MID', 'ZENITHIN', 'INGENIC', 'PMID701C', 'PD',
'PMP5097C', 'MASS', 'NOVO7', 'ZEKI', 'COBY', 'SXZ', 'USB_2.0',
'COBY_MID', 'VS', 'AINOL', 'TOPWISE']
'COBY_MID', 'VS', 'AINOL', 'TOPWISE', 'PAD703']
WINDOWS_MAIN_MEM = ['ANDROID_PHONE', 'A855', 'A853', 'INC.NEXUS_ONE',
'__UMS_COMPOSITE', '_MB200', 'MASS_STORAGE', '_-_CARD', 'SGH-I897',
'GT-I9000', 'FILE-STOR_GADGET', 'SGH-T959_CARD', 'SGH-T959', 'SAMSUNG_ANDROID',

View File

@ -59,6 +59,7 @@ class Book(Book_):
self.contentID = None
self.current_shelves = []
self.kobo_collections = []
if thumbnail_name is not None:
self.thumbnail = ImageWrapper(thumbnail_name)
@ -99,6 +100,10 @@ class KTCollectionsBookList(CollectionsBookList):
lpath = getattr(book, 'lpath', None)
if lpath is None:
continue
# If the book is not in the current library, we don't want to use the metadtaa for the collections
if book.application_id is None:
# debug_print("KTCollectionsBookList:get_collections - Book not in current library")
continue
# Decide how we will build the collections. The default: leave the
# book in all existing collections. Do not add any new ones.
attrs = ['device_collections']
@ -115,7 +120,8 @@ class KTCollectionsBookList(CollectionsBookList):
elif prefs['manage_device_metadata'] == 'on_connect':
# For existing books, modify the collections only if the user
# specified 'on_connect'
attrs += collection_attributes
attrs = collection_attributes
book.device_collections = []
if show_debug:
debug_print("KTCollectionsBookList:get_collections - attrs=", attrs)

View File

@ -33,7 +33,7 @@ class KOBO(USBMS):
gui_name = 'Kobo Reader'
description = _('Communicate with the Kobo Reader')
author = 'Timothy Legge and David Forrester'
version = (2, 0, 2)
version = (2, 0, 3)
dbversion = 0
fwversion = 0
@ -653,6 +653,7 @@ class KOBO(USBMS):
@classmethod
def book_from_path(cls, prefix, lpath, title, authors, mime, date, ContentType, ImageID):
# debug_print("KOBO:book_from_path - title=%s"%title)
from calibre.ebooks.metadata import MetaInformation
if cls.settings().read_metadata or cls.MUST_READ_METADATA:
@ -1199,7 +1200,7 @@ class KOBOTOUCH(KOBO):
author = 'David Forrester'
description = 'Communicate with the Kobo Touch, Glo and Mini firmware. Based on the existing Kobo driver by %s.' % (KOBO.author)
supported_dbversion = 65
supported_dbversion = 70
min_supported_dbversion = 53
booklist_class = KTCollectionsBookList
@ -1408,10 +1409,15 @@ class KOBOTOUCH(KOBO):
debug_print("KoboTouch:update_booklist - have a deleted book")
# Label Previews
if accessibility == 6:
if isdownloaded == 'false':
playlist_map[lpath].append('Recommendation')
else:
playlist_map[lpath].append('Preview')
elif accessibility == 4:
playlist_map[lpath].append('Recommendation')
kobo_collections = playlist_map[lpath][:]
if len(bookshelves) > 0:
playlist_map[lpath].extend(bookshelves)
@ -1428,13 +1434,15 @@ class KOBOTOUCH(KOBO):
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 - bookshelves=', bookshelves)
debug_print('KoboTouch:update_booklist - kobo_collections=', kobo_collections)
debug_print('KoboTouch:update_booklist - series="%s"' % bl[idx].series)
debug_print('KoboTouch:update_booklist - the book=', bl[idx])
debug_print('KoboTouch:update_booklist - the authors=', bl[idx].authors)
debug_print('KoboTouch:update_booklist - application_id=', bl[idx].application_id)
bl_cache[lpath] = None
if bl[idx].title_sort is not None:
bl[idx].title = bl[idx].title_sort
# removed to allow recognizing of ePub with an UUID inside
# if bl[idx].title_sort is not None:
# bl[idx].title = bl[idx].title_sort
if ImageID is not None:
imagename = self.imagefilename_from_imageID(ImageID)
if imagename is not None:
@ -1454,8 +1462,9 @@ class KOBOTOUCH(KOBO):
if lpath in playlist_map:
bl[idx].device_collections = playlist_map.get(lpath,[])
changed = True
bl[idx].current_shelves = bookshelves
bl[idx].kobo_collections = kobo_collections
changed = True
if show_debug:
debug_print('KoboTouch:update_booklist - updated bl[idx].device_collections=', bl[idx].device_collections)
@ -1490,10 +1499,12 @@ class KOBOTOUCH(KOBO):
debug_print(" the book:", book)
debug_print(" author_sort:'%s'"%book.author_sort)
debug_print(" bookshelves:", bookshelves)
debug_print(" kobo_collections:", kobo_collections)
# print 'Update booklist'
book.device_collections = playlist_map.get(lpath,[])# if lpath in playlist_map else []
book.current_shelves = bookshelves
book.kobo_collections = kobo_collections
book.contentID = ContentID
# debug_print('KoboTouch:update_booklist - title=', title, 'book.device_collections', book.device_collections)
@ -1630,7 +1641,8 @@ class KOBOTOUCH(KOBO):
#print "count found in cache: %d, count of files in metadata: %d, need_sync: %s" % \
# (len(bl_cache), len(bl), need_sync)
# Bypassing the KOBO sync_booklists as that does things we don't need to do
if need_sync: #self.count_found_in_bl != len(bl) or need_sync:
# Also forcing sync to see if this solves issues with updating shelves and matching books.
if need_sync or True: #self.count_found_in_bl != len(bl) or need_sync:
debug_print("KoboTouch:books - about to sync_booklists")
if oncard == 'cardb':
USBMS.sync_booklists(self, (None, None, bl))
@ -1948,7 +1960,6 @@ class KOBOTOUCH(KOBO):
debug_print("Booklists=", booklists)
if self.dbversion < 53:
self.reset_readstatus(connection, oncard)
self.remove_from_bookshelves(connection, oncard)
if self.dbversion >= 14:
debug_print("No Collections - reseting FavouritesIndex")
self.reset_favouritesindex(connection, oncard)
@ -1961,6 +1972,7 @@ class KOBOTOUCH(KOBO):
if book.application_id is not None:
# debug_print("KoboTouch:update_device_database_collections - about to remove a book from shelves book.title=%s" % book.title)
self.remove_book_from_device_bookshelves(connection, book)
book.device_collections.extend(book.kobo_collections)
if not prefs['manage_device_metadata'] == 'manual' and delete_empty_shelves:
debug_print("KoboTouch:update_device_database_collections - about to clear empty bookshelves")
self.delete_empty_bookshelves(connection)
@ -2096,7 +2108,7 @@ class KOBOTOUCH(KOBO):
def remove_book_from_device_bookshelves(self, connection, book):
show_debug = self.is_debugging_title(book.title)# or True
remove_shelf_list = set(book.current_shelves) - set(book.device_collections)# - set(["Im_Reading", "Read", "Closed"])
remove_shelf_list = set(book.current_shelves) - set(book.device_collections)
if show_debug:
debug_print('KoboTouch:remove_book_from_device_bookshelves - book.application_id="%s"'%book.application_id)
@ -2212,11 +2224,8 @@ class KOBOTOUCH(KOBO):
debug_print('KoboTouch:check_for_bookshelf bookshelf_name="%s"'%bookshelf_name)
test_query = 'SELECT InternalName, Name, _IsDeleted FROM Shelf WHERE Name = ?'
test_values = (bookshelf_name, )
addquery = 'INSERT INTO "main"."Shelf"'\
' ("CreationDate","InternalName","LastModified","Name","_IsDeleted","_IsVisible","_IsSynced")'\
' VALUES (?, ?, ?, ?, ?, ?, ?)'
add_values = (
time.strftime(self.TIMESTAMP_STRING, time.gmtime()),
addquery = 'INSERT INTO "main"."Shelf"'
add_values = (time.strftime(self.TIMESTAMP_STRING, time.gmtime()),
bookshelf_name,
time.strftime(self.TIMESTAMP_STRING, time.gmtime()),
bookshelf_name,
@ -2224,6 +2233,17 @@ class KOBOTOUCH(KOBO):
"true",
"false",
)
if self.dbversion < 64:
addquery += ' ("CreationDate","InternalName","LastModified","Name","_IsDeleted","_IsVisible","_IsSynced")'\
' VALUES (?, ?, ?, ?, ?, ?, ?)'
else:
addquery += ' ("CreationDate", "InternalName","LastModified","Name","_IsDeleted","_IsVisible","_IsSynced", "Id")'\
' VALUES (?, ?, ?, ?, ?, ?, ?, ?)'
add_values = add_values +(bookshelf_name,)
if show_debug:
debug_print('KoboTouch:check_for_bookshelf addquery=', addquery)
debug_print('KoboTouch:check_for_bookshelf add_values=', add_values)
updatequery = 'UPDATE Shelf SET _IsDeleted = "false" WHERE Name = ?'
cursor = connection.cursor()

View File

@ -114,7 +114,7 @@ class MTP_DEVICE(BASE):
except:
prints('Failed to load existing driveinfo.calibre file, with error:')
traceback.print_exc()
dinfo = None
dinfo = {}
if dinfo.get('device_store_uuid', None) is None:
dinfo['device_store_uuid'] = unicode(uuid.uuid4())
if dinfo.get('device_name', None) is None:

View File

@ -901,6 +901,9 @@ class Device(DeviceConfig, DevicePlugin):
for d in drives:
try:
winutil.eject_drive(bytes(d)[0])
except Exception as e:
try:
prints(as_unicode(e))
except:
pass

View File

@ -254,7 +254,6 @@ def unit_convert(value, base, font, dpi):
def generate_masthead(title, output_path=None, width=600, height=60):
from calibre.ebooks.conversion.config import load_defaults
from calibre.utils.fonts import fontconfig
from calibre.utils.config import tweaks
fp = tweaks['generate_cover_title_font']
if not fp:
@ -264,11 +263,10 @@ def generate_masthead(title, output_path=None, width=600, height=60):
masthead_font_family = recs.get('masthead_font', 'Default')
if masthead_font_family != 'Default':
masthead_font = fontconfig.files_for_family(masthead_font_family)
# Assume 'normal' always in dict, else use default
# {'normal': (path_to_font, friendly name)}
if 'normal' in masthead_font:
font_path = masthead_font['normal'][0]
from calibre.utils.fonts.scanner import font_scanner
faces = font_scanner.fonts_for_family(masthead_font_family)
if faces:
font_path = faces[0]['path']
if not font_path or not os.access(font_path, os.R_OK):
font_path = default_font

View File

@ -133,6 +133,7 @@ def add_pipeline_options(parser, plumber):
[
'base_font_size', 'disable_font_rescaling',
'font_size_mapping', 'embed_font_family',
'subset_embedded_fonts',
'line_height', 'minimum_line_height',
'linearize_tables',
'extra_css', 'filter_css',

View File

@ -150,8 +150,15 @@ class EPUBInput(InputFormatPlugin):
from calibre import walk
from calibre.ebooks import DRMError
from calibre.ebooks.metadata.opf2 import OPF
try:
zf = ZipFile(stream)
zf.extractall(os.getcwdu())
except:
log.exception('EPUB appears to be invalid ZIP file, trying a'
' more forgiving ZIP parser')
from calibre.utils.localunzip import extractall
stream.seek(0)
extractall(stream)
encfile = os.path.abspath(os.path.join('META-INF', 'encryption.xml'))
opf = self.find_opf()
if opf is None:

View File

@ -204,6 +204,17 @@ OptionRecommendation(name='embed_font_family',
'with some output formats, principally EPUB and AZW3.')
),
OptionRecommendation(name='subset_embedded_fonts',
recommended_value=False, level=OptionRecommendation.LOW,
help=_(
'Subset all embedded fonts. Every embedded font is reduced '
'to contain only the glyphs used in this document. This decreases '
'the size of the font files. Useful if you are embedding a '
'particularly large font with lots of unused glyphs. Note that '
'subsetting is only supported for fonts that contain TrueType '
'outlines, not Postscript outlines.')
),
OptionRecommendation(name='linearize_tables',
recommended_value=False, level=OptionRecommendation.LOW,
help=_('Some badly designed documents use tables to control the '
@ -1112,6 +1123,10 @@ OptionRecommendation(name='search_replace',
RemoveFakeMargins()(self.oeb, self.log, self.opts)
RemoveAdobeMargins()(self.oeb, self.log, self.opts)
if self.opts.subset_embedded_fonts:
from calibre.ebooks.oeb.transforms.subset import SubsetFonts
SubsetFonts()(self.oeb, self.log, self.opts)
pr(0.9)
self.flush()

View File

@ -34,24 +34,24 @@ class PRS500_PROFILE(object):
name = 'prs500'
def find_custom_fonts(options, logger):
from calibre.utils.fonts import fontconfig
files_for_family = fontconfig.files_for_family
from calibre.utils.fonts.scanner import font_scanner
fonts = {'serif' : None, 'sans' : None, 'mono' : None}
def family(cmd):
return cmd.split(',')[-1].strip()
if options.serif_family:
f = family(options.serif_family)
fonts['serif'] = files_for_family(f)
fonts['serif'] = font_scanner.legacy_fonts_for_family(f)
print (111111, fonts['serif'])
if not fonts['serif']:
logger.warn('Unable to find serif family %s'%f)
if options.sans_family:
f = family(options.sans_family)
fonts['sans'] = files_for_family(f)
fonts['sans'] = font_scanner.legacy_fonts_for_family(f)
if not fonts['sans']:
logger.warn('Unable to find sans family %s'%f)
if options.mono_family:
f = family(options.mono_family)
fonts['mono'] = files_for_family(f)
fonts['mono'] = font_scanner.legacy_fonts_for_family(f)
if not fonts['mono']:
logger.warn('Unable to find mono family %s'%f)
return fonts

View File

@ -10,6 +10,7 @@ from cStringIO import StringIO
from contextlib import closing
from calibre.utils.zipfile import ZipFile, BadZipfile, safe_replace
from calibre.utils.localunzip import LocalZipFile
from calibre.ebooks.BeautifulSoup import BeautifulStoneSoup
from calibre.ebooks.metadata import MetaInformation
from calibre.ebooks.metadata.opf2 import OPF
@ -105,6 +106,9 @@ class OCFReader(OCF):
class OCFZipReader(OCFReader):
def __init__(self, stream, mode='r', root=None):
if isinstance(stream, (LocalZipFile, ZipFile)):
self.archive = stream
else:
try:
self.archive = ZipFile(stream, mode=mode)
except BadZipfile:
@ -119,8 +123,18 @@ class OCFZipReader(OCFReader):
super(OCFZipReader, self).__init__()
def open(self, name, mode='r'):
if isinstance(self.archive, LocalZipFile):
return self.archive.open(name)
return StringIO(self.archive.read(name))
def get_zip_reader(stream, root=None):
try:
zf = ZipFile(stream, mode='r')
except:
stream.seek(0)
zf = LocalZipFile(stream)
return OCFZipReader(zf, root=root)
class OCFDirReader(OCFReader):
def __init__(self, path):
self.root = path
@ -184,7 +198,12 @@ def render_cover(opf, opf_path, zf, reader=None):
def get_cover(opf, opf_path, stream, reader=None):
raster_cover = opf.raster_cover
stream.seek(0)
try:
zf = ZipFile(stream)
except:
stream.seek(0)
zf = LocalZipFile(stream)
if raster_cover:
base = posixpath.dirname(opf_path)
cpath = posixpath.normpath(posixpath.join(base, raster_cover))
@ -207,7 +226,7 @@ def get_cover(opf, opf_path, stream, reader=None):
def get_metadata(stream, extract_cover=True):
""" Return metadata as a :class:`Metadata` object """
stream.seek(0)
reader = OCFZipReader(stream)
reader = get_zip_reader(stream)
mi = reader.opf.to_book_metadata()
if extract_cover:
try:
@ -232,7 +251,7 @@ def _write_new_cover(new_cdata, cpath):
def set_metadata(stream, mi, apply_null=False, update_timestamp=False):
stream.seek(0)
reader = OCFZipReader(stream, root=os.getcwdu())
reader = get_zip_reader(stream, root=os.getcwdu())
raster_cover = reader.opf.raster_cover
mi = MetaInformation(mi)
new_cdata = None
@ -283,6 +302,10 @@ def set_metadata(stream, mi, apply_null=False, update_timestamp=False):
reader.opf.timestamp = mi.timestamp
newopf = StringIO(reader.opf.render())
if isinstance(reader.archive, LocalZipFile):
reader.archive.safe_replace(reader.container[OPF.MIMETYPE], newopf,
extra_replacements=replacements)
else:
safe_replace(stream, reader.container[OPF.MIMETYPE], newopf,
extra_replacements=replacements)
try:

View File

@ -178,44 +178,40 @@ class CSSFlattener(object):
body_font_family = None
if not family:
return body_font_family, efi
from calibre.utils.fonts import fontconfig
from calibre.utils.fonts.utils import (get_font_characteristics,
panose_to_css_generic_family, get_font_names)
faces = fontconfig.fonts_for_family(family)
if not faces or not u'normal' in faces:
from calibre.utils.fonts.scanner import font_scanner
from calibre.utils.fonts.utils import panose_to_css_generic_family
faces = font_scanner.fonts_for_family(family)
if not faces:
msg = (u'No embeddable fonts found for family: %r'%self.opts.embed_font_family)
if failure_critical:
raise ValueError(msg)
self.oeb.log.warn(msg)
return body_font_family, efi
for k, v in faces.iteritems():
ext, data = v[0::2]
weight, is_italic, is_bold, is_regular, fs_type, panose = \
get_font_characteristics(data)
generic_family = panose_to_css_generic_family(panose)
family_name, subfamily_name, full_name = get_font_names(data)
if k == u'normal':
body_font_family = u"'%s',%s"%(family_name, generic_family)
if family_name.lower() != family.lower():
self.oeb.log.warn(u'Failed to find an exact match for font:'
u' %r, using %r instead'%(family, family_name))
else:
self.oeb.log(u'Embedding font: %s'%family_name)
font = {u'font-family':u'"%s"'%family_name}
if is_italic:
font[u'font-style'] = u'italic'
if is_bold:
font[u'font-weight'] = u'bold'
for i, font in enumerate(faces):
ext = 'otf' if font['is_otf'] else 'ttf'
fid, href = self.oeb.manifest.generate(id=u'font',
href=u'%s.%s'%(ascii_filename(full_name).replace(u' ', u'-'), ext))
href=u'%s.%s'%(ascii_filename(font['full_name']).replace(u' ', u'-'), ext))
item = self.oeb.manifest.add(fid, href,
guess_type(full_name+'.'+ext)[0],
data=data)
guess_type('dummy.'+ext)[0],
data=font_scanner.get_font_data(font))
item.unload_data_from_memory()
font[u'src'] = u'url(%s)'%item.href
cfont = {
u'font-family':u'"%s"'%font['font-family'],
u'panose-1': u' '.join(map(unicode, font['panose'])),
u'src': u'url(%s)'%item.href,
}
if i == 0:
generic_family = panose_to_css_generic_family(font['panose'])
body_font_family = u"'%s',%s"%(font['font-family'], generic_family)
self.oeb.log(u'Embedding font: %s'%font['font-family'])
for k in (u'font-weight', u'font-style', u'font-stretch'):
if font[k] != u'normal':
cfont[k] = font[k]
rule = '@font-face { %s }'%('; '.join(u'%s:%s'%(k, v) for k, v in
font.iteritems()))
cfont.iteritems()))
rule = cssutils.parseString(rule)
efi.append(rule)

View File

@ -0,0 +1,284 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:fdm=marker:ai
from __future__ import (unicode_literals, division, absolute_import,
print_function)
__license__ = 'GPL v3'
__copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
from collections import defaultdict
from calibre.ebooks.oeb.base import urlnormalize
from calibre.utils.fonts.sfnt.subset import subset, NoGlyphs, UnsupportedFont
class SubsetFonts(object):
'''
Subset all embedded fonts. Must be run after CSS flattening, as it requires
CSS normalization and flattening to work.
'''
def __call__(self, oeb, log, opts):
self.oeb, self.log, self.opts = oeb, log, opts
self.find_embedded_fonts()
if not self.embedded_fonts:
self.log.debug('No embedded fonts found')
return
self.find_style_rules()
self.find_font_usage()
totals = [0, 0]
def remove(font):
totals[1] += len(font['item'].data)
self.oeb.manifest.remove(font['item'])
font['rule'].parentStyleSheet.deleteRule(font['rule'])
for font in self.embedded_fonts:
if not font['chars']:
self.log('The font %s is unused. Removing it.'%font['src'])
remove(font)
continue
try:
raw, old_stats, new_stats = subset(font['item'].data, font['chars'])
except NoGlyphs:
self.log('The font %s has no used glyphs. Removing it.'%font['src'])
remove(font)
continue
except UnsupportedFont as e:
self.log.warn('The font %s is unsupported for subsetting. %s'%(
font['src'], e))
sz = len(font['item'].data)
totals[0] += sz
totals[1] += sz
else:
font['item'].data = raw
nlen = sum(new_stats.itervalues())
olen = sum(old_stats.itervalues())
self.log('Decreased the font %s to %.1f%% of its original size'%
(font['src'], nlen/olen *100))
totals[0] += nlen
totals[1] += olen
font['item'].unload_data_from_memory()
if totals[0]:
self.log('Reduced total font size to %.1f%% of original'%
(totals[0]/totals[1] * 100))
def get_font_properties(self, rule, default=None):
'''
Given a CSS rule, extract normalized font properties from
it. Note that shorthand font property should already have been expanded
by the CSS flattening code.
'''
props = {}
s = rule.style
for q in ('font-family', 'src', 'font-weight', 'font-stretch',
'font-style'):
g = 'uri' if q == 'src' else 'value'
try:
val = s.getProperty(q).propertyValue[0]
val = getattr(val, g)
if q == 'font-family':
val = [x.value for x in s.getProperty(q).propertyValue]
if val and val[0] == 'inherit':
val = None
except (IndexError, KeyError, AttributeError, TypeError, ValueError):
val = None if q in {'src', 'font-family'} else default
if q in {'font-weight', 'font-stretch', 'font-style'}:
val = val.lower() if val else val
if val == 'inherit':
val = default
if q == 'font-weight':
val = {'normal':'400', 'bold':'700'}.get(val, val)
if val not in {'100', '200', '300', '400', '500', '600', '700',
'800', '900', 'bolder', 'lighter'}:
val = default
if val == 'normal': val = '400'
elif q == 'font-style':
if val not in {'normal', 'italic', 'oblique'}:
val = default
elif q == 'font-stretch':
if val not in { 'normal', 'ultra-condensed', 'extra-condensed',
'condensed', 'semi-condensed', 'semi-expanded',
'expanded', 'extra-expanded', 'ultra-expanded'}:
val = default
props[q] = val
return props
def find_embedded_fonts(self):
'''
Find all @font-face rules and extract the relevant info from them.
'''
self.embedded_fonts = []
for item in self.oeb.manifest:
if not hasattr(item.data, 'cssRules'): continue
for i, rule in enumerate(item.data.cssRules):
if rule.type != rule.FONT_FACE_RULE:
continue
props = self.get_font_properties(rule, default='normal')
if not props['font-family'] or not props['src']:
continue
path = item.abshref(props['src'])
ff = self.oeb.manifest.hrefs.get(urlnormalize(path), None)
if not ff:
continue
props['item'] = ff
if props['font-weight'] in {'bolder', 'lighter'}:
props['font-weight'] = '400'
props['weight'] = int(props['font-weight'])
props['chars'] = set()
props['rule'] = rule
self.embedded_fonts.append(props)
def find_style_rules(self):
'''
Extract all font related style information from all stylesheets into a
dict mapping classes to font properties specified by that class. All
the heavy lifting has already been done by the CSS flattening code.
'''
rules = defaultdict(dict)
for item in self.oeb.manifest:
if not hasattr(item.data, 'cssRules'): continue
for i, rule in enumerate(item.data.cssRules):
if rule.type != rule.STYLE_RULE:
continue
props = {k:v for k,v in
self.get_font_properties(rule).iteritems() if v}
if not props:
continue
for sel in rule.selectorList:
sel = sel.selectorText
if sel and sel.startswith('.'):
# We dont care about pseudo-selectors as the worst that
# can happen is some extra characters will remain in
# the font
sel = sel.partition(':')[0]
rules[sel[1:]].update(props)
self.style_rules = dict(rules)
def find_font_usage(self):
for item in self.oeb.manifest:
if not hasattr(item.data, 'xpath'): continue
for body in item.data.xpath('//*[local-name()="body"]'):
base = {'font-family':['serif'], 'font-weight': '400',
'font-style':'normal', 'font-stretch':'normal'}
self.find_usage_in(body, base)
def elem_style(self, cls, inherited_style):
'''
Find the effective style for the given element.
'''
classes = cls.split()
style = inherited_style.copy()
for cls in classes:
style.update(self.style_rules.get(cls, {}))
wt = style.get('font-weight', None)
pwt = inherited_style.get('font-weight', '400')
if wt == 'bolder':
style['font-weight'] = {
'100':'400',
'200':'400',
'300':'400',
'400':'700',
'500':'700',
}.get(pwt, '900')
elif wt == 'lighter':
style['font-weight'] = {
'600':'400', '700':'400',
'800':'700', '900':'700'}.get(pwt, '100')
return style
def used_font(self, style):
'''
Given a style find the embedded font that matches it. Returns None if
no match is found ( can happen if not family matches).
'''
ff = style.get('font-family', [])
lnames = {x.lower() for x in ff}
matching_set = []
# Filter on font-family
for ef in self.embedded_fonts:
flnames = {x.lower() for x in ef.get('font-family', [])}
if not lnames.intersection(flnames):
continue
matching_set.append(ef)
if not matching_set:
return None
# Filter on font-stretch
widths = {x:i for i, x in enumerate(( 'ultra-condensed',
'extra-condensed', 'condensed', 'semi-condensed', 'normal',
'semi-expanded', 'expanded', 'extra-expanded', 'ultra-expanded'
))}
width = widths[style.get('font-stretch', 'normal')]
for f in matching_set:
f['width'] = widths[style.get('font-stretch', 'normal')]
min_dist = min(abs(width-f['width']) for f in matching_set)
nearest = [f for f in matching_set if abs(width-f['width']) ==
min_dist]
if width <= 4:
lmatches = [f for f in nearest if f['width'] <= width]
else:
lmatches = [f for f in nearest if f['width'] >= width]
matching_set = (lmatches or nearest)
# Filter on font-style
fs = style.get('font-style', 'normal')
order = {
'oblique':['oblique', 'italic', 'normal'],
'normal':['normal', 'oblique', 'italic']
}.get(fs, ['italic', 'oblique', 'normal'])
for q in order:
matches = [f for f in matching_set if f.get('font-style', 'normal')
== q]
if matches:
matching_set = matches
break
# Filter on font weight
fw = int(style.get('font-weight', '400'))
if fw == 400:
q = [400, 500, 300, 200, 100, 600, 700, 800, 900]
elif fw == 500:
q = [500, 400, 300, 200, 100, 600, 700, 800, 900]
elif fw < 400:
q = [fw] + list(xrange(fw-100, -100, -100)) + list(xrange(fw+100,
100, 1000))
else:
q = [fw] + list(xrange(fw+100, 100, 1000)) + list(xrange(fw-100,
-100, -100))
for wt in q:
matches = [f for f in matching_set if f['weight'] == wt]
if matches:
return matches[0]
def find_chars(self, elem):
ans = set()
if elem.text:
ans |= set(elem.text)
for child in elem:
if child.tail:
ans |= set(child.tail)
return ans
def find_usage_in(self, elem, inherited_style):
style = self.elem_style(elem.get('class', ''), inherited_style)
for child in elem:
self.find_usage_in(child, style)
font = self.used_font(style)
if font:
chars = self.find_chars(elem)
if chars:
font['chars'] |= chars

View File

@ -1,18 +1,19 @@
__license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
""" The GUI """
import os, sys, Queue, threading
import os, sys, Queue, threading, glob
from threading import RLock
from urllib import unquote
from PyQt4.Qt import (QVariant, QFileInfo, QObject, SIGNAL, QBuffer, Qt,
QByteArray, QTranslator, QCoreApplication, QThread,
QEvent, QTimer, pyqtSignal, QDateTime, QDesktopServices,
QFileDialog, QFileIconProvider, QSettings, QColor,
QIcon, QApplication, QDialog, QUrl, QFont, QPalette)
QIcon, QApplication, QDialog, QUrl, QFont, QPalette,
QFontDatabase)
ORG_NAME = 'KovidsBrain'
APP_UID = 'libprs500'
from calibre import prints, load_builtin_fonts
from calibre import prints
from calibre.constants import (islinux, iswindows, isbsd, isfrozen, isosx,
plugins, config_dir, filesystem_encoding, DEBUG)
from calibre.utils.config import Config, ConfigProxy, dynamic, JSONConfig
@ -779,7 +780,6 @@ class Application(QApplication):
qt_app = self
self._file_open_paths = []
self._file_open_lock = RLock()
load_builtin_fonts()
self.setup_styles(force_calibre_style)
if DEBUG:
@ -792,6 +792,29 @@ class Application(QApplication):
self.redirect_notify = True
return ret
def load_builtin_fonts(self, scan_for_fonts=False):
global _rating_font
if scan_for_fonts:
from calibre.utils.fonts.scanner import font_scanner
# Start scanning the users computer for fonts
font_scanner
# Load the builtin fonts and any fonts added to calibre by the user to
# Qt
for ff in glob.glob(P('fonts/liberation/*.?tf')) + \
[P('fonts/calibreSymbols.otf')] + \
glob.glob(os.path.join(config_dir, 'fonts', '*.?tf')):
if ff.rpartition('.')[-1].lower() in {'ttf', 'otf'}:
with open(ff, 'rb') as s:
# Windows requires font files to be executable for them to be
# loaded successfully, so we use the in memory loader
fid = QFontDatabase.addApplicationFontFromData(s.read())
if fid > -1:
fam = QFontDatabase.applicationFontFamilies(fid)
fam = set(map(unicode, fam))
if u'calibre Symbols' in fam:
_rating_font = u'calibre Symbols'
def load_calibre_style(self):
# On OS X QtCurve resets the palette, so we preserve it explicitly
orig_pal = QPalette(self.palette())
@ -964,22 +987,9 @@ def is_gui_thread():
global gui_thread
return gui_thread is QThread.currentThread()
_rating_font = None
_rating_font = 'Arial Unicode MS' if iswindows else 'sans-serif'
def rating_font():
global _rating_font
if _rating_font is None:
from PyQt4.Qt import QFontDatabase
_rating_font = 'Arial Unicode MS' if iswindows else 'sans-serif'
fontid = QFontDatabase.addApplicationFont(
#P('fonts/liberation/LiberationSerif-Regular.ttf')
P('fonts/calibreSymbols.otf')
)
if fontid > -1:
try:
_rating_font = unicode(list(
QFontDatabase.applicationFontFamilies(fontid))[0])
except:
pass
return _rating_font
def find_forms(srcdir):

View File

@ -120,17 +120,19 @@ class ShareConnMenu(QMenu): # {{{
for account in keys:
formats, auto, default = opts.accounts[account]
subject = opts.subjects.get(account, '')
alias = opts.aliases.get(account, '')
dest = 'mail:'+account+';'+formats+';'+subject
action1 = DeviceAction(dest, False, False, I('mail.png'),
account)
alias or account)
action2 = DeviceAction(dest, True, False, I('mail.png'),
account + ' ' + _('(delete from library)'))
(alias or account) + ' ' + _('(delete from library)'))
self.email_to_menu.addAction(action1)
self.email_to_and_delete_menu.addAction(action2)
map(self.memory.append, (action1, action2))
if default:
ac = DeviceAction(dest, False, False,
I('mail.png'), _('Email to') + ' ' +account)
I('mail.png'), _('Email to') + ' ' +(alias or
account))
self.addAction(ac)
self.email_actions.append(ac)
ac.a_s.connect(sync_menu.action_triggered)

View File

@ -239,10 +239,11 @@ class PluginWidget(QWidget,Ui_Form):
def initialize(self, name, db):
'''
CheckBoxControls (c_type: check_box):
['generate_titles','generate_series','generate_genres',
'generate_recently_added','generate_descriptions','include_hr']
['cross_reference_authors',
'generate_titles','generate_series','generate_genres',
'generate_recently_added','generate_descriptions',
'include_hr']
ComboBoxControls (c_type: combo_box):
['exclude_source_field','header_note_source_field',
'merge_source_field']

View File

@ -305,7 +305,7 @@ The default pattern \[.+\]|\+ excludes tags of the form [tag], e.g., [Test book]
<string>Other options</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="2" column="1">
<item row="3" column="1">
<layout class="QHBoxLayout" name="merge_with_comments_hl">
<item>
<widget class="QComboBox" name="merge_source_field">
@ -372,7 +372,7 @@ The default pattern \[.+\]|\+ excludes tags of the form [tag], e.g., [Test book]
</item>
</layout>
</item>
<item row="2" column="0">
<item row="3" column="0">
<widget class="QLabel" name="label_9">
<property name="minimumSize">
<size>
@ -397,7 +397,7 @@ The default pattern \[.+\]|\+ excludes tags of the form [tag], e.g., [Test book]
</property>
</widget>
</item>
<item row="0" column="0">
<item row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="minimumSize">
<size>
@ -413,7 +413,7 @@ The default pattern \[.+\]|\+ excludes tags of the form [tag], e.g., [Test book]
</property>
</widget>
</item>
<item row="0" column="1">
<item row="1" column="1">
<layout class="QHBoxLayout" name="replace_cover_hl">
<item>
<widget class="QRadioButton" name="generate_new_cover">
@ -447,7 +447,7 @@ The default pattern \[.+\]|\+ excludes tags of the form [tag], e.g., [Test book]
</item>
</layout>
</item>
<item row="1" column="0">
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>E&amp;xtra Description note:</string>
@ -460,7 +460,7 @@ The default pattern \[.+\]|\+ excludes tags of the form [tag], e.g., [Test book]
</property>
</widget>
</item>
<item row="1" column="1">
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QComboBox" name="header_note_source_field">
@ -561,6 +561,27 @@ The default pattern \[.+\]|\+ excludes tags of the form [tag], e.g., [Test book]
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Author cross-references:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="cross_references_hl">
<item>
<widget class="QCheckBox" name="cross_reference_authors">
<property name="text">
<string>For books with multiple authors, list each author separately</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>

View File

@ -32,7 +32,7 @@ class LookAndFeelWidget(Widget, Ui_Form):
Widget.__init__(self, parent,
['change_justification', 'extra_css', 'base_font_size',
'font_size_mapping', 'line_height', 'minimum_line_height',
'embed_font_family',
'embed_font_family', 'subset_embedded_fonts',
'smarten_punctuation', 'unsmarten_punctuation',
'disable_font_rescaling', 'insert_blank_line',
'remove_paragraph_spacing',

View File

@ -406,7 +406,14 @@
</widget>
</item>
<item row="6" column="1" colspan="2">
<widget class="FontFamilyChooser" name="opt_embed_font_family"/>
<widget class="FontFamilyChooser" name="opt_embed_font_family" native="true"/>
</item>
<item row="6" column="3" colspan="2">
<widget class="QCheckBox" name="opt_subset_embedded_fonts">
<property name="text">
<string>&amp;Subset all embedded fonts</string>
</property>
</widget>
</item>
</layout>
</widget>

View File

@ -29,38 +29,8 @@ class PluginWidget(Widget, Ui_Form):
)
self.db, self.book_id = db, book_id
'''
from calibre.utils.fonts import fontconfig
global font_family_model
if font_family_model is None:
font_family_model = FontFamilyModel()
try:
font_family_model.families = fontconfig.find_font_families(allowed_extensions=['ttf'])
except:
import traceback
font_family_model.families = []
print 'WARNING: Could not load fonts'
traceback.print_exc()
font_family_model.families.sort()
font_family_model.families[:0] = [_('Default')]
self.font_family_model = font_family_model
self.opt_masthead_font.setModel(self.font_family_model)
'''
self.opt_mobi_file_type.addItems(['old', 'both', 'new'])
self.initialize_options(get_option, get_help, db, book_id)
'''
def set_value_handler(self, g, val):
if unicode(g.objectName()) in 'opt_masthead_font':
idx = -1
if val:
idx = g.findText(val, Qt.MatchFixedString)
if idx < 0:
idx = 0
g.setCurrentIndex(idx)
return True
return False
'''

View File

@ -504,7 +504,11 @@ from the value in the box</string>
<item>
<widget class="QCheckBox" name="restore_original">
<property name="toolTip">
<string>When doing a same format to same format conversion, for e.g., EPUB to EPUB, calibre saves the original EPUB as ORIGINAL_EPUB. This option tells calibre to restore the EPUB from ORIGINAL_EPUB. Useful if you did a bulk conversion of a large number of books and something went wrong.</string>
<string>When doing a same format to same format conversion,
for e.g., EPUB to EPUB, calibre saves the original EPUB
as ORIGINAL_EPUB. This option tells calibre to restore
the EPUB from ORIGINAL_EPUB. Useful if you did a bulk
conversion of a large number of books and something went wrong.</string>
</property>
<property name="text">
<string>Restore pre conversion &amp;originals, if available</string>

View File

@ -219,7 +219,13 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
if mi:
self.mi = mi
else:
self.mi = Metadata(None, None)
self.mi = Metadata(_('Title'), [_('Author')])
self.mi.author_sort = _('Author Sort')
self.mi.series = _('Series')
self.mi.series_index = 3
self.mi.rating = 4.0
self.mi.tags = [_('Tag 1'), _('Tag 2')]
self.mi.languages = ['eng']
# Remove help icon on title bar
icon = self.windowIcon()

View File

@ -7,13 +7,16 @@ __license__ = 'GPL v3'
__copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
import os, shutil
from PyQt4.Qt import (QFontInfo, QFontMetrics, Qt, QFont, QFontDatabase, QPen,
QStyledItemDelegate, QSize, QStyle, QStringListModel, pyqtSignal,
QDialog, QVBoxLayout, QApplication, QFontComboBox, QPushButton,
QToolButton, QGridLayout, QListView, QWidget, QDialogButtonBox, QIcon,
QHBoxLayout, QLabel, QModelIndex)
QHBoxLayout, QLabel, QModelIndex, QLineEdit)
from calibre.utils.icu import sort_key
from calibre.constants import config_dir
from calibre.gui2 import choose_files, error_dialog, info_dialog
def writing_system_for_font(font):
has_latin = True
@ -112,8 +115,54 @@ class FontFamilyDelegate(QStyledItemDelegate):
r.setLeft(r.left() + w)
painter.drawText(r, Qt.AlignVCenter|Qt.AlignLeading|Qt.TextSingleLine, sample)
class Typefaces(QWidget):
pass
class Typefaces(QLabel):
def __init__(self, parent=None):
QLabel.__init__(self, parent)
self.setMinimumWidth(400)
self.base_msg = '<h3>'+_('Choose a font family')+'</h3>'
self.setText(self.base_msg)
self.setWordWrap(True)
def show_family(self, family, faces):
if not family:
self.setText(self.base_msg)
return
msg = '''
<h3>%s</h3>
<dl style="font-size: smaller">
{0}
</dl>
'''%(_('Available faces for %s')%family)
entries = []
for font in faces:
sf = (font['wws_subfamily_name'] or font['preferred_subfamily_name']
or font['subfamily_name'])
entries.append('''
<dt><b>{sf}</b></dt>
<dd>font-stretch: <i>{width}</i> font-weight: <i>{weight}</i> font-style:
<i>{style}</i></dd>
'''.format(sf=sf, width=font['font-stretch'],
weight=font['font-weight'], style=font['font-style']))
msg = msg.format('\n\n'.join(entries))
self.setText(msg)
class FontsView(QListView):
changed = pyqtSignal()
def __init__(self, parent):
QListView.__init__(self, parent)
self.setSelectionMode(self.SingleSelection)
self.setAlternatingRowColors(True)
self.d = FontFamilyDelegate(self)
self.setItemDelegate(self.d)
def currentChanged(self, current, previous):
self.changed.emit()
QListView.currentChanged(self, current, previous)
class FontFamilyDialog(QDialog):
@ -121,28 +170,15 @@ class FontFamilyDialog(QDialog):
QDialog.__init__(self, parent)
self.setWindowTitle(_('Choose font family'))
self.setWindowIcon(QIcon(I('font.png')))
from calibre.utils.fonts import fontconfig
try:
self.families = fontconfig.find_font_families()
except:
self.families = []
print ('WARNING: Could not load fonts')
import traceback
traceback.print_exc()
# Restrict to Qt families as we need the font to be available in
# QFontDatabase
qt_families = set([unicode(x) for x in QFontDatabase().families()])
self.families = list(qt_families.intersection(set(self.families)))
self.families.sort(key=sort_key)
self.families.insert(0, _('None'))
from calibre.utils.fonts.scanner import font_scanner
self.font_scanner = font_scanner
self.m = QStringListModel(self)
self.build_font_list()
self.l = l = QGridLayout()
self.setLayout(l)
self.view = QListView(self)
self.m = QStringListModel(self.families)
self.view = FontsView(self)
self.view.setModel(self.m)
self.d = FontFamilyDelegate(self)
self.view.setItemDelegate(self.d)
self.view.setCurrentIndex(self.m.index(0))
if current_family:
for i, val in enumerate(self.families):
@ -150,22 +186,114 @@ class FontFamilyDialog(QDialog):
self.view.setCurrentIndex(self.m.index(i))
break
self.view.doubleClicked.connect(self.accept, type=Qt.QueuedConnection)
self.view.setSelectionMode(self.view.SingleSelection)
self.view.setAlternatingRowColors(True)
self.view.changed.connect(self.current_changed,
type=Qt.QueuedConnection)
self.faces = Typefaces(self)
self.bb = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Cancel)
self.bb.accepted.connect(self.accept)
self.bb.rejected.connect(self.reject)
self.add_fonts_button = afb = self.bb.addButton(_('Add &fonts'),
self.bb.ActionRole)
afb.setIcon(QIcon(I('plus.png')))
afb.clicked.connect(self.add_fonts)
self.ml = QLabel(_('Choose a font family from the list below:'))
self.search = QLineEdit(self)
self.search.setPlaceholderText(_('Search'))
self.search.returnPressed.connect(self.find)
self.nb = QToolButton(self)
self.nb.setIcon(QIcon(I('arrow-down.png')))
self.nb.setToolTip(_('Find Next'))
self.pb = QToolButton(self)
self.pb.setIcon(QIcon(I('arrow-up.png')))
self.pb.setToolTip(_('Find Previous'))
self.nb.clicked.connect(self.find_next)
self.pb.clicked.connect(self.find_previous)
self.faces = Typefaces(self)
l.addWidget(self.ml, 0, 0, 1, 4)
l.addWidget(self.search, 1, 0, 1, 1)
l.addWidget(self.nb, 1, 1, 1, 1)
l.addWidget(self.pb, 1, 2, 1, 1)
l.addWidget(self.view, 2, 0, 1, 3)
l.addWidget(self.faces, 1, 3, 2, 1)
l.addWidget(self.bb, 3, 0, 1, 4)
l.setAlignment(self.faces, Qt.AlignTop)
l.addWidget(self.ml, 0, 0, 1, 2)
l.addWidget(self.view, 1, 0, 1, 1)
l.addWidget(self.faces, 1, 1, 1, 1)
l.addWidget(self.bb, 2, 0, 1, 2)
self.resize(800, 600)
self.resize(600, 500)
def set_current(self, i):
self.view.setCurrentIndex(self.m.index(i))
def keyPressEvent(self, e):
if e.key() == Qt.Key_Return:
return
return QDialog.keyPressEvent(self, e)
def find(self, backwards=False):
i = self.view.currentIndex().row()
if i < 0: i = 0
q = icu_lower(unicode(self.search.text())).strip()
if not q: return
r = (xrange(i-1, -1, -1) if backwards else xrange(i+1,
len(self.families)))
for j in r:
f = self.families[j]
if q in icu_lower(f):
self.set_current(j)
return
def find_next(self):
self.find()
def find_previous(self):
self.find(backwards=True)
def build_font_list(self):
try:
self.families = list(self.font_scanner.find_font_families())
except:
self.families = []
print ('WARNING: Could not load fonts')
import traceback
traceback.print_exc()
self.families.insert(0, _('None'))
self.m.setStringList(self.families)
def add_fonts(self):
from calibre.utils.fonts.metadata import FontMetadata
files = choose_files(self, 'add fonts to calibre',
_('Select font files'), filters=[(_('TrueType/OpenType Fonts'),
['ttf', 'otf'])], all_files=False)
if not files: return
families = set()
for f in files:
try:
with open(f, 'rb') as stream:
fm = FontMetadata(stream)
except:
import traceback
error_dialog(self, _('Corrupt font'),
_('Failed to read metadata from the font file: %s')%
f, det_msg=traceback.format_exc(), show=True)
return
families.add(fm.font_family)
families = sorted(families)
dest = os.path.join(config_dir, 'fonts')
for f in files:
shutil.copyfile(f, os.path.join(dest, os.path.basename(f)))
self.font_scanner.do_scan()
self.build_font_list()
self.m.reset()
self.view.setCurrentIndex(self.m.index(0))
if families:
for i, val in enumerate(self.families):
if icu_lower(val) == icu_lower(families[0]):
self.view.setCurrentIndex(self.m.index(i))
break
info_dialog(self, _('Added fonts'),
_('Added font families: %s')%(
', '.join(families)), show=True)
@property
def font_family(self):
@ -173,6 +301,11 @@ class FontFamilyDialog(QDialog):
if idx == 0: return None
return self.families[idx]
def current_changed(self):
fam = self.font_family
self.faces.show_family(fam, self.font_scanner.fonts_for_family(fam)
if fam else None)
class FontFamilyChooser(QWidget):
family_changed = pyqtSignal(object)

View File

@ -871,11 +871,17 @@ class BooksModel(QAbstractTableModel): # {{{
try:
return self._set_data(index, value)
except (IOError, OSError) as err:
if getattr(err, 'errno', None) == errno.EACCES: # Permission denied
import traceback
if getattr(err, 'errno', None) == errno.EACCES: # Permission denied
fname = getattr(err, 'filename', None)
p = 'Locked file: %s\n\n'%fname if fname else ''
error_dialog(get_gui(), _('Permission denied'),
_('Could not change the on disk location of this'
' book. Is it open in another program?'),
det_msg=p+traceback.format_exc(), show=True)
return False
error_dialog(get_gui(), _('Failed to set data'),
_('Could not set data, click Show Details to see why.'),
det_msg=traceback.format_exc(), show=True)
except:
import traceback

View File

@ -291,6 +291,7 @@ def run_in_debug_mode(logpath=None):
def run_gui(opts, args, actions, listener, app, gui_debug=None):
initialize_file_icon_provider()
app.load_builtin_fonts(scan_for_fonts=True)
if not dynamic.get('welcome_wizard_was_run', False):
from calibre.gui2.wizard import wizard
wizard().exec_()

View File

@ -91,6 +91,9 @@ class TitleEdit(EnLineEdit):
def commit(self, db, id_):
title = self.current_val
if title != self.original_val:
# Only try to commit if changed. This allow setting of other fields
# to work even if some of the book files are opened in windows.
try:
if self.COMMIT:
getattr(db, 'set_'+ self.TITLE_ATTR)(id_, title, notify=False)
@ -98,13 +101,14 @@ class TitleEdit(EnLineEdit):
getattr(db, 'set_'+ self.TITLE_ATTR)(id_, title, notify=False,
commit=False)
except (IOError, OSError) as err:
if getattr(err, 'errno', -1) == errno.EACCES: # Permission denied
if getattr(err, 'errno', None) == errno.EACCES: # Permission denied
import traceback
fname = err.filename if err.filename else 'file'
fname = getattr(err, 'filename', None)
p = 'Locked file: %s\n\n'%fname if fname else ''
error_dialog(self, _('Permission denied'),
_('Could not open %s. Is it being used by another'
' program?')%fname, det_msg=traceback.format_exc(),
show=True)
_('Could not change the on disk location of this'
' book. Is it open in another program?'),
det_msg=p+traceback.format_exc(), show=True)
return False
raise
return True
@ -262,17 +266,21 @@ class AuthorsEdit(EditWithComplete):
def commit(self, db, id_):
authors = self.current_val
if authors != self.original_val:
# Only try to commit if changed. This allow setting of other fields
# to work even if some of the book files are opened in windows.
try:
self.books_to_refresh |= db.set_authors(id_, authors, notify=False,
allow_case_change=True)
except (IOError, OSError) as err:
if getattr(err, 'errno', -1) == errno.EACCES: # Permission denied
if getattr(err, 'errno', None) == errno.EACCES: # Permission denied
import traceback
fname = err.filename if err.filename else 'file'
fname = getattr(err, 'filename', None)
p = 'Locked file: %s\n\n'%fname if fname else ''
error_dialog(self, _('Permission denied'),
_('Could not open "%s". Is it being used by another'
' program?')%fname, det_msg=traceback.format_exc(),
show=True)
_('Could not change the on disk location of this'
' book. Is it open in another program?'),
det_msg=p+traceback.format_exc(), show=True)
return False
raise
return True

View File

@ -188,6 +188,10 @@ class MetadataSingleDialogBase(ResizableDialog):
self.tags_editor_button.setToolTip(_('Open Tag Editor'))
self.tags_editor_button.setIcon(QIcon(I('chapters.png')))
self.tags_editor_button.clicked.connect(self.tags_editor)
self.clear_tags_button = QToolButton(self)
self.clear_tags_button.setToolTip(_('Clear all tags'))
self.clear_tags_button.setIcon(QIcon(I('trash.png')))
self.clear_tags_button.clicked.connect(self.tags.clear)
self.basic_metadata_widgets.append(self.tags)
self.identifiers = IdentifiersEdit(self)
@ -322,6 +326,7 @@ class MetadataSingleDialogBase(ResizableDialog):
' program?')%fname, det_msg=traceback.format_exc(),
show=True)
return
raise
if mi is None:
return
cdata = None
@ -444,11 +449,12 @@ class MetadataSingleDialogBase(ResizableDialog):
except (IOError, OSError) as err:
if getattr(err, 'errno', None) == errno.EACCES: # Permission denied
import traceback
fname = err.filename if err.filename else 'file'
fname = getattr(err, 'filename', None)
p = 'Locked file: %s\n\n'%fname if fname else ''
error_dialog(self, _('Permission denied'),
_('Could not open %s. Is it being used by another'
' program?')%fname, det_msg=traceback.format_exc(),
show=True)
_('Could not change the on disk location of this'
' book. Is it open in another program?'),
det_msg=p+traceback.format_exc(), show=True)
return False
raise
for widget in getattr(self, 'custom_metadata_widgets', []):
@ -654,9 +660,10 @@ class MetadataSingleDialog(MetadataSingleDialogBase): # {{{
l.addItem(self.tabs[0].spc_one, 1, 0, 1, 3)
sto(self.cover.buttons[-1], self.rating)
create_row2(1, self.rating)
sto(self.rating, self.tags)
create_row2(2, self.tags, self.tags_editor_button)
sto(self.tags_editor_button, self.paste_isbn_button)
sto(self.rating, self.tags_editor_button)
sto(self.tags_editor_button, self.tags)
create_row2(2, self.tags, self.clear_tags_button, front_button=self.tags_editor_button)
sto(self.clear_tags_button, self.paste_isbn_button)
sto(self.paste_isbn_button, self.identifiers)
create_row2(3, self.identifiers, self.clear_identifiers_button,
front_button=self.paste_isbn_button)
@ -759,6 +766,7 @@ class MetadataSingleDialogAlt1(MetadataSingleDialogBase): # {{{
tl.addWidget(self.swap_title_author_button, 0, 0, 2, 1)
tl.addWidget(self.manage_authors_button, 2, 0, 1, 1)
tl.addWidget(self.paste_isbn_button, 12, 0, 1, 1)
tl.addWidget(self.tags_editor_button, 6, 0, 1, 1)
create_row(0, self.title, self.title_sort,
button=self.deduce_title_sort_button, span=2,
@ -771,7 +779,7 @@ class MetadataSingleDialogAlt1(MetadataSingleDialogBase): # {{{
create_row(4, self.series, self.series_index,
button=self.clear_series_button, icon='trash.png')
create_row(5, self.series_index, self.tags)
create_row(6, self.tags, self.rating, button=self.tags_editor_button)
create_row(6, self.tags, self.rating, button=self.clear_tags_button)
create_row(7, self.rating, self.pubdate)
create_row(8, self.pubdate, self.publisher,
button=self.pubdate.clear_button, icon='trash.png')
@ -783,7 +791,8 @@ class MetadataSingleDialogAlt1(MetadataSingleDialogBase): # {{{
button=self.clear_identifiers_button, icon='trash.png')
sto(self.clear_identifiers_button, self.swap_title_author_button)
sto(self.swap_title_author_button, self.manage_authors_button)
sto(self.manage_authors_button, self.paste_isbn_button)
sto(self.manage_authors_button, self.tags_editor_button)
sto(self.tags_editor_button, self.paste_isbn_button)
tl.addItem(QSpacerItem(1, 1, QSizePolicy.Fixed, QSizePolicy.Expanding),
13, 1, 1 ,1)
@ -894,6 +903,7 @@ class MetadataSingleDialogAlt2(MetadataSingleDialogBase): # {{{
tl.addWidget(self.swap_title_author_button, 0, 0, 2, 1)
tl.addWidget(self.manage_authors_button, 2, 0, 2, 1)
tl.addWidget(self.paste_isbn_button, 12, 0, 1, 1)
tl.addWidget(self.tags_editor_button, 6, 0, 1, 1)
create_row(0, self.title, self.title_sort,
button=self.deduce_title_sort_button, span=2,
@ -906,7 +916,7 @@ class MetadataSingleDialogAlt2(MetadataSingleDialogBase): # {{{
create_row(4, self.series, self.series_index,
button=self.clear_series_button, icon='trash.png')
create_row(5, self.series_index, self.tags)
create_row(6, self.tags, self.rating, button=self.tags_editor_button)
create_row(6, self.tags, self.rating, button=self.clear_tags_button)
create_row(7, self.rating, self.pubdate)
create_row(8, self.pubdate, self.publisher,
button=self.pubdate.clear_button, icon='trash.png')
@ -918,7 +928,8 @@ class MetadataSingleDialogAlt2(MetadataSingleDialogBase): # {{{
button=self.clear_identifiers_button, icon='trash.png')
sto(self.clear_identifiers_button, self.swap_title_author_button)
sto(self.swap_title_author_button, self.manage_authors_button)
sto(self.manage_authors_button, self.paste_isbn_button)
sto(self.manage_authors_button, self.tags_editor_button)
sto(self.tags_editor_button, self.paste_isbn_button)
tl.addItem(QSpacerItem(1, 1, QSizePolicy.Fixed, QSizePolicy.Expanding),
13, 1, 1 ,1)

View File

@ -19,12 +19,14 @@ from calibre.utils.smtp import config as smtp_prefs
class EmailAccounts(QAbstractTableModel): # {{{
def __init__(self, accounts, subjects):
def __init__(self, accounts, subjects, aliases={}):
QAbstractTableModel.__init__(self)
self.accounts = accounts
self.subjects = subjects
self.aliases = aliases
self.account_order = sorted(self.accounts.keys())
self.headers = map(QVariant, [_('Email'), _('Formats'), _('Subject'), _('Auto send')])
self.headers = map(QVariant, [_('Email'), _('Formats'), _('Subject'),
_('Auto send'), _('Alias')])
self.default_font = QFont()
self.default_font.setBold(True)
self.default_font = QVariant(self.default_font)
@ -36,7 +38,9 @@ class EmailAccounts(QAbstractTableModel): # {{{
'{author_sort} can be used here.'),
'<p>'+_('If checked, downloaded news will be automatically '
'mailed <br>to this email address '
'(provided it is in one of the listed formats).')])))
'(provided it is in one of the listed formats).'),
_('Friendly name to use for this email address')
])))
def rowCount(self, *args):
return len(self.account_order)
@ -67,6 +71,8 @@ class EmailAccounts(QAbstractTableModel): # {{{
return QVariant(self.accounts[account][0])
if col == 2:
return QVariant(self.subjects.get(account, ''))
if col == 4:
return QVariant(self.aliases.get(account, ''))
if role == Qt.FontRole and self.accounts[account][2]:
return self.default_font
if role == Qt.CheckStateRole and col == 3:
@ -88,6 +94,11 @@ class EmailAccounts(QAbstractTableModel): # {{{
self.accounts[account][1] ^= True
elif col == 2:
self.subjects[account] = unicode(value.toString())
elif col == 4:
self.aliases.pop(account, None)
aval = unicode(value.toString()).strip()
if aval:
self.aliases[account] = aval
elif col == 1:
self.accounts[account][0] = unicode(value.toString()).upper()
elif col == 0:
@ -156,7 +167,8 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
self.send_email_widget.initialize(self.preferred_to_address)
self.send_email_widget.changed_signal.connect(self.changed_signal.emit)
opts = self.send_email_widget.smtp_opts
self._email_accounts = EmailAccounts(opts.accounts, opts.subjects)
self._email_accounts = EmailAccounts(opts.accounts, opts.subjects,
opts.aliases)
self._email_accounts.dataChanged.connect(lambda x,y:
self.changed_signal.emit())
self.email_view.setModel(self._email_accounts)
@ -184,6 +196,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
raise AbortCommit('abort')
self.proxy['accounts'] = self._email_accounts.accounts
self.proxy['subjects'] = self._email_accounts.subjects
self.proxy['aliases'] = self._email_accounts.aliases
return ConfigWidgetBase.commit(self)

View File

@ -403,7 +403,12 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
return
all_locations = OrderedDict(ConfigWidget.LOCATIONS)
try:
plugin_action = plugin.load_actual_plugin(self.gui)
except:
# Broken plugin, fails to initialize. Given that, it's probably
# already configured, so we can just quit.
return
installed_actions = OrderedDict([
(key, list(gprefs.get('action-layout-'+key, [])))
for key in all_locations])

View File

@ -6,102 +6,19 @@ __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>'
__docformat__ = 'restructuredtext en'
from contextlib import closing
from calibre.gui2.store.stores.amazon_uk_plugin import AmazonUKKindleStore
from lxml import html
from PyQt4.Qt import QUrl
from calibre import browser
from calibre.gui2 import open_url
from calibre.gui2.store import StorePlugin
from calibre.gui2.store.search_result import SearchResult
class AmazonDEKindleStore(StorePlugin):
class AmazonDEKindleStore(AmazonUKKindleStore):
'''
For comments on the implementation, please see amazon_plugin.py
'''
def open(self, parent=None, detail_item=None, external=False):
aff_id = {'tag': 'charhale0a-21'}
store_link = ('http://www.amazon.de/gp/redirect.html?ie=UTF8&site-redirect=de'
'&tag=%(tag)s&linkCode=ur2&camp=1638&creative=19454'
'&location=http://www.amazon.de/ebooks-kindle/b?node=530886031') % aff_id
if detail_item:
aff_id['asin'] = detail_item
store_link = ('http://www.amazon.de/gp/redirect.html?ie=UTF8'
'&location=http://www.amazon.de/ebooks-kindle/b?node=530886031')
store_link_details = ('http://www.amazon.de/gp/redirect.html?ie=UTF8'
'&location=http://www.amazon.de/dp/%(asin)s&site-redirect=de'
'&tag=%(tag)s&linkCode=ur2&camp=1638&creative=6742') % aff_id
open_url(QUrl(store_link))
def search(self, query, max_results=10, timeout=60):
'&tag=%(tag)s&linkCode=ur2&camp=1638&creative=6742')
search_url = 'http://www.amazon.de/s/?url=search-alias%3Ddigital-text&field-keywords='
url = search_url + query.encode('ascii', 'backslashreplace').replace('%', '%25').replace('\\x', '%').replace(' ', '+')
br = browser()
counter = max_results
with closing(br.open(url, timeout=timeout)) as f:
# doc = html.fromstring(f.read().decode('latin-1', 'replace'))
# Apparently amazon Europe is responding in UTF-8 now
doc = html.fromstring(f.read())
data_xpath = '//div[contains(@class, "result") and contains(@class, "product")]'
format_xpath = './/span[@class="format"]/text()'
cover_xpath = './/img[@class="productImage"]/@src'
for data in doc.xpath(data_xpath):
if counter <= 0:
break
# Even though we are searching digital-text only Amazon will still
# put in results for non Kindle books (author pages). So we need
# to explicitly check if the item is a Kindle book and ignore it
# if it isn't.
format = ''.join(data.xpath(format_xpath))
if 'kindle' not in format.lower():
continue
# We must have an asin otherwise we can't easily reference the
# book later.
asin = ''.join(data.xpath("@name"))
cover_url = ''.join(data.xpath(cover_xpath))
title = ''.join(data.xpath('.//a[@class="title"]/text()'))
price = ''.join(data.xpath('.//div[@class="newPrice"]/span[contains(@class, "price")]/text()'))
author = ''.join(data.xpath('.//h3[@class="title"]/span[@class="ptBrand"]/text()'))
if author.startswith('von '):
author = author[4:]
counter -= 1
s = SearchResult()
s.cover_url = cover_url.strip()
s.title = title.strip()
s.author = author.strip()
s.price = price.strip()
s.detail_item = asin.strip()
s.formats = 'Kindle'
yield s
def get_details(self, search_result, timeout):
drm_search_text = u'Gleichzeitige Verwendung von Geräten'
drm_free_text = u'Keine Einschränkung'
url = 'http://amazon.de/dp/'
br = browser()
with closing(br.open(url + search_result.detail_item, timeout=timeout)) as nf:
idata = html.fromstring(nf.read())
if idata.xpath('boolean(//div[@class="content"]//li/b[contains(text(), "' +
drm_search_text + '")])'):
if idata.xpath('boolean(//div[@class="content"]//li[contains(., "' +
drm_free_text + '") and contains(b, "' +
drm_search_text + '")])'):
search_result.drm = SearchResult.DRM_UNLOCKED
else:
search_result.drm = SearchResult.DRM_UNKNOWN
else:
search_result.drm = SearchResult.DRM_LOCKED
return True

View File

@ -6,78 +6,17 @@ __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>'
__docformat__ = 'restructuredtext en'
from contextlib import closing
from calibre.gui2.store.stores.amazon_uk_plugin import AmazonUKKindleStore
from lxml import html
from PyQt4.Qt import QUrl
from calibre import browser
from calibre.gui2 import open_url
from calibre.gui2.store import StorePlugin
from calibre.gui2.store.search_result import SearchResult
class AmazonESKindleStore(StorePlugin):
class AmazonESKindleStore(AmazonUKKindleStore):
'''
For comments on the implementation, please see amazon_plugin.py
'''
def open(self, parent=None, detail_item=None, external=False):
aff_id = {'tag': 'charhale09-21'}
store_link = 'http://www.amazon.es/ebooks-kindle/b?_encoding=UTF8&node=827231031&tag=%(tag)s&ie=UTF8&linkCode=ur2&camp=3626&creative=24790' % aff_id
if detail_item:
aff_id['asin'] = detail_item
store_link = 'http://www.amazon.es/gp/redirect.html?ie=UTF8&location=http://www.amazon.es/dp/%(asin)s&tag=%(tag)s&linkCode=ur2&camp=3626&creative=24790' % aff_id
open_url(QUrl(store_link))
def search(self, query, max_results=10, timeout=60):
store_link = ('http://www.amazon.es/ebooks-kindle/b?_encoding=UTF8&'
'node=827231031&tag=%(tag)s&ie=UTF8&linkCode=ur2&camp=3626&creative=24790')
store_link_details = ('http://www.amazon.es/gp/redirect.html?ie=UTF8&'
'location=http://www.amazon.es/dp/%(asin)s&tag=%(tag)s'
'&linkCode=ur2&camp=3626&creative=24790')
search_url = 'http://www.amazon.es/s/?url=search-alias%3Ddigital-text&field-keywords='
url = search_url + query.encode('ascii', 'backslashreplace').replace('%', '%25').replace('\\x', '%').replace(' ', '+')
br = browser()
counter = max_results
with closing(br.open(url, timeout=timeout)) as f:
# doc = html.fromstring(f.read().decode('latin-1', 'replace'))
# Apparently amazon Europe is responding in UTF-8 now
doc = html.fromstring(f.read())
data_xpath = '//div[contains(@class, "result") and contains(@class, "product")]'
format_xpath = './/span[@class="format"]/text()'
cover_xpath = './/img[@class="productImage"]/@src'
for data in doc.xpath(data_xpath):
if counter <= 0:
break
# Even though we are searching digital-text only Amazon will still
# put in results for non Kindle books (author pages). So we need
# to explicitly check if the item is a Kindle book and ignore it
# if it isn't.
format = ''.join(data.xpath(format_xpath))
if 'kindle' not in format.lower():
continue
# We must have an asin otherwise we can't easily reference the
# book later.
asin = ''.join(data.xpath("@name"))
cover_url = ''.join(data.xpath(cover_xpath))
title = ''.join(data.xpath('.//a[@class="title"]/text()'))
price = ''.join(data.xpath('.//div[@class="newPrice"]/span[contains(@class, "price")]/text()'))
author = unicode(''.join(data.xpath('.//h3[@class="title"]/span[@class="ptBrand"]/text()')))
if author.startswith('de '):
author = author[3:]
counter -= 1
s = SearchResult()
s.cover_url = cover_url.strip()
s.title = title.strip()
s.author = author.strip()
s.price = price.strip()
s.detail_item = asin.strip()
s.formats = 'Kindle'
s.drm = SearchResult.DRM_UNKNOWN
yield s

View File

@ -6,79 +6,16 @@ __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>'
__docformat__ = 'restructuredtext en'
from contextlib import closing
from lxml import html
from calibre.gui2.store.stores.amazon_uk_plugin import AmazonUKKindleStore
from PyQt4.Qt import QUrl
from calibre import browser
from calibre.gui2 import open_url
from calibre.gui2.store import StorePlugin
from calibre.gui2.store.search_result import SearchResult
class AmazonFRKindleStore(StorePlugin):
class AmazonFRKindleStore(AmazonUKKindleStore):
'''
For comments on the implementation, please see amazon_plugin.py
'''
def open(self, parent=None, detail_item=None, external=False):
aff_id = {'tag': 'charhale-21'}
store_link = 'http://www.amazon.fr/livres-kindle/b?ie=UTF8&node=695398031&ref_=sa_menu_kbo1&_encoding=UTF8&tag=%(tag)s&linkCode=ur2&camp=1642&creative=19458' % aff_id
if detail_item:
aff_id['asin'] = detail_item
store_link = 'http://www.amazon.fr/gp/redirect.html?ie=UTF8&location=http://www.amazon.fr/dp/%(asin)s&tag=%(tag)s&linkCode=ur2&camp=1634&creative=6738' % aff_id
open_url(QUrl(store_link))
def search(self, query, max_results=10, timeout=60):
store_link_details = 'http://www.amazon.fr/gp/redirect.html?ie=UTF8&location=http://www.amazon.fr/dp/%(asin)s&tag=%(tag)s&linkCode=ur2&camp=1634&creative=6738'
search_url = 'http://www.amazon.fr/s/?url=search-alias%3Ddigital-text&field-keywords='
url = search_url + query.encode('ascii', 'backslashreplace').replace('%', '%25').replace('\\x', '%').replace(' ', '+')
br = browser()
counter = max_results
with closing(br.open(url, timeout=timeout)) as f:
# doc = html.fromstring(f.read().decode('latin-1', 'replace'))
# Apparently amazon Europe is responding in UTF-8 now
doc = html.fromstring(f.read())
data_xpath = '//div[contains(@class, "result") and contains(@class, "product")]'
format_xpath = './/span[@class="format"]/text()'
cover_xpath = './/img[@class="productImage"]/@src'
for data in doc.xpath(data_xpath):
if counter <= 0:
break
# Even though we are searching digital-text only Amazon will still
# put in results for non Kindle books (author pages). So we need
# to explicitly check if the item is a Kindle book and ignore it
# if it isn't.
format = ''.join(data.xpath(format_xpath))
if 'kindle' not in format.lower():
continue
# We must have an asin otherwise we can't easily reference the
# book later.
asin = ''.join(data.xpath("@name"))
cover_url = ''.join(data.xpath(cover_xpath))
title = ''.join(data.xpath('.//a[@class="title"]/text()'))
price = ''.join(data.xpath('.//div[@class="newPrice"]/span[contains(@class, "price")]/text()'))
author = unicode(''.join(data.xpath('.//h3[@class="title"]/span[@class="ptBrand"]/text()')))
if author.startswith('de '):
author = author[3:]
counter -= 1
s = SearchResult()
s.cover_url = cover_url.strip()
s.title = title.strip()
s.author = author.strip()
s.price = price.strip()
s.detail_item = asin.strip()
s.formats = 'Kindle'
s.drm = SearchResult.DRM_UNKNOWN
yield s

View File

@ -6,78 +6,17 @@ __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>'
__docformat__ = 'restructuredtext en'
from contextlib import closing
from calibre.gui2.store.stores.amazon_uk_plugin import AmazonUKKindleStore
from lxml import html
from PyQt4.Qt import QUrl
from calibre import browser
from calibre.gui2 import open_url
from calibre.gui2.store import StorePlugin
from calibre.gui2.store.search_result import SearchResult
class AmazonITKindleStore(StorePlugin):
class AmazonITKindleStore(AmazonUKKindleStore):
'''
For comments on the implementation, please see amazon_plugin.py
'''
def open(self, parent=None, detail_item=None, external=False):
aff_id = {'tag': 'httpcharles07-21'}
store_link = 'http://www.amazon.it/ebooks-kindle/b?_encoding=UTF8&node=827182031&tag=%(tag)s&ie=UTF8&linkCode=ur2&camp=3370&creative=23322' % aff_id
if detail_item:
aff_id['asin'] = detail_item
store_link = 'http://www.amazon.it/gp/redirect.html?ie=UTF8&location=http://www.amazon.it/dp/%(asin)s&tag=%(tag)s&linkCode=ur2&camp=3370&creative=23322' % aff_id
open_url(QUrl(store_link))
def search(self, query, max_results=10, timeout=60):
store_link = ('http://www.amazon.it/ebooks-kindle/b?_encoding=UTF8&'
'node=827182031&tag=%(tag)s&ie=UTF8&linkCode=ur2&camp=3370&creative=23322')
store_link_details = ('http://www.amazon.it/gp/redirect.html?ie=UTF8&'
'location=http://www.amazon.it/dp/%(asin)s&tag=%(tag)s&'
'linkCode=ur2&camp=3370&creative=23322')
search_url = 'http://www.amazon.it/s/?url=search-alias%3Ddigital-text&field-keywords='
url = search_url + query.encode('ascii', 'backslashreplace').replace('%', '%25').replace('\\x', '%').replace(' ', '+')
br = browser()
counter = max_results
with closing(br.open(url, timeout=timeout)) as f:
# doc = html.fromstring(f.read().decode('latin-1', 'replace'))
# Apparently amazon Europe is responding in UTF-8 now
doc = html.fromstring(f.read())
data_xpath = '//div[contains(@class, "result") and contains(@class, "product")]'
format_xpath = './/span[@class="format"]/text()'
cover_xpath = './/img[@class="productImage"]/@src'
for data in doc.xpath(data_xpath):
if counter <= 0:
break
# Even though we are searching digital-text only Amazon will still
# put in results for non Kindle books (author pages). So we need
# to explicitly check if the item is a Kindle book and ignore it
# if it isn't.
format = ''.join(data.xpath(format_xpath))
if 'kindle' not in format.lower():
continue
# We must have an asin otherwise we can't easily reference the
# book later.
asin = ''.join(data.xpath("@name"))
cover_url = ''.join(data.xpath(cover_xpath))
title = ''.join(data.xpath('.//a[@class="title"]/text()'))
price = ''.join(data.xpath('.//div[@class="newPrice"]/span[contains(@class, "price")]/text()'))
author = unicode(''.join(data.xpath('.//h3[@class="title"]/span[@class="ptBrand"]/text()')))
if author.startswith('di '):
author = author[3:]
counter -= 1
s = SearchResult()
s.cover_url = cover_url.strip()
s.title = title.strip()
s.author = author.strip()
s.price = price.strip()
s.detail_item = asin.strip()
s.formats = 'Kindle'
s.drm = SearchResult.DRM_UNKNOWN
yield s

View File

@ -128,34 +128,13 @@ class AmazonKindleStore(StorePlugin):
with closing(br.open(url, timeout=timeout)) as f:
doc = html.fromstring(f.read().decode('latin-1', 'replace'))
# Amazon has two results pages.
is_shot = doc.xpath('boolean(//div[@id="shotgunMainResults"])')
# Horizontal grid of books. Search "Paolo Bacigalupi"
if is_shot:
data_xpath = '//div[contains(@class, "result")]'
format_xpath = './/div[@class="productTitle"]//text()'
asin_xpath = './/div[@class="productTitle"]//a'
cover_xpath = './/div[@class="productTitle"]//img/@src'
title_xpath = './/div[@class="productTitle"]/a//text()'
price_xpath = './/div[@class="newPrice"]/span/text()'
# Vertical list of books.
else:
# New style list. Search "Paolo Bacigalupi"
if doc.xpath('boolean(//div[@class="image"])'):
data_xpath = '//div[contains(@class, "results")]//div[contains(@class, "result")]'
format_xpath = './/span[@class="binding"]//text()'
data_xpath = '//div[contains(@class, "prod")]'
format_xpath = './/ul[contains(@class, "rsltL")]//span[contains(@class, "lrg") and not(contains(@class, "bld"))]/text()'
asin_xpath = './/div[@class="image"]/a[1]'
cover_xpath = './/img[@class="productImage"]/@src'
title_xpath = './/a[@class="title"]/text()'
price_xpath = './/span[contains(@class, "price")]/text()'
# Old style list. Search "martin"
else:
data_xpath = '//div[contains(@class, "result")]'
format_xpath = './/span[@class="format"]//text()'
asin_xpath = './/div[@class="productImage"]/a[1]'
cover_xpath = './/div[@class="productImage"]//img/@src'
title_xpath = './/div[@class="productTitle"]/a/text()'
price_xpath = './/div[@class="newPrice"]//span//text()'
title_xpath = './/h3[@class="newaps"]/a//text()'
author_xpath = './/h3[@class="newaps"]//span[contains(@class, "reg")]/text()'
price_xpath = './/ul[contains(@class, "rsltL")]//span[contains(@class, "lrg") and contains(@class, "bld")]/text()'
for data in doc.xpath(data_xpath):
if counter <= 0:
@ -186,13 +165,13 @@ class AmazonKindleStore(StorePlugin):
cover_url = ''.join(data.xpath(cover_xpath))
title = ''.join(data.xpath(title_xpath))
price = ''.join(data.xpath(price_xpath))
author = ''.join(data.xpath(author_xpath))
try:
author = author.split('by ', 1)[1].split(" (")[0]
except:
pass
if is_shot:
author = format.split(' by ')[-1]
else:
author = ''.join(data.xpath('.//span[@class="ptBrand"]/text()'))
author = author.split('by ')[-1]
price = ''.join(data.xpath(price_xpath))
counter -= 1

View File

@ -6,8 +6,9 @@ __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>'
__docformat__ = 'restructuredtext en'
from contextlib import closing
import re
from contextlib import closing
from lxml import html
from PyQt4.Qt import QUrl
@ -18,57 +19,80 @@ from calibre.gui2.store import StorePlugin
from calibre.gui2.store.search_result import SearchResult
class AmazonUKKindleStore(StorePlugin):
aff_id = {'tag': 'calcharles-21'}
store_link = ('http://www.amazon.co.uk/gp/redirect.html?ie=UTF8&'
'location=http://www.amazon.co.uk/Kindle-eBooks/b?'
'ie=UTF8&node=341689031&ref_=sa_menu_kbo2&tag=%(tag)s&'
'linkCode=ur2&camp=1634&creative=19450')
store_link_details = ('http://www.amazon.co.uk/gp/redirect.html?ie=UTF8&'
'location=http://www.amazon.co.uk/dp/%(asin)s&tag=%(tag)s&'
'linkCode=ur2&camp=1634&creative=6738')
search_url = 'http://www.amazon.co.uk/s/?url=search-alias%3Ddigital-text&field-keywords='
'''
For comments on the implementation, please see amazon_plugin.py
'''
def open(self, parent=None, detail_item=None, external=False):
aff_id = {'tag': 'calcharles-21'}
store_link = 'http://www.amazon.co.uk/gp/redirect.html?ie=UTF8&location=http://www.amazon.co.uk/Kindle-eBooks/b?ie=UTF8&node=341689031&ref_=sa_menu_kbo2&tag=%(tag)s&linkCode=ur2&camp=1634&creative=19450' % aff_id
store_link = self.store_link % self.aff_id
if detail_item:
aff_id['asin'] = detail_item
store_link = 'http://www.amazon.co.uk/gp/redirect.html?ie=UTF8&location=http://www.amazon.co.uk/dp/%(asin)s&tag=%(tag)s&linkCode=ur2&camp=1634&creative=6738' % aff_id
self.aff_id['asin'] = detail_item
store_link = self.store_link_details % self.aff_id
open_url(QUrl(store_link))
def search(self, query, max_results=10, timeout=60):
search_url = 'http://www.amazon.co.uk/s/?url=search-alias%3Ddigital-text&field-keywords='
url = search_url + query.encode('ascii', 'backslashreplace').replace('%', '%25').replace('\\x', '%').replace(' ', '+')
url = self.search_url + query.encode('ascii', 'backslashreplace').replace('%', '%25').replace('\\x', '%').replace(' ', '+')
br = browser()
counter = max_results
with closing(br.open(url, timeout=timeout)) as f:
# Apparently amazon Europe is responding in UTF-8 now
doc = html.fromstring(f.read())
doc = html.fromstring(f.read())#.decode('latin-1', 'replace'))
data_xpath = '//div[contains(@class, "result") and contains(@class, "product")]'
format_xpath = './/span[@class="format"]/text()'
data_xpath = '//div[contains(@class, "prod")]'
format_xpath = './/ul[contains(@class, "rsltL")]//span[contains(@class, "lrg") and not(contains(@class, "bld"))]/text()'
asin_xpath = './/div[@class="image"]/a[1]'
cover_xpath = './/img[@class="productImage"]/@src'
title_xpath = './/h3[@class="newaps"]/a//text()'
author_xpath = './/h3[@class="newaps"]//span[contains(@class, "reg")]/text()'
price_xpath = './/ul[contains(@class, "rsltL")]//span[contains(@class, "lrg") and contains(@class, "bld")]/text()'
for data in doc.xpath(data_xpath):
if counter <= 0:
break
# Even though we are searching digital-text only Amazon will still
# put in results for non Kindle books (author pages). So we need
# put in results for non Kindle books (author pages). Se we need
# to explicitly check if the item is a Kindle book and ignore it
# if it isn't.
format = ''.join(data.xpath(format_xpath))
if 'kindle' not in format.lower():
format_ = ''.join(data.xpath(format_xpath))
if 'kindle' not in format_.lower():
continue
# We must have an asin otherwise we can't easily reference the
# book later.
asin = ''.join(data.xpath("@name"))
asin_href = None
asin_a = data.xpath(asin_xpath)
if asin_a:
asin_href = asin_a[0].get('href', '')
m = re.search(r'/dp/(?P<asin>.+?)(/|$)', asin_href)
if m:
asin = m.group('asin')
else:
continue
else:
continue
cover_url = ''.join(data.xpath(cover_xpath))
title = ''.join(data.xpath('.//a[@class="title"]/text()'))
price = ''.join(data.xpath('.//div[@class="newPrice"]/span[contains(@class, "price")]/text()'))
title = ''.join(data.xpath(title_xpath))
author = ''.join(data.xpath(author_xpath))
try:
author = author.split('by ', 1)[1].split(" (")[0]
except:
pass
author = ''.join(data.xpath('.//h3[@class="title"]/span[@class="ptBrand"]/text()'))
if author.startswith('by '):
author = author[3:]
price = ''.join(data.xpath(price_xpath))
counter -= 1
@ -78,37 +102,10 @@ class AmazonUKKindleStore(StorePlugin):
s.author = author.strip()
s.price = price.strip()
s.detail_item = asin.strip()
s.drm = SearchResult.DRM_UNKNOWN
s.formats = 'Kindle'
yield s
def get_details(self, search_result, timeout):
# We might already have been called.
if search_result.drm:
return
url = 'http://amazon.co.uk/dp/'
drm_search_text = u'Simultaneous Device Usage'
drm_free_text = u'Unlimited'
br = browser()
with closing(br.open(url + search_result.detail_item, timeout=timeout)) as nf:
idata = html.fromstring(nf.read())
if not search_result.author:
search_result.author = ''.join(idata.xpath('//div[@class="buying" and contains(., "Author")]/a/text()'))
is_kindle = idata.xpath('boolean(//div[@class="buying"]/h1/span/span[contains(text(), "Kindle Edition")])')
if is_kindle:
search_result.formats = 'Kindle'
if idata.xpath('boolean(//div[@class="content"]//li/b[contains(text(), "' +
drm_search_text + '")])'):
if idata.xpath('boolean(//div[@class="content"]//li[contains(., "' +
drm_free_text + '") and contains(b, "' +
drm_search_text + '")])'):
search_result.drm = SearchResult.DRM_UNLOCKED
else:
search_result.drm = SearchResult.DRM_UNKNOWN
else:
search_result.drm = SearchResult.DRM_LOCKED
return True
pass

View File

@ -6,7 +6,6 @@ __license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>'
__docformat__ = 'restructuredtext en'
import random
import re
import urllib2
from contextlib import closing
@ -25,23 +24,12 @@ from calibre.gui2.store.web_store_dialog import WebStoreDialog
class EHarlequinStore(BasicStoreConfig, StorePlugin):
def open(self, parent=None, detail_item=None, external=False):
m_url = 'http://www.dpbolvw.net/'
h_click = 'click-4879827-534091'
d_click = 'click-4879827-10375439'
# Use Kovid's affiliate id 30% of the time.
if random.randint(1, 10) in (1, 2, 3):
h_click = 'click-4913808-534091'
d_click = 'click-4913808-10375439'
url = m_url + h_click
detail_url = None
if detail_item:
detail_url = m_url + d_click + detail_item
url = 'http://www.harlequin.com/'
if external or self.config.get('open_external', False):
open_url(QUrl(url_slash_cleaner(detail_url if detail_url else url)))
open_url(QUrl(url_slash_cleaner(detail_item if detail_item else url)))
else:
d = WebStoreDialog(self.gui, url, parent, detail_url)
d = WebStoreDialog(self.gui, url, parent, detail_item)
d.setWindowTitle(self.name)
d.set_tags(self.config.get('tags', ''))
d.exec_()
@ -74,7 +62,7 @@ class EHarlequinStore(BasicStoreConfig, StorePlugin):
s.title = title.strip()
s.author = author.strip()
s.price = price.strip()
s.detail_item = '?url=http://ebooks.eharlequin.com/' + id.strip()
s.detail_item = 'http://ebooks.eharlequin.com/' + id.strip()
s.formats = 'EPUB'
yield s

View File

@ -0,0 +1,80 @@
# -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function)
__license__ = 'GPL 3'
__copyright__ = '2011-2012, Tomasz Długosz <tomek3d@gmail.com>'
__docformat__ = 'restructuredtext en'
import re
import urllib
from contextlib import closing
from lxml import html
from PyQt4.Qt import QUrl
from calibre import browser, url_slash_cleaner
from calibre.gui2 import open_url
from calibre.gui2.store import StorePlugin
from calibre.gui2.store.basic_config import BasicStoreConfig
from calibre.gui2.store.search_result import SearchResult
from calibre.gui2.store.web_store_dialog import WebStoreDialog
class EmpikStore(BasicStoreConfig, StorePlugin):
def open(self, parent=None, detail_item=None, external=False):
plain_url = 'http://www.empik.com/ebooki'
url = 'https://ssl.afiliant.com/affskrypt,,2f9de2,,23c7f,,,?u=(' + plain_url + ')'
detail_url = None
if detail_item:
detail_url = 'https://ssl.afiliant.com/affskrypt,,2f9de2,,23c7f,,,?u=(' + detail_item + ')'
if external or self.config.get('open_external', False):
open_url(QUrl(url_slash_cleaner(detail_url if detail_url else url)))
else:
d = WebStoreDialog(self.gui, url, parent, detail_url)
d.setWindowTitle(self.name)
d.set_tags(self.config.get('tags', ''))
d.exec_()
def search(self, query, max_results=10, timeout=60):
url = 'http://www.empik.com/szukaj/produkt?c=ebooki-ebooki&q=' + urllib.quote(query) + '&qtype=basicForm&start=1&catalogType=pl&searchCategory=3501&resultsPP=' + str(max_results)
br = browser()
counter = max_results
with closing(br.open(url, timeout=timeout)) as f:
doc = html.fromstring(f.read())
for data in doc.xpath('//div[@class="productsSet"]/div'):
if counter <= 0:
break
id = ''.join(data.xpath('.//a[@class="productBox-450Title"]/@href'))
if not id:
continue
cover_url = ''.join(data.xpath('.//div[@class="productBox-450Pic"]/a/img/@src'))
title = ''.join(data.xpath('.//a[@class="productBox-450Title"]/text()'))
title = re.sub(r' \(ebook\)', '', title)
author = ''.join(data.xpath('.//div[@class="productBox-450Author"]/a/text()'))
price = ''.join(data.xpath('.//div[@class="actPrice"]/text()'))
formats = ''.join(data.xpath('.//div[@class="productBox-450Type"]/text()'))
formats = re.sub(r'Ebook *,? *','', formats)
formats = re.sub(r'\(.*\)','', formats)
drm = data.xpath('boolean(.//div[@class="productBox-450Type" and contains(text(), "ADE")])')
counter -= 1
s = SearchResult()
s.cover_url = cover_url
s.title = title.strip() + ' ' + formats
s.author = author.strip()
s.price = price
s.detail_item = 'http://empik.com' + id.strip()
s.formats = formats.upper().strip()
s.drm = SearchResult.DRM_LOCKED if drm else SearchResult.DRM_UNLOCKED
yield s

View File

@ -68,10 +68,10 @@ class GoogleBooksStore(BasicStoreConfig, StorePlugin):
continue
title = ''.join(data.xpath('.//h3/a//text()'))
authors = data.xpath('.//span[@class="f"]//a//text()')
if authors and authors[-1].strip().lower() in ('preview', 'read'):
authors = data.xpath('.//div[@class="f"]//a//text()')
while authors and authors[-1].strip().lower() in ('preview', 'read', 'more editions'):
authors = authors[:-1]
else:
if not authors:
continue
author = ', '.join(authors)

View File

@ -7,6 +7,7 @@ __copyright__ = '2011, John Schember <john@nachtimwald.com>'
__docformat__ = 'restructuredtext en'
import random
import urllib
import urllib2
from contextlib import closing
@ -24,23 +25,24 @@ from calibre.gui2.store.web_store_dialog import WebStoreDialog
class KoboStore(BasicStoreConfig, StorePlugin):
def open(self, parent=None, detail_item=None, external=False):
m_url = 'http://www.dpbolvw.net/'
h_click = 'click-4879827-10762497'
d_click = 'click-4879827-10772898'
pub_id = 'sHa5EXvYOwA'
# Use Kovid's affiliate id 30% of the time.
if random.randint(1, 10) in (1, 2, 3):
h_click = 'click-4913808-10762497'
d_click = 'click-4913808-10772898'
pub_id = '0dsO3kDu/AU'
murl = 'http://click.linksynergy.com/fs-bin/click?id=%s&offerid=268429.4&type=3&subid=0' % pub_id
url = m_url + h_click
detail_url = None
if detail_item:
detail_url = m_url + d_click + detail_item
purl = 'http://click.linksynergy.com/link?id=%s&offerid=268429&type=2&murl=%s' % (pub_id, urllib.quote_plus(detail_item))
url = purl
else:
purl = None
url = murl
if external or self.config.get('open_external', False):
open_url(QUrl(url_slash_cleaner(detail_url if detail_url else url)))
open_url(QUrl(url_slash_cleaner(url)))
else:
d = WebStoreDialog(self.gui, url, parent, detail_url)
d = WebStoreDialog(self.gui, murl, parent, purl)
d.setWindowTitle(self.name)
d.set_tags(self.config.get('tags', ''))
d.exec_()
@ -60,15 +62,19 @@ class KoboStore(BasicStoreConfig, StorePlugin):
id = ''.join(data.xpath('.//div[@class="SearchImageContainer"]/a[1]/@href'))
if not id:
continue
try:
id = id.split('?', 1)[0]
except:
continue
price = ''.join(data.xpath('.//span[@class="OurPrice"]/strong/text()'))
price = ''.join(data.xpath('.//span[@class="KV2OurPrice"]/strong/text()'))
if not price:
price = '$0.00'
cover_url = ''.join(data.xpath('.//div[@class="SearchImageContainer"]//img[1]/@src'))
title = ''.join(data.xpath('.//div[@class="SCItemHeader"]/h1/a[1]/text()'))
author = ', '.join(data.xpath('.//div[@class="SCItemSummary"]//span//a/text()'))
title = ''.join(data.xpath('.//div[@class="SCItemHeader"]//a[1]/text()'))
author = ', '.join(data.xpath('.//div[@class="SCItemSummary"]//span[contains(@class, "Author")]//a/text()'))
drm = data.xpath('boolean(.//span[@class="SCAvailibilityFormatsText" and not(contains(text(), "DRM-Free"))])')
counter -= 1
@ -78,7 +84,7 @@ class KoboStore(BasicStoreConfig, StorePlugin):
s.title = title.strip()
s.author = author.strip()
s.price = price.strip()
s.detail_item = '?url=http://www.kobobooks.com/' + id.strip()
s.detail_item = 'http://www.kobobooks.com/' + id.strip()
s.drm = SearchResult.DRM_LOCKED if drm else SearchResult.DRM_UNLOCKED
s.formats = 'EPUB'

View File

@ -25,7 +25,7 @@ class LibreDEStore(BasicStoreConfig, StorePlugin):
def open(self, parent=None, detail_item=None, external=False):
url = 'http://ad.zanox.com/ppc/?18817073C15644254T'
url_details = ('http://ad.zanox.com/ppc/?18817073C15644254T&ULP=[['
'http://www.libri.de/shop/action/productDetails?artiId={0}]]')
'http://www.ebook.de/shop/action/productDetails?artiId={0}]]')
if external or self.config.get('open_external', False):
if detail_item:
@ -41,33 +41,38 @@ class LibreDEStore(BasicStoreConfig, StorePlugin):
d.exec_()
def search(self, query, max_results=10, timeout=60):
url = ('http://www.libri.de/shop/action/quickSearch?facetNodeId=6'
'&mainsearchSubmit=Los!&searchString=' + urllib2.quote(query))
url = ('http://www.ebook.de/de/pathSearch?nav=52122&searchString='
+ urllib2.quote(query))
br = browser()
counter = max_results
with closing(br.open(url, timeout=timeout)) as f:
doc = html.fromstring(f.read())
for data in doc.xpath('//div[contains(@class, "item")]'):
for data in doc.xpath('//div[contains(@class, "articlecontainer")]'):
if counter <= 0:
break
details = data.xpath('./div[@class="beschreibungContainer"]')
details = data.xpath('./div[@class="articleinfobox"]')
if not details:
continue
details = details[0]
id = ''.join(details.xpath('./div[@class="text"]/a/@name')).strip()
if not id:
id_ = ''.join(details.xpath('./a/@name')).strip()
if not id_:
continue
cover_url = ''.join(details.xpath('.//div[@class="coverImg"]/a/img/@src'))
title = ''.join(details.xpath('./div[@class="text"]/span[@class="titel"]/a/text()')).strip()
author = ''.join(details.xpath('./div[@class="text"]/span[@class="author"]/text()')).strip()
title = ''.join(details.xpath('.//a[@class="su1_c_l_titel"]/text()')).strip()
author = ''.join(details.xpath('.//div[@class="author"]/text()')).strip()
if author.startswith('von'):
author = author[4:]
pdf = details.xpath(
'boolean(.//span[@class="format" and contains(text(), "pdf")]/text())')
'boolean(.//span[@class="bindername" and contains(text(), "pdf")]/text())')
epub = details.xpath(
'boolean(.//span[@class="format" and contains(text(), "epub")]/text())')
'boolean(.//span[@class="bindername" and contains(text(), "epub")]/text())')
mobi = details.xpath(
'boolean(.//span[@class="format" and contains(text(), "mobipocket")]/text())')
'boolean(.//span[@class="bindername" and contains(text(), "mobipocket")]/text())')
cover_url = ''.join(data.xpath('.//div[@class="coverImg"]/a/img/@src'))
price = ''.join(data.xpath('.//span[@class="preis"]/text()')).replace('*', '').strip()
counter -= 1
@ -78,7 +83,7 @@ class LibreDEStore(BasicStoreConfig, StorePlugin):
s.author = author.strip()
s.price = price
s.drm = SearchResult.DRM_UNKNOWN
s.detail_item = id
s.detail_item = id_
formats = []
if epub:
formats.append('ePub')

View File

@ -485,7 +485,7 @@ class DocumentView(QWebView): # {{{
self.dictionary_action.triggered.connect(self.lookup)
self.addAction(self.dictionary_action)
self.image_popup = ImagePopup(self)
self.view_image_action = QAction(_('View &image...'), self)
self.view_image_action = QAction(QIcon(I('view-image.png')), _('View &image...'), self)
self.view_image_action.triggered.connect(self.image_popup)
self.search_action = QAction(QIcon(I('dictionary.png')),
_('&Search for next occurrence'), self)

View File

@ -8,7 +8,8 @@ __copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
from PyQt4.Qt import (QDialog, QPixmap, QUrl, QScrollArea, QLabel, QSizePolicy,
QDialogButtonBox, QVBoxLayout, QPalette, QApplication, QSize, QIcon, Qt)
QDialogButtonBox, QVBoxLayout, QPalette, QApplication, QSize, QIcon,
Qt, QTransform)
from calibre.gui2 import choose_save_file, gprefs
@ -37,12 +38,15 @@ class ImageView(QDialog):
self.zi_button = zi = bb.addButton(_('Zoom &in'), bb.ActionRole)
self.zo_button = zo = bb.addButton(_('Zoom &out'), bb.ActionRole)
self.save_button = so = bb.addButton(_('&Save as'), bb.ActionRole)
self.rotate_button = ro = bb.addButton(_('&Rotate'), bb.ActionRole)
zi.setIcon(QIcon(I('plus.png')))
zo.setIcon(QIcon(I('minus.png')))
so.setIcon(QIcon(I('save.png')))
ro.setIcon(QIcon(I('rotate-right.png')))
zi.clicked.connect(self.zoom_in)
zo.clicked.connect(self.zoom_out)
so.clicked.connect(self.save_image)
ro.clicked.connect(self.rotate_image)
self.l = l = QVBoxLayout()
self.setLayout(l)
@ -76,6 +80,14 @@ class ImageView(QDialog):
self.scrollarea.verticalScrollBar()):
sb.setValue(int(factor*sb.value()) + ((factor - 1) * sb.pageStep()/2))
def rotate_image(self):
pm = self.label.pixmap()
t = QTransform()
t.rotate(90)
pm = pm.transformed(t)
self.label.setPixmap(pm)
self.label.adjustSize()
def __call__(self):
geom = self.avail_geom
self.label.setPixmap(self.current_img)
@ -93,6 +105,14 @@ class ImageView(QDialog):
gprefs['viewer_image_popup_geometry'] = bytearray(self.saveGeometry())
return QDialog.done(self, e)
def wheelEvent(self, event):
if event.delta() < -14:
self.zoom_out()
event.accept()
elif event.delta() > 14:
event.accept()
self.zoom_in()
class ImagePopup(object):
def __init__(self, parent):
@ -114,3 +134,12 @@ class ImagePopup(object):
if not d.isVisible():
self.dialogs.remove(d)
if __name__ == '__main__':
import sys
app = QApplication([])
p = QPixmap()
p.load(sys.argv[-1])
u = QUrl.fromLocalFile(sys.argv[-1])
d = ImageView(None, p, u)
d()
app.exec_()

View File

@ -1137,6 +1137,7 @@ def main(args=sys.argv):
if pid <= 0:
override = 'calibre-ebook-viewer' if islinux else None
app = Application(args, override_program_name=override)
app.load_builtin_fonts()
app.setWindowIcon(QIcon(I('viewer.png')))
QApplication.setOrganizationName(ORG_NAME)
QApplication.setApplicationName(APP_UID)

View File

@ -3,18 +3,16 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
'''
Miscellaneous widgets used in the GUI
'''
import re, traceback, os
import re, os
from PyQt4.Qt import (QIcon, QFont, QLabel, QListWidget, QAction,
QListWidgetItem, QTextCharFormat, QApplication, QSyntaxHighlighter,
QCursor, QColor, QWidget, QPixmap, QSplitterHandle, QToolButton,
QAbstractListModel, QVariant, Qt, SIGNAL, pyqtSignal, QRegExp, QSize,
QSplitter, QPainter, QLineEdit, QComboBox, QPen, QGraphicsScene, QMenu,
QStringListModel, QCompleter, QStringList, QTimer, QRect,
QFontDatabase, QGraphicsView, QByteArray)
QVariant, Qt, SIGNAL, pyqtSignal, QRegExp, QSize, QSplitter, QPainter,
QLineEdit, QComboBox, QPen, QGraphicsScene, QMenu, QStringListModel,
QCompleter, QStringList, QTimer, QRect, QGraphicsView, QByteArray)
from calibre.constants import iswindows
from calibre.gui2 import (NONE, error_dialog, pixmap_to_data, gprefs,
from calibre.gui2 import (error_dialog, pixmap_to_data, gprefs,
warning_dialog)
from calibre.gui2.filename_pattern_ui import Ui_Form
from calibre import fit_image
@ -348,46 +346,6 @@ class CoverView(QGraphicsView, ImageDropMixin): # {{{
# }}}
class FontFamilyModel(QAbstractListModel): # {{{
def __init__(self, *args):
QAbstractListModel.__init__(self, *args)
from calibre.utils.fonts import fontconfig
try:
self.families = fontconfig.find_font_families()
except:
self.families = []
print 'WARNING: Could not load fonts'
traceback.print_exc()
# Restrict to Qt families as Qt tends to crash
qt_families = set([unicode(x) for x in QFontDatabase().families()])
self.families = list(qt_families.intersection(set(self.families)))
self.families.sort()
self.families[:0] = [_('None')]
self.font = QFont('Arial' if iswindows else 'sansserif')
def rowCount(self, *args):
return len(self.families)
def data(self, index, role):
try:
family = self.families[index.row()]
except:
traceback.print_exc()
return NONE
if role == Qt.DisplayRole:
return QVariant(family)
if role == Qt.FontRole:
# If a user chooses some non standard font as the interface font,
# rendering some font names causes Qt to crash, so return what is
# hopefully a "safe" font
return QVariant(self.font)
return NONE
def index_of(self, family):
return self.families.index(family.strip())
# }}}
# BasicList {{{
class BasicListItem(QListWidgetItem):

View File

@ -41,6 +41,13 @@ class EPUB_MOBI(CatalogPlugin):
help = _('Title of generated catalog used as title in metadata.\n'
"Default: '%default'\n"
"Applies to: AZW3, ePub, MOBI output formats")),
Option('--cross-reference-authors',
default=False,
dest='cross_reference_authors',
action = 'store_true',
help=_("Create cross-references in Authors section for books with multiple authors.\n"
"Default: '%default'\n"
"Applies to: AZW3, ePub, MOBI output formats")),
Option('--debug-pipeline',
default=None,
dest='debug_pipeline',
@ -58,7 +65,6 @@ class EPUB_MOBI(CatalogPlugin):
help=_("Regex describing tags to exclude as genres.\n"
"Default: '%default' excludes bracketed tags, e.g. '[Project Gutenberg]', and '+', the default tag for read books.\n"
"Applies to: AZW3, ePub, MOBI output formats")),
Option('--exclusion-rules',
default="(('Catalogs','Tags','Catalog'),)",
dest='exclusion_rules',
@ -72,7 +78,6 @@ class EPUB_MOBI(CatalogPlugin):
"When multiple rules are defined, all rules will be applied.\n"
"Default: \n" + '"' + '%default' + '"' + "\n"
"Applies to AZW3, ePub, MOBI output formats")),
Option('--generate-authors',
default=False,
dest='generate_authors',
@ -318,8 +323,8 @@ class EPUB_MOBI(CatalogPlugin):
build_log.append(" opts:")
for key in keys:
if key in ['catalog_title','author_clip','connected_kindle','creator',
'description_clip','exclude_book_marker','exclude_genre',
'exclude_tags','exclusion_rules', 'fmt',
'cross_reference_authors','description_clip','exclude_book_marker',
'exclude_genre','exclude_tags','exclusion_rules', 'fmt',
'header_note_source_field','merge_comments_rule',
'output_profile','prefix_rules','read_book_marker',
'search_text','sort_by','sort_descriptions_by_author','sync',

View File

@ -14,11 +14,12 @@ from calibre.customize.conversion import DummyReporter
from calibre.customize.ui import output_profiles
from calibre.ebooks.BeautifulSoup import BeautifulSoup, BeautifulStoneSoup, Tag, NavigableString
from calibre.ebooks.chardet import substitute_entites
from calibre.ebooks.metadata import author_to_author_sort
from calibre.library.catalogs import AuthorSortMismatchException, EmptyCatalogException
from calibre.ptempfile import PersistentTemporaryDirectory
from calibre.utils.config import config_dir
from calibre.utils.date import format_date, is_date_undefined, now as nowf
from calibre.utils.filenames import ascii_text
from calibre.utils.filenames import ascii_text, shorten_components_to
from calibre.utils.icu import capitalize, collation_order, sort_key
from calibre.utils.magick.draw import thumbnail
from calibre.utils.zipfile import ZipFile
@ -109,6 +110,7 @@ class CatalogBuilder(object):
self.stylesheet = stylesheet
self.cache_dir = os.path.join(config_dir, 'caches', 'catalog')
self.catalog_path = PersistentTemporaryDirectory("_epub_mobi_catalog", prefix='')
self.content_dir = os.path.join(self.catalog_path, "content")
self.excluded_tags = self.get_excluded_tags()
self.generate_for_kindle_azw3 = True if (_opts.fmt == 'azw3' and
_opts.output_profile and
@ -127,12 +129,13 @@ class CatalogBuilder(object):
self.books_by_title = None
self.books_by_title_no_series_prefix = None
self.books_to_catalog = None
self.content_dir = os.path.join(self.catalog_path, "content")
self.current_step = 0.0
self.error = []
self.generate_recently_read = False
self.genres = []
self.genre_tags_dict = None
self.genre_tags_dict = \
self.filter_db_tags(max_len = 245 - len("%s/Genre_.html" % self.content_dir)) \
if self.opts.generate_genres else None
self.html_filelist_1 = []
self.html_filelist_2 = []
self.merge_comments_rule = dict(zip(['field','position','hr'],
@ -505,7 +508,7 @@ class CatalogBuilder(object):
if not os.path.isdir(images_path):
os.makedirs(images_path)
def detect_author_sort_mismatches(self):
def detect_author_sort_mismatches(self, books_to_test):
""" Detect author_sort mismatches.
Sort by author, look for inconsistencies in author_sort among
@ -513,17 +516,18 @@ class CatalogBuilder(object):
annoyance for EPUB.
Inputs:
self.books_to_catalog (list): list of books to catalog
books_by_author (list): list of books to test, possibly unsorted
Output:
self.books_by_author (list): sorted by author
(none)
Exceptions:
AuthorSortMismatchException: author_sort mismatch detected
"""
self.books_by_author = sorted(list(self.books_to_catalog), key=self._kf_books_by_author_sorter_author)
authors = [(record['author'], record['author_sort']) for record in self.books_by_author]
books_by_author = sorted(list(books_to_test), key=self._kf_books_by_author_sorter_author)
authors = [(record['author'], record['author_sort']) for record in books_by_author]
current_author = authors[0]
for (i,author) in enumerate(authors):
if author != current_author and i:
@ -582,7 +586,10 @@ class CatalogBuilder(object):
if rule['field'].lower() == 'tags':
if rule['pattern'].lower() in map(unicode.lower,record['tags']):
if self.opts.verbose:
_log_prefix_rule_match_info(rule, record, rule['pattern'])
self.opts.log.info(" %s '%s' by %s (%s: Tags includes '%s')" %
(rule['prefix'],record['title'],
record['authors'][0], rule['name'],
rule['pattern']))
return rule['prefix']
# Regex match for custom field
@ -698,6 +705,7 @@ class CatalogBuilder(object):
def fetch_books_by_author(self):
""" Generate a list of books sorted by author.
For books with multiple authors, relist book with additional authors.
Sort the database by author. Report author_sort inconsistencies as warning when
building EPUB or MOBI, error when building MOBI. Collect a list of unique authors
to self.authors.
@ -717,25 +725,30 @@ class CatalogBuilder(object):
self.update_progress_full_step(_("Sorting database"))
self.detect_author_sort_mismatches()
books_by_author = list(self.books_to_catalog)
self.detect_author_sort_mismatches(books_by_author)
if self.opts.cross_reference_authors:
books_by_author = self.relist_multiple_authors(books_by_author)
#books_by_author = sorted(list(books_by_author), key=self._kf_books_by_author_sorter_author)
# Sort authors using sort_key to normalize accented letters
# Determine the longest author_sort length before sorting
asl = [i['author_sort'] for i in self.books_by_author]
asl = [i['author_sort'] for i in books_by_author]
las = max(asl, key=len)
self.books_by_author = sorted(self.books_to_catalog,
books_by_author = sorted(books_by_author,
key=lambda x: sort_key(self._kf_books_by_author_sorter_author_sort(x, len(las))))
if self.DEBUG and self.opts.verbose:
tl = [i['title'] for i in self.books_by_author]
tl = [i['title'] for i in books_by_author]
lt = max(tl, key=len)
fs = '{:<6}{:<%d} {:<%d} {!s}' % (len(lt),len(las))
print(fs.format('','Title','Author','Series'))
for i in self.books_by_author:
for i in books_by_author:
print(fs.format('', i['title'],i['author_sort'],i['series']))
# Build the unique_authors set from existing data
authors = [(record['author'], capitalize(record['author_sort'])) for record in self.books_by_author]
authors = [(record['author'], capitalize(record['author_sort'])) for record in books_by_author]
# authors[] contains a list of all book authors, with multiple entries for multiple books by author
# authors[]: (([0]:friendly [1]:sort))
@ -773,6 +786,7 @@ class CatalogBuilder(object):
author[2])).encode('utf-8'))
self.authors = unique_authors
self.books_by_author = books_by_author
return True
def fetch_books_by_title(self):
@ -860,15 +874,15 @@ class CatalogBuilder(object):
this_title['series_index'] = 0.0
this_title['title_sort'] = self.generate_sort_title(this_title['title'])
if 'authors' in record:
# from calibre.ebooks.metadata import authors_to_string
# return authors_to_string(self.authors)
if 'authors' in record:
this_title['authors'] = record['authors']
# Synthesize author attribution from authors list
if record['authors']:
this_title['author'] = " &amp; ".join(record['authors'])
else:
this_title['author'] = 'Unknown'
this_title['author'] = _('Unknown')
this_title['authors'] = [this_title['author']]
if 'author_sort' in record and record['author_sort'].strip():
this_title['author_sort'] = record['author_sort']
@ -1090,7 +1104,7 @@ class CatalogBuilder(object):
self.bookmarked_books = bookmarks
def filter_db_tags(self):
def filter_db_tags(self, max_len):
""" Remove excluded tags from data set, return normalized genre list.
Filter all db tags, removing excluded tags supplied in opts.
@ -1098,13 +1112,13 @@ class CatalogBuilder(object):
tags are flattened to alphanumeric ascii_text.
Args:
(none)
max_len: maximum length of normalized tag to fit within OS constraints
Return:
genre_tags_dict (dict): dict of filtered, normalized tags in data set
"""
def _format_tag_list(tags, indent=2, line_break=70, header='Tag list'):
def _format_tag_list(tags, indent=1, line_break=70, header='Tag list'):
def _next_tag(sorted_tags):
for (i, tag) in enumerate(sorted_tags):
if i < len(tags) - 1:
@ -1123,6 +1137,31 @@ class CatalogBuilder(object):
out_str = ' ' * (indent + 1)
return ans + out_str
def _normalize_tag(tag, max_len):
""" Generate an XHTML-legal anchor string from tag.
Parse tag for non-ascii, convert to unicode name.
Args:
tags (str): tag name possible containing symbols
max_len (int): maximum length of tag
Return:
normalized (str): unicode names substituted for non-ascii chars,
clipped to max_len
"""
normalized = massaged = re.sub('\s','',ascii_text(tag).lower())
if re.search('\W',normalized):
normalized = ''
for c in massaged:
if re.search('\W',c):
normalized += self.generate_unicode_name(c)
else:
normalized += c
shortened = shorten_components_to(max_len, [normalized])[0]
return shortened
# Entry point
normalized_tags = []
friendly_tags = []
@ -1141,7 +1180,7 @@ class CatalogBuilder(object):
if tag == ' ':
continue
normalized_tags.append(self.normalize_tag(tag))
normalized_tags.append(_normalize_tag(tag, max_len))
friendly_tags.append(tag)
genre_tags_dict = dict(zip(friendly_tags,normalized_tags))
@ -1938,8 +1977,6 @@ class CatalogBuilder(object):
self.update_progress_full_step(_("Genres HTML"))
self.genre_tags_dict = self.filter_db_tags()
# Extract books matching filtered_tags
genre_list = []
for friendly_tag in sorted(self.genre_tags_dict, key=sort_key):
@ -2021,10 +2058,11 @@ class CatalogBuilder(object):
books_by_current_author += 1
# Write the genre book list as an article
titles_spanned = self.generate_html_by_genre(genre, True if index==0 else False,
outfile = "%s/Genre_%s.html" % (self.content_dir, genre)
titles_spanned = self.generate_html_by_genre(genre,
True if index==0 else False,
genre_tag_set[genre],
"%s/Genre_%s.html" % (self.content_dir,
genre))
outfile)
tag_file = "content/Genre_%s.html" % genre
master_genre_list.append({'tag':genre,
@ -2546,7 +2584,7 @@ class CatalogBuilder(object):
for (i, tag) in enumerate(sorted(book.get('tags', []))):
aTag = Tag(_soup,'a')
if self.opts.generate_genres:
aTag['href'] = "Genre_%s.html" % self.normalize_tag(tag)
aTag['href'] = "Genre_%s.html" % self.genre_tags_dict[tag]
aTag.insert(0,escape(NavigableString(tag)))
genresTag.insert(gtc, aTag)
gtc += 1
@ -2757,7 +2795,6 @@ class CatalogBuilder(object):
"""
from calibre.ebooks.conversion.config import load_defaults
from calibre.utils.fonts import fontconfig
MI_WIDTH = 600
MI_HEIGHT = 60
@ -2767,11 +2804,10 @@ class CatalogBuilder(object):
masthead_font_family = recs.get('masthead_font', 'Default')
if masthead_font_family != 'Default':
masthead_font = fontconfig.files_for_family(masthead_font_family)
# Assume 'normal' always in dict, else use default
# {'normal': (path_to_font, friendly name)}
if 'normal' in masthead_font:
font_path = masthead_font['normal'][0]
from calibre.utils.fonts.scanner import font_scanner
faces = font_scanner.fonts_for_family(masthead_font_family)
if faces:
font_path = faces[0]['path']
if not font_path or not os.access(font_path, os.R_OK):
font_path = default_font
@ -4602,28 +4638,6 @@ class CatalogBuilder(object):
return merged
def normalize_tag(self, tag):
""" Generate an XHTML-legal anchor string from tag.
Parse tag for non-ascii, convert to unicode name.
Args:
tags (str): tag name possible containing symbols
Return:
normalized (str): unicode names substituted for non-ascii chars
"""
normalized = massaged = re.sub('\s','',ascii_text(tag).lower())
if re.search('\W',normalized):
normalized = ''
for c in massaged:
if re.search('\W',c):
normalized += self.generate_unicode_name(c)
else:
normalized += c
return normalized
def process_exclusions(self, data_set):
""" Filter data_set based on exclusion_rules.
@ -4696,6 +4710,43 @@ class CatalogBuilder(object):
else:
return data_set
def relist_multiple_authors(self, books_by_author):
""" Create multiple entries for books with multiple authors
Given a list of books by author, scan list for books with multiple
authors. Add a cloned copy of the book per additional author.
Args:
books_by_author (list): book list possibly containing books
with multiple authors
Return:
(list): books_by_author with additional cloned entries for books with
multiple authors
"""
multiple_author_books = []
# Find the multiple author books
for book in books_by_author:
if len(book['authors']) > 1:
multiple_author_books.append(book)
for book in multiple_author_books:
cloned_authors = list(book['authors'])
for x, author in enumerate(book['authors']):
if x:
first_author = cloned_authors.pop(0)
cloned_authors.append(first_author)
new_book = deepcopy(book)
new_book['author'] = ' & '.join(cloned_authors)
new_book['authors'] = list(cloned_authors)
asl = [author_to_author_sort(auth) for auth in cloned_authors]
new_book['author_sort'] = ' & '.join(asl)
books_by_author.append(new_book)
return books_by_author
def update_progress_full_step(self, description):
""" Update calibre's job status UI.

View File

@ -292,6 +292,7 @@ class CustomColumns(object):
if num is not None:
data = self.custom_column_num_map[num]
table,lt = self.custom_table_names(data['num'])
self.dirty_books_referencing('#'+data['label'], id, commit=False)
self.conn.execute('DELETE FROM %s WHERE value=?'%lt, (id,))
self.conn.execute('DELETE FROM %s WHERE id=?'%table, (id,))
self.conn.commit()

View File

@ -646,12 +646,13 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
spath = os.path.join(self.library_path, *current_path.split('/'))
tpath = os.path.join(self.library_path, *path.split('/'))
wam = WindowsAtomicFolderMove(spath) if iswindows and current_path else None
source_ok = current_path and os.path.exists(spath)
wam = WindowsAtomicFolderMove(spath) if iswindows and source_ok else None
try:
if not os.path.exists(tpath):
os.makedirs(tpath)
if current_path and os.path.exists(spath): # Migrate existing files
if source_ok: # Migrate existing files
self.copy_cover_to(id, os.path.join(tpath, 'cover.jpg'),
index_is_id=True, windows_atomic_move=wam,
use_hardlink=True)
@ -669,7 +670,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
self.conn.commit()
self.data.set(id, self.FIELD_MAP['path'], path, row_is_id=True)
# Delete not needed directories
if current_path and os.path.exists(spath):
if source_ok:
if not samefile(spath, tpath):
if wam is not None:
wam.delete_originals()
@ -1432,7 +1433,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
if use_hardlink:
try:
hardlink_file(path, dest)
return
return True
except:
pass
with lopen(dest, 'wb') as d:
@ -2204,13 +2205,14 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
def set(self, row, column, val, allow_case_change=False):
'''
Convenience method for setting the title, authors, publisher or rating
Convenience method for setting the title, authors, publisher, tags or
rating
'''
id = self.data[row][0]
col = {'title':1, 'authors':2, 'publisher':3, 'rating':4, 'tags':7}[column]
col = self.FIELD_MAP[column]
books_to_refresh = set()
self.data.set(row, col, val)
set_args = (row, col, val)
if column == 'authors':
val = string_to_authors(val)
books_to_refresh |= self.set_authors(id, val, notify=False,
@ -2226,6 +2228,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
books_to_refresh |= \
self.set_tags(id, [x.strip() for x in val.split(',') if x.strip()],
append=False, notify=False, allow_case_change=allow_case_change)
self.data.set(*set_args)
self.data.refresh_ids(self, [id])
self.set_path(id, True)
self.notify('metadata', [id])
@ -2473,6 +2476,23 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
self.clean_standard_field('authors', commit=True)
return books_to_refresh
def windows_check_if_files_in_use(self, book_id):
'''
Raises an EACCES IOError if any of the files in the folder of book_id
are opened in another program on windows.
'''
if iswindows:
path = self.path(book_id, index_is_id=True)
if path:
spath = os.path.join(self.library_path, *path.split('/'))
wam = None
if os.path.exists(spath):
try:
wam = WindowsAtomicFolderMove(spath)
finally:
if wam is not None:
wam.close_handles()
def set_authors(self, id, authors, notify=True, commit=True,
allow_case_change=False):
'''
@ -2481,6 +2501,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
:param authors: A list of authors.
'''
self.windows_check_if_files_in_use(id)
books_to_refresh = self._set_authors(id, authors,
allow_case_change=allow_case_change)
self.dirtied(set([id])|books_to_refresh, commit=False)
@ -2531,6 +2552,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
Note that even if commit is False, the db will still be committed to
because this causes the location of files to change
'''
self.windows_check_if_files_in_use(id)
if not self._set_title(id, title):
return
self.set_path(id, index_is_id=True)

View File

@ -200,6 +200,11 @@ def get_components(template, mi, id, timefmt='%b %Y', length=250,
template = re.sub(r'\{series_index[^}]*?\}', '', template)
if mi.rating is not None:
format_args['rating'] = mi.format_rating(divide_by=2.0)
if mi.identifiers:
format_args['identifiers'] = mi.format_field_extended('identifiers')[1]
else:
format_args['identifiers'] = ''
if hasattr(mi.timestamp, 'timetuple'):
format_args['timestamp'] = strftime(timefmt, mi.timestamp.timetuple())
if hasattr(mi.pubdate, 'timetuple'):

View File

@ -37,14 +37,6 @@ def test_freetype():
test()
print ('FreeType OK!')
def test_fontconfig():
from calibre.utils.fonts import fontconfig
families = fontconfig.find_font_families()
num = len(families)
if num < 10:
raise RuntimeError('Fontconfig found only %d font families'%num)
print ('Fontconfig OK! (%d families)'%num)
def test_winutil():
from calibre.devices.scanner import win_pnp_drives
matches = win_pnp_drives.scanner()
@ -123,13 +115,12 @@ def test():
test_plugins()
test_lxml()
test_freetype()
test_fontconfig()
test_sqlite()
test_qt()
test_imaging()
test_unrar()
test_icu()
test_woff()
test_qt()
if iswindows:
test_win32()
test_winutil()

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: calibre\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-10-24 04:12+0000\n"
"POT-Creation-Date: 2012-10-26 05:12+0000\n"
"PO-Revision-Date: 2012-08-14 16:03+0000\n"
"Last-Translator: Albé Theunissen <Unknown>\n"
"Language-Team: Afrikaans <af@li.org>\n"
@ -15,8 +15,8 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Launchpad-Export-Date: 2012-10-25 05:13+0000\n"
"X-Generator: Launchpad (build 16179)\n"
"X-Launchpad-Export-Date: 2012-10-27 04:37+0000\n"
"X-Generator: Launchpad (build 16194)\n"
#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:56
msgid "Does absolutely nothing"
@ -175,12 +175,12 @@ msgstr "Doen absolute niks"
#: /home/kovid/work/calibre/src/calibre/library/database2.py:586
#: /home/kovid/work/calibre/src/calibre/library/database2.py:594
#: /home/kovid/work/calibre/src/calibre/library/database2.py:605
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2273
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2427
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2857
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3504
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3506
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3643
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2274
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2428
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2858
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3505
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3507
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3644
#: /home/kovid/work/calibre/src/calibre/library/server/content.py:250
#: /home/kovid/work/calibre/src/calibre/library/server/content.py:251
#: /home/kovid/work/calibre/src/calibre/library/server/mobile.py:247
@ -942,26 +942,26 @@ msgstr "Pad na biblioteek te lank. Moet minder as %d karakters wees."
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/book/base.py:666
#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:67
#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:668
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1061
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1062
#: /home/kovid/work/calibre/src/calibre/utils/formatter_functions.py:887
#: /home/kovid/work/calibre/src/calibre/utils/formatter_functions.py:910
msgid "Yes"
msgstr "Ja"
#: /home/kovid/work/calibre/src/calibre/db/fields.py:163
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1216
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1217
msgid "Main"
msgstr "Hoof"
#: /home/kovid/work/calibre/src/calibre/db/fields.py:165
#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:77
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1218
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1219
msgid "Card A"
msgstr "Kaart A"
#: /home/kovid/work/calibre/src/calibre/db/fields.py:167
#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:79
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1220
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1221
msgid "Card B"
msgstr "Kaart B"
@ -1151,14 +1151,14 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:1199
#: /home/kovid/work/calibre/src/calibre/library/database2.py:371
#: /home/kovid/work/calibre/src/calibre/library/database2.py:384
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3361
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3362
#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:187
msgid "News"
msgstr "Nuus"
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:2770
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3317
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3335
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3318
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3336
msgid "Catalog"
msgstr "Katalogus"
@ -1208,10 +1208,10 @@ msgstr "Bambook"
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:128
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:131
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:348
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1307
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1311
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1315
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1635
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1319
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1323
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1642
#: /home/kovid/work/calibre/src/calibre/devices/prst1/driver.py:155
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:144
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:147
@ -12075,6 +12075,10 @@ msgstr ""
msgid "Choose &font family"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/font_family_chooser.py:196
msgid "Clear the font family"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/init.py:108
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:296
msgid "Cover Browser"
@ -13368,7 +13372,7 @@ msgstr ""
msgid ""
"If set, this option will causes calibre to check if a file\n"
" being auto-added is already in the calibre library.\n"
" If it is, a meesage will pop up asking you whether\n"
" If it is, a message will pop up asking you whether\n"
" you want to add it anyway."
msgstr ""
@ -16719,7 +16723,7 @@ msgid "Options to customize the ebook viewer"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/config.py:30
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1106
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1107
msgid "Remember last used window size"
msgstr ""
@ -17310,39 +17314,39 @@ msgstr ""
msgid "Loading ebook..."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:977
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:978
msgid "Could not open ebook"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:978
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:979
msgid "Unknown error"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1093
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1094
msgid "Options to control the ebook viewer"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1100
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1101
msgid ""
"If specified, viewer window will try to come to the front when started."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1103
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1104
msgid ""
"If specified, viewer window will try to open full screen when started."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1108
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1109
msgid "Print javascript alert and console messages to the console"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1110
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1111
msgid ""
"The position at which to open the specified book. The position is a location "
"as displayed in the top left corner of the viewer."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1117
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1118
msgid ""
"%prog [options] file\n"
"\n"
@ -18946,17 +18950,17 @@ msgstr ""
msgid "creating custom column "
msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3669
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3670
#, python-format
msgid "<p>Migrating old database to ebook library in %s<br><center>"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3698
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3699
#, python-format
msgid "Copying <b>%s</b>"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3715
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3716
msgid "Compacting database"
msgstr ""

View File

@ -8,17 +8,17 @@ msgid ""
msgstr ""
"Project-Id-Version: iso_639_3\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/calibre\n"
"POT-Creation-Date: 2012-10-24 04:12+0000\n"
"PO-Revision-Date: 2012-05-24 09:38+0000\n"
"Last-Translator: abbas <abbasalshaikh@gmail.com>\n"
"POT-Creation-Date: 2012-10-26 05:12+0000\n"
"PO-Revision-Date: 2012-10-31 19:43+0000\n"
"Last-Translator: mourad <leslous_mourad@yahoo.fr>\n"
"Language-Team: awadh alghaamdi <awadh_al_ghaamdi@hotmail.com>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n % 100 >= "
"3 && n % 100 <= 10 ? 3 : n % 100 >= 11 && n % 100 <= 99 ? 4 : 5;\n"
"X-Launchpad-Export-Date: 2012-10-25 05:14+0000\n"
"X-Generator: Launchpad (build 16179)\n"
"X-Launchpad-Export-Date: 2012-11-01 04:35+0000\n"
"X-Generator: Launchpad (build 16218)\n"
"X-Poedit-Country: SAUDI ARABIA\n"
"Language: ar\n"
"X-Poedit-Language: Arabic\n"
@ -64,7 +64,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:56
msgid "Does absolutely nothing"
msgstr "لا يفعل شيئًا"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:59
#: /home/kovid/work/calibre/src/calibre/db/cache.py:106
@ -219,12 +219,12 @@ msgstr "لا يفعل شيئًا"
#: /home/kovid/work/calibre/src/calibre/library/database2.py:586
#: /home/kovid/work/calibre/src/calibre/library/database2.py:594
#: /home/kovid/work/calibre/src/calibre/library/database2.py:605
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2273
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2427
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2857
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3504
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3506
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3643
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2274
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2428
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2858
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3505
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3507
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3644
#: /home/kovid/work/calibre/src/calibre/library/server/content.py:250
#: /home/kovid/work/calibre/src/calibre/library/server/content.py:251
#: /home/kovid/work/calibre/src/calibre/library/server/mobile.py:247
@ -235,11 +235,11 @@ msgstr "لا يفعل شيئًا"
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/collection.py:45
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/collection.py:53
msgid "Unknown"
msgstr "غير محدّد"
msgstr "مجهول"
#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:77
msgid "Base"
msgstr "أساس"
msgstr "قاعدة"
#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:148
#: /home/kovid/work/calibre/src/calibre/ebooks/html/to_zip.py:81
@ -272,7 +272,7 @@ msgstr "مولّد الفهرس"
#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:527
msgid "User Interface Action"
msgstr "واجهة المستخدم"
msgstr "العمليات على واجهة المستخدم"
#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:561
#: /home/kovid/work/calibre/src/calibre/gui2/actions/preferences.py:20
@ -1009,26 +1009,26 @@ msgstr "الطريق إلى المكتبة وقتا طويلا. يجب أن يك
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/book/base.py:666
#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:67
#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:668
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1061
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1062
#: /home/kovid/work/calibre/src/calibre/utils/formatter_functions.py:887
#: /home/kovid/work/calibre/src/calibre/utils/formatter_functions.py:910
msgid "Yes"
msgstr "نعم"
#: /home/kovid/work/calibre/src/calibre/db/fields.py:163
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1216
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1217
msgid "Main"
msgstr "الصفحة الرئيسية"
#: /home/kovid/work/calibre/src/calibre/db/fields.py:165
#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:77
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1218
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1219
msgid "Card A"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/db/fields.py:167
#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:79
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1220
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1221
msgid "Card B"
msgstr "بلكبيبي"
@ -1224,14 +1224,14 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:1199
#: /home/kovid/work/calibre/src/calibre/library/database2.py:371
#: /home/kovid/work/calibre/src/calibre/library/database2.py:384
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3361
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3362
#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:187
msgid "News"
msgstr "الأخبار"
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:2770
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3317
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3335
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3318
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3336
msgid "Catalog"
msgstr "الفهرس"
@ -1284,10 +1284,10 @@ msgstr "Bambook"
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:128
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:131
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:348
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1307
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1311
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1315
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1635
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1319
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1323
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1642
#: /home/kovid/work/calibre/src/calibre/devices/prst1/driver.py:155
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:144
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:147
@ -12327,6 +12327,10 @@ msgstr ""
msgid "Choose &font family"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/font_family_chooser.py:196
msgid "Clear the font family"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/init.py:108
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:296
msgid "Cover Browser"
@ -13627,7 +13631,7 @@ msgstr ""
msgid ""
"If set, this option will causes calibre to check if a file\n"
" being auto-added is already in the calibre library.\n"
" If it is, a meesage will pop up asking you whether\n"
" If it is, a message will pop up asking you whether\n"
" you want to add it anyway."
msgstr ""
@ -16992,7 +16996,7 @@ msgid "Options to customize the ebook viewer"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/config.py:30
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1106
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1107
msgid "Remember last used window size"
msgstr "نتذكر الماضي حجم الإطار المستخدمة"
@ -17555,39 +17559,39 @@ msgstr ""
msgid "Loading ebook..."
msgstr "يتم تحميل الكتاب الإلكتروني..."
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:977
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:978
msgid "Could not open ebook"
msgstr "لم يتمكن من فتح الكتاب الإلكتروني"
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:978
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:979
msgid "Unknown error"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1093
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1094
msgid "Options to control the ebook viewer"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1100
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1101
msgid ""
"If specified, viewer window will try to come to the front when started."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1103
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1104
msgid ""
"If specified, viewer window will try to open full screen when started."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1108
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1109
msgid "Print javascript alert and console messages to the console"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1110
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1111
msgid ""
"The position at which to open the specified book. The position is a location "
"as displayed in the top left corner of the viewer."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1117
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1118
msgid ""
"%prog [options] file\n"
"\n"
@ -19194,17 +19198,17 @@ msgstr ""
msgid "creating custom column "
msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3669
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3670
#, python-format
msgid "<p>Migrating old database to ebook library in %s<br><center>"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3698
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3699
#, python-format
msgid "Copying <b>%s</b>"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3715
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3716
msgid "Compacting database"
msgstr ""

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: calibre\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-10-24 04:12+0000\n"
"POT-Creation-Date: 2012-10-26 05:12+0000\n"
"PO-Revision-Date: 2011-09-26 16:28+0000\n"
"Last-Translator: Xandru <xandru@softastur.org>\n"
"Language-Team: Asturian <ast@li.org>\n"
@ -15,8 +15,8 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Launchpad-Export-Date: 2012-10-25 05:14+0000\n"
"X-Generator: Launchpad (build 16179)\n"
"X-Launchpad-Export-Date: 2012-10-27 04:38+0000\n"
"X-Generator: Launchpad (build 16194)\n"
#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:56
msgid "Does absolutely nothing"
@ -175,12 +175,12 @@ msgstr "Nun fai nada"
#: /home/kovid/work/calibre/src/calibre/library/database2.py:586
#: /home/kovid/work/calibre/src/calibre/library/database2.py:594
#: /home/kovid/work/calibre/src/calibre/library/database2.py:605
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2273
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2427
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2857
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3504
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3506
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3643
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2274
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2428
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2858
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3505
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3507
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3644
#: /home/kovid/work/calibre/src/calibre/library/server/content.py:250
#: /home/kovid/work/calibre/src/calibre/library/server/content.py:251
#: /home/kovid/work/calibre/src/calibre/library/server/mobile.py:247
@ -935,26 +935,26 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/book/base.py:666
#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:67
#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:668
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1061
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1062
#: /home/kovid/work/calibre/src/calibre/utils/formatter_functions.py:887
#: /home/kovid/work/calibre/src/calibre/utils/formatter_functions.py:910
msgid "Yes"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/db/fields.py:163
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1216
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1217
msgid "Main"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/db/fields.py:165
#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:77
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1218
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1219
msgid "Card A"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/db/fields.py:167
#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:79
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1220
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1221
msgid "Card B"
msgstr ""
@ -1129,14 +1129,14 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:1199
#: /home/kovid/work/calibre/src/calibre/library/database2.py:371
#: /home/kovid/work/calibre/src/calibre/library/database2.py:384
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3361
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3362
#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:187
msgid "News"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:2770
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3317
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3335
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3318
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3336
msgid "Catalog"
msgstr ""
@ -1184,10 +1184,10 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:128
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:131
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:348
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1307
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1311
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1315
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1635
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1319
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1323
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1642
#: /home/kovid/work/calibre/src/calibre/devices/prst1/driver.py:155
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:144
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:147
@ -12044,6 +12044,10 @@ msgstr ""
msgid "Choose &font family"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/font_family_chooser.py:196
msgid "Clear the font family"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/init.py:108
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:296
msgid "Cover Browser"
@ -13337,7 +13341,7 @@ msgstr ""
msgid ""
"If set, this option will causes calibre to check if a file\n"
" being auto-added is already in the calibre library.\n"
" If it is, a meesage will pop up asking you whether\n"
" If it is, a message will pop up asking you whether\n"
" you want to add it anyway."
msgstr ""
@ -16688,7 +16692,7 @@ msgid "Options to customize the ebook viewer"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/config.py:30
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1106
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1107
msgid "Remember last used window size"
msgstr ""
@ -17279,39 +17283,39 @@ msgstr ""
msgid "Loading ebook..."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:977
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:978
msgid "Could not open ebook"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:978
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:979
msgid "Unknown error"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1093
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1094
msgid "Options to control the ebook viewer"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1100
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1101
msgid ""
"If specified, viewer window will try to come to the front when started."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1103
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1104
msgid ""
"If specified, viewer window will try to open full screen when started."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1108
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1109
msgid "Print javascript alert and console messages to the console"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1110
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1111
msgid ""
"The position at which to open the specified book. The position is a location "
"as displayed in the top left corner of the viewer."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1117
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1118
msgid ""
"%prog [options] file\n"
"\n"
@ -18915,17 +18919,17 @@ msgstr ""
msgid "creating custom column "
msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3669
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3670
#, python-format
msgid "<p>Migrating old database to ebook library in %s<br><center>"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3698
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3699
#, python-format
msgid "Copying <b>%s</b>"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3715
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3716
msgid "Compacting database"
msgstr ""

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: calibre\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-10-24 04:12+0000\n"
"POT-Creation-Date: 2012-10-26 05:12+0000\n"
"PO-Revision-Date: 2012-08-07 14:00+0000\n"
"Last-Translator: Emin Mastizadeh <emin25@ovi.com>\n"
"Language-Team: Azerbaijani <az@li.org>\n"
@ -15,8 +15,8 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Launchpad-Export-Date: 2012-10-25 05:14+0000\n"
"X-Generator: Launchpad (build 16179)\n"
"X-Launchpad-Export-Date: 2012-10-27 04:38+0000\n"
"X-Generator: Launchpad (build 16194)\n"
#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:56
msgid "Does absolutely nothing"
@ -175,12 +175,12 @@ msgstr "Heç bir şey etmir"
#: /home/kovid/work/calibre/src/calibre/library/database2.py:586
#: /home/kovid/work/calibre/src/calibre/library/database2.py:594
#: /home/kovid/work/calibre/src/calibre/library/database2.py:605
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2273
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2427
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2857
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3504
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3506
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3643
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2274
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2428
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2858
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3505
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3507
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3644
#: /home/kovid/work/calibre/src/calibre/library/server/content.py:250
#: /home/kovid/work/calibre/src/calibre/library/server/content.py:251
#: /home/kovid/work/calibre/src/calibre/library/server/mobile.py:247
@ -933,26 +933,26 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/book/base.py:666
#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:67
#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:668
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1061
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1062
#: /home/kovid/work/calibre/src/calibre/utils/formatter_functions.py:887
#: /home/kovid/work/calibre/src/calibre/utils/formatter_functions.py:910
msgid "Yes"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/db/fields.py:163
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1216
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1217
msgid "Main"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/db/fields.py:165
#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:77
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1218
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1219
msgid "Card A"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/db/fields.py:167
#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:79
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1220
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1221
msgid "Card B"
msgstr ""
@ -1127,14 +1127,14 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:1199
#: /home/kovid/work/calibre/src/calibre/library/database2.py:371
#: /home/kovid/work/calibre/src/calibre/library/database2.py:384
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3361
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3362
#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:187
msgid "News"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:2770
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3317
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3335
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3318
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3336
msgid "Catalog"
msgstr ""
@ -1182,10 +1182,10 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:128
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:131
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:348
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1307
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1311
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1315
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1635
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1319
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1323
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1642
#: /home/kovid/work/calibre/src/calibre/devices/prst1/driver.py:155
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:144
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:147
@ -12042,6 +12042,10 @@ msgstr ""
msgid "Choose &font family"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/font_family_chooser.py:196
msgid "Clear the font family"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/init.py:108
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:296
msgid "Cover Browser"
@ -13335,7 +13339,7 @@ msgstr ""
msgid ""
"If set, this option will causes calibre to check if a file\n"
" being auto-added is already in the calibre library.\n"
" If it is, a meesage will pop up asking you whether\n"
" If it is, a message will pop up asking you whether\n"
" you want to add it anyway."
msgstr ""
@ -16686,7 +16690,7 @@ msgid "Options to customize the ebook viewer"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/config.py:30
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1106
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1107
msgid "Remember last used window size"
msgstr ""
@ -17277,39 +17281,39 @@ msgstr ""
msgid "Loading ebook..."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:977
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:978
msgid "Could not open ebook"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:978
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:979
msgid "Unknown error"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1093
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1094
msgid "Options to control the ebook viewer"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1100
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1101
msgid ""
"If specified, viewer window will try to come to the front when started."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1103
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1104
msgid ""
"If specified, viewer window will try to open full screen when started."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1108
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1109
msgid "Print javascript alert and console messages to the console"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1110
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1111
msgid ""
"The position at which to open the specified book. The position is a location "
"as displayed in the top left corner of the viewer."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1117
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1118
msgid ""
"%prog [options] file\n"
"\n"
@ -18913,17 +18917,17 @@ msgstr ""
msgid "creating custom column "
msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3669
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3670
#, python-format
msgid "<p>Migrating old database to ebook library in %s<br><center>"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3698
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3699
#, python-format
msgid "Copying <b>%s</b>"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3715
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3716
msgid "Compacting database"
msgstr ""

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: calibre\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-10-24 04:12+0000\n"
"POT-Creation-Date: 2012-10-26 05:12+0000\n"
"PO-Revision-Date: 2012-10-14 04:57+0000\n"
"Last-Translator: Walid AMMOU <w.ammou@gmail.com>\n"
"Language-Team: Berber (Other) <ber@li.org>\n"
@ -15,8 +15,8 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Launchpad-Export-Date: 2012-10-25 05:15+0000\n"
"X-Generator: Launchpad (build 16179)\n"
"X-Launchpad-Export-Date: 2012-10-27 04:39+0000\n"
"X-Generator: Launchpad (build 16194)\n"
#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:56
msgid "Does absolutely nothing"
@ -175,12 +175,12 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:586
#: /home/kovid/work/calibre/src/calibre/library/database2.py:594
#: /home/kovid/work/calibre/src/calibre/library/database2.py:605
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2273
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2427
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2857
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3504
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3506
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3643
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2274
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2428
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2858
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3505
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3507
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3644
#: /home/kovid/work/calibre/src/calibre/library/server/content.py:250
#: /home/kovid/work/calibre/src/calibre/library/server/content.py:251
#: /home/kovid/work/calibre/src/calibre/library/server/mobile.py:247
@ -929,26 +929,26 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/book/base.py:666
#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:67
#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:668
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1061
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1062
#: /home/kovid/work/calibre/src/calibre/utils/formatter_functions.py:887
#: /home/kovid/work/calibre/src/calibre/utils/formatter_functions.py:910
msgid "Yes"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/db/fields.py:163
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1216
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1217
msgid "Main"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/db/fields.py:165
#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:77
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1218
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1219
msgid "Card A"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/db/fields.py:167
#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:79
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1220
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1221
msgid "Card B"
msgstr ""
@ -1123,14 +1123,14 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:1199
#: /home/kovid/work/calibre/src/calibre/library/database2.py:371
#: /home/kovid/work/calibre/src/calibre/library/database2.py:384
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3361
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3362
#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:187
msgid "News"
msgstr "ⵉⵏⵖⵎⵉⵙⵏ"
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:2770
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3317
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3335
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3318
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3336
msgid "Catalog"
msgstr ""
@ -1178,10 +1178,10 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:128
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:131
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:348
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1307
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1311
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1315
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1635
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1319
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1323
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1642
#: /home/kovid/work/calibre/src/calibre/devices/prst1/driver.py:155
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:144
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:147
@ -12038,6 +12038,10 @@ msgstr ""
msgid "Choose &font family"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/font_family_chooser.py:196
msgid "Clear the font family"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/init.py:108
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:296
msgid "Cover Browser"
@ -13331,7 +13335,7 @@ msgstr ""
msgid ""
"If set, this option will causes calibre to check if a file\n"
" being auto-added is already in the calibre library.\n"
" If it is, a meesage will pop up asking you whether\n"
" If it is, a message will pop up asking you whether\n"
" you want to add it anyway."
msgstr ""
@ -16682,7 +16686,7 @@ msgid "Options to customize the ebook viewer"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/config.py:30
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1106
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1107
msgid "Remember last used window size"
msgstr ""
@ -17273,39 +17277,39 @@ msgstr ""
msgid "Loading ebook..."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:977
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:978
msgid "Could not open ebook"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:978
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:979
msgid "Unknown error"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1093
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1094
msgid "Options to control the ebook viewer"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1100
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1101
msgid ""
"If specified, viewer window will try to come to the front when started."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1103
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1104
msgid ""
"If specified, viewer window will try to open full screen when started."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1108
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1109
msgid "Print javascript alert and console messages to the console"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1110
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1111
msgid ""
"The position at which to open the specified book. The position is a location "
"as displayed in the top left corner of the viewer."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1117
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1118
msgid ""
"%prog [options] file\n"
"\n"
@ -18909,17 +18913,17 @@ msgstr ""
msgid "creating custom column "
msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3669
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3670
#, python-format
msgid "<p>Migrating old database to ebook library in %s<br><center>"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3698
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3699
#, python-format
msgid "Copying <b>%s</b>"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3715
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3716
msgid "Compacting database"
msgstr ""

View File

@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: calibre 0.4.51\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-10-24 04:12+0000\n"
"POT-Creation-Date: 2012-10-26 05:12+0000\n"
"PO-Revision-Date: 2012-10-24 13:23+0000\n"
"Last-Translator: Nelly Hoang <Unknown>\n"
"Language-Team: bg\n"
@ -14,8 +14,8 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Launchpad-Export-Date: 2012-10-25 05:15+0000\n"
"X-Generator: Launchpad (build 16179)\n"
"X-Launchpad-Export-Date: 2012-10-27 04:40+0000\n"
"X-Generator: Launchpad (build 16194)\n"
"Generated-By: pygettext.py 1.5\n"
#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:56
@ -175,12 +175,12 @@ msgstr "Не прави абсолютно нищо"
#: /home/kovid/work/calibre/src/calibre/library/database2.py:586
#: /home/kovid/work/calibre/src/calibre/library/database2.py:594
#: /home/kovid/work/calibre/src/calibre/library/database2.py:605
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2273
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2427
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2857
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3504
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3506
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3643
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2274
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2428
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2858
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3505
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3507
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3644
#: /home/kovid/work/calibre/src/calibre/library/server/content.py:250
#: /home/kovid/work/calibre/src/calibre/library/server/content.py:251
#: /home/kovid/work/calibre/src/calibre/library/server/mobile.py:247
@ -993,26 +993,26 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/book/base.py:666
#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:67
#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:668
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1061
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1062
#: /home/kovid/work/calibre/src/calibre/utils/formatter_functions.py:887
#: /home/kovid/work/calibre/src/calibre/utils/formatter_functions.py:910
msgid "Yes"
msgstr "Да"
#: /home/kovid/work/calibre/src/calibre/db/fields.py:163
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1216
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1217
msgid "Main"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/db/fields.py:165
#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:77
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1218
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1219
msgid "Card A"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/db/fields.py:167
#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:79
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1220
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1221
msgid "Card B"
msgstr ""
@ -1217,14 +1217,14 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:1199
#: /home/kovid/work/calibre/src/calibre/library/database2.py:371
#: /home/kovid/work/calibre/src/calibre/library/database2.py:384
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3361
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3362
#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:187
msgid "News"
msgstr "Новини"
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:2770
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3317
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3335
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3318
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3336
msgid "Catalog"
msgstr "Каталог"
@ -1272,10 +1272,10 @@ msgstr "Bambook"
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:128
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:131
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:348
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1307
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1311
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1315
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1635
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1319
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1323
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1642
#: /home/kovid/work/calibre/src/calibre/devices/prst1/driver.py:155
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:144
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:147
@ -12150,6 +12150,10 @@ msgstr ""
msgid "Choose &font family"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/font_family_chooser.py:196
msgid "Clear the font family"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/init.py:108
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:296
msgid "Cover Browser"
@ -13443,7 +13447,7 @@ msgstr ""
msgid ""
"If set, this option will causes calibre to check if a file\n"
" being auto-added is already in the calibre library.\n"
" If it is, a meesage will pop up asking you whether\n"
" If it is, a message will pop up asking you whether\n"
" you want to add it anyway."
msgstr ""
@ -16796,7 +16800,7 @@ msgid "Options to customize the ebook viewer"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/config.py:30
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1106
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1107
msgid "Remember last used window size"
msgstr ""
@ -17387,39 +17391,39 @@ msgstr ""
msgid "Loading ebook..."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:977
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:978
msgid "Could not open ebook"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:978
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:979
msgid "Unknown error"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1093
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1094
msgid "Options to control the ebook viewer"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1100
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1101
msgid ""
"If specified, viewer window will try to come to the front when started."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1103
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1104
msgid ""
"If specified, viewer window will try to open full screen when started."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1108
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1109
msgid "Print javascript alert and console messages to the console"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1110
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1111
msgid ""
"The position at which to open the specified book. The position is a location "
"as displayed in the top left corner of the viewer."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1117
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1118
msgid ""
"%prog [options] file\n"
"\n"
@ -19023,17 +19027,17 @@ msgstr ""
msgid "creating custom column "
msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3669
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3670
#, python-format
msgid "<p>Migrating old database to ebook library in %s<br><center>"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3698
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3699
#, python-format
msgid "Copying <b>%s</b>"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3715
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3716
msgid "Compacting database"
msgstr ""

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: calibre\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-10-24 04:12+0000\n"
"POT-Creation-Date: 2012-10-26 05:12+0000\n"
"PO-Revision-Date: 2012-04-12 14:19+0000\n"
"Last-Translator: Kazi Shahnoor Ashraf <kazidxb@gmail.com>\n"
"Language-Team: Bengali <bn@li.org>\n"
@ -15,8 +15,8 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Launchpad-Export-Date: 2012-10-25 05:15+0000\n"
"X-Generator: Launchpad (build 16179)\n"
"X-Launchpad-Export-Date: 2012-10-27 04:39+0000\n"
"X-Generator: Launchpad (build 16194)\n"
#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:56
msgid "Does absolutely nothing"
@ -175,12 +175,12 @@ msgstr "আসলে কিছুই করে না"
#: /home/kovid/work/calibre/src/calibre/library/database2.py:586
#: /home/kovid/work/calibre/src/calibre/library/database2.py:594
#: /home/kovid/work/calibre/src/calibre/library/database2.py:605
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2273
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2427
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2857
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3504
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3506
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3643
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2274
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2428
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2858
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3505
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3507
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3644
#: /home/kovid/work/calibre/src/calibre/library/server/content.py:250
#: /home/kovid/work/calibre/src/calibre/library/server/content.py:251
#: /home/kovid/work/calibre/src/calibre/library/server/mobile.py:247
@ -929,26 +929,26 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/book/base.py:666
#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:67
#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:668
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1061
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1062
#: /home/kovid/work/calibre/src/calibre/utils/formatter_functions.py:887
#: /home/kovid/work/calibre/src/calibre/utils/formatter_functions.py:910
msgid "Yes"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/db/fields.py:163
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1216
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1217
msgid "Main"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/db/fields.py:165
#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:77
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1218
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1219
msgid "Card A"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/db/fields.py:167
#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:79
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1220
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1221
msgid "Card B"
msgstr ""
@ -1123,14 +1123,14 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:1199
#: /home/kovid/work/calibre/src/calibre/library/database2.py:371
#: /home/kovid/work/calibre/src/calibre/library/database2.py:384
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3361
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3362
#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:187
msgid "News"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:2770
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3317
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3335
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3318
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3336
msgid "Catalog"
msgstr ""
@ -1178,10 +1178,10 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:128
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:131
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:348
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1307
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1311
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1315
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1635
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1319
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1323
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1642
#: /home/kovid/work/calibre/src/calibre/devices/prst1/driver.py:155
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:144
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:147
@ -12038,6 +12038,10 @@ msgstr ""
msgid "Choose &font family"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/font_family_chooser.py:196
msgid "Clear the font family"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/init.py:108
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:296
msgid "Cover Browser"
@ -13331,7 +13335,7 @@ msgstr ""
msgid ""
"If set, this option will causes calibre to check if a file\n"
" being auto-added is already in the calibre library.\n"
" If it is, a meesage will pop up asking you whether\n"
" If it is, a message will pop up asking you whether\n"
" you want to add it anyway."
msgstr ""
@ -16682,7 +16686,7 @@ msgid "Options to customize the ebook viewer"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/config.py:30
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1106
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1107
msgid "Remember last used window size"
msgstr ""
@ -17273,39 +17277,39 @@ msgstr ""
msgid "Loading ebook..."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:977
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:978
msgid "Could not open ebook"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:978
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:979
msgid "Unknown error"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1093
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1094
msgid "Options to control the ebook viewer"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1100
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1101
msgid ""
"If specified, viewer window will try to come to the front when started."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1103
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1104
msgid ""
"If specified, viewer window will try to open full screen when started."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1108
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1109
msgid "Print javascript alert and console messages to the console"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1110
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1111
msgid ""
"The position at which to open the specified book. The position is a location "
"as displayed in the top left corner of the viewer."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1117
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1118
msgid ""
"%prog [options] file\n"
"\n"
@ -18909,17 +18913,17 @@ msgstr ""
msgid "creating custom column "
msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3669
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3670
#, python-format
msgid "<p>Migrating old database to ebook library in %s<br><center>"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3698
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3699
#, python-format
msgid "Copying <b>%s</b>"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3715
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3716
msgid "Compacting database"
msgstr ""

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: calibre\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-10-24 04:12+0000\n"
"POT-Creation-Date: 2012-10-26 05:12+0000\n"
"PO-Revision-Date: 2011-08-13 04:22+0000\n"
"Last-Translator: Denis <Unknown>\n"
"Language-Team: Breton <br@li.org>\n"
@ -15,8 +15,8 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Launchpad-Export-Date: 2012-10-25 05:15+0000\n"
"X-Generator: Launchpad (build 16179)\n"
"X-Launchpad-Export-Date: 2012-10-27 04:39+0000\n"
"X-Generator: Launchpad (build 16194)\n"
#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:56
msgid "Does absolutely nothing"
@ -175,12 +175,12 @@ msgstr "Ne ra netra da vat"
#: /home/kovid/work/calibre/src/calibre/library/database2.py:586
#: /home/kovid/work/calibre/src/calibre/library/database2.py:594
#: /home/kovid/work/calibre/src/calibre/library/database2.py:605
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2273
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2427
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2857
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3504
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3506
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3643
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2274
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2428
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2858
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3505
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3507
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3644
#: /home/kovid/work/calibre/src/calibre/library/server/content.py:250
#: /home/kovid/work/calibre/src/calibre/library/server/content.py:251
#: /home/kovid/work/calibre/src/calibre/library/server/mobile.py:247
@ -932,26 +932,26 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/book/base.py:666
#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:67
#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:668
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1061
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1062
#: /home/kovid/work/calibre/src/calibre/utils/formatter_functions.py:887
#: /home/kovid/work/calibre/src/calibre/utils/formatter_functions.py:910
msgid "Yes"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/db/fields.py:163
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1216
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1217
msgid "Main"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/db/fields.py:165
#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:77
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1218
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1219
msgid "Card A"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/db/fields.py:167
#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:79
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1220
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1221
msgid "Card B"
msgstr ""
@ -1126,14 +1126,14 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:1199
#: /home/kovid/work/calibre/src/calibre/library/database2.py:371
#: /home/kovid/work/calibre/src/calibre/library/database2.py:384
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3361
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3362
#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:187
msgid "News"
msgstr "Keleier"
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:2770
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3317
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3335
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3318
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3336
msgid "Catalog"
msgstr "Katalog"
@ -1181,10 +1181,10 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:128
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:131
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:348
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1307
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1311
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1315
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1635
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1319
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1323
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1642
#: /home/kovid/work/calibre/src/calibre/devices/prst1/driver.py:155
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:144
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:147
@ -12044,6 +12044,10 @@ msgstr ""
msgid "Choose &font family"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/font_family_chooser.py:196
msgid "Clear the font family"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/init.py:108
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:296
msgid "Cover Browser"
@ -13337,7 +13341,7 @@ msgstr ""
msgid ""
"If set, this option will causes calibre to check if a file\n"
" being auto-added is already in the calibre library.\n"
" If it is, a meesage will pop up asking you whether\n"
" If it is, a message will pop up asking you whether\n"
" you want to add it anyway."
msgstr ""
@ -16688,7 +16692,7 @@ msgid "Options to customize the ebook viewer"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/config.py:30
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1106
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1107
msgid "Remember last used window size"
msgstr ""
@ -17279,39 +17283,39 @@ msgstr ""
msgid "Loading ebook..."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:977
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:978
msgid "Could not open ebook"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:978
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:979
msgid "Unknown error"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1093
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1094
msgid "Options to control the ebook viewer"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1100
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1101
msgid ""
"If specified, viewer window will try to come to the front when started."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1103
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1104
msgid ""
"If specified, viewer window will try to open full screen when started."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1108
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1109
msgid "Print javascript alert and console messages to the console"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1110
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1111
msgid ""
"The position at which to open the specified book. The position is a location "
"as displayed in the top left corner of the viewer."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1117
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1118
msgid ""
"%prog [options] file\n"
"\n"
@ -18915,17 +18919,17 @@ msgstr ""
msgid "creating custom column "
msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3669
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3670
#, python-format
msgid "<p>Migrating old database to ebook library in %s<br><center>"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3698
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3699
#, python-format
msgid "Copying <b>%s</b>"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3715
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3716
msgid "Compacting database"
msgstr ""

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: calibre\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-10-24 04:12+0000\n"
"POT-Creation-Date: 2012-10-26 05:12+0000\n"
"PO-Revision-Date: 2012-01-02 13:31+0000\n"
"Last-Translator: Kenan Dervišević <kenan3008@gmail.com>\n"
"Language-Team: Bosnian <bs@li.org>\n"
@ -16,8 +16,8 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Launchpad-Export-Date: 2012-10-25 05:15+0000\n"
"X-Generator: Launchpad (build 16179)\n"
"X-Launchpad-Export-Date: 2012-10-27 04:39+0000\n"
"X-Generator: Launchpad (build 16194)\n"
#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:56
msgid "Does absolutely nothing"
@ -176,12 +176,12 @@ msgstr "Ne radi apsolutno ništa"
#: /home/kovid/work/calibre/src/calibre/library/database2.py:586
#: /home/kovid/work/calibre/src/calibre/library/database2.py:594
#: /home/kovid/work/calibre/src/calibre/library/database2.py:605
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2273
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2427
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2857
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3504
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3506
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3643
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2274
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2428
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2858
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3505
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3507
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3644
#: /home/kovid/work/calibre/src/calibre/library/server/content.py:250
#: /home/kovid/work/calibre/src/calibre/library/server/content.py:251
#: /home/kovid/work/calibre/src/calibre/library/server/mobile.py:247
@ -935,26 +935,26 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/book/base.py:666
#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:67
#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:668
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1061
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1062
#: /home/kovid/work/calibre/src/calibre/utils/formatter_functions.py:887
#: /home/kovid/work/calibre/src/calibre/utils/formatter_functions.py:910
msgid "Yes"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/db/fields.py:163
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1216
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1217
msgid "Main"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/db/fields.py:165
#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:77
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1218
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1219
msgid "Card A"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/db/fields.py:167
#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:79
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1220
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1221
msgid "Card B"
msgstr ""
@ -1129,14 +1129,14 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:1199
#: /home/kovid/work/calibre/src/calibre/library/database2.py:371
#: /home/kovid/work/calibre/src/calibre/library/database2.py:384
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3361
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3362
#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:187
msgid "News"
msgstr "Vijesti"
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:2770
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3317
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3335
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3318
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3336
msgid "Catalog"
msgstr "Katalog"
@ -1184,10 +1184,10 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:128
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:131
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:348
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1307
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1311
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1315
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1635
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1319
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1323
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1642
#: /home/kovid/work/calibre/src/calibre/devices/prst1/driver.py:155
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:144
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:147
@ -12045,6 +12045,10 @@ msgstr ""
msgid "Choose &font family"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/font_family_chooser.py:196
msgid "Clear the font family"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/init.py:108
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:296
msgid "Cover Browser"
@ -13338,7 +13342,7 @@ msgstr ""
msgid ""
"If set, this option will causes calibre to check if a file\n"
" being auto-added is already in the calibre library.\n"
" If it is, a meesage will pop up asking you whether\n"
" If it is, a message will pop up asking you whether\n"
" you want to add it anyway."
msgstr ""
@ -16693,7 +16697,7 @@ msgid "Options to customize the ebook viewer"
msgstr "Opcije za prilagođavanje preglednika e-knjiga"
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/config.py:30
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1106
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1107
msgid "Remember last used window size"
msgstr "Zapamti zadnju korištenu veličinu prozora"
@ -17284,39 +17288,39 @@ msgstr "Upravljanje zabilješkama"
msgid "Loading ebook..."
msgstr "Učitavam e-knjigu..."
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:977
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:978
msgid "Could not open ebook"
msgstr "Nije moguće otvoriti e-knjigu"
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:978
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:979
msgid "Unknown error"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1093
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1094
msgid "Options to control the ebook viewer"
msgstr "Opcije pomoću kojih se kontroliše preglednik e-knjiga"
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1100
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1101
msgid ""
"If specified, viewer window will try to come to the front when started."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1103
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1104
msgid ""
"If specified, viewer window will try to open full screen when started."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1108
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1109
msgid "Print javascript alert and console messages to the console"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1110
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1111
msgid ""
"The position at which to open the specified book. The position is a location "
"as displayed in the top left corner of the viewer."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1117
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1118
msgid ""
"%prog [options] file\n"
"\n"
@ -18920,17 +18924,17 @@ msgstr ""
msgid "creating custom column "
msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3669
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3670
#, python-format
msgid "<p>Migrating old database to ebook library in %s<br><center>"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3698
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3699
#, python-format
msgid "Copying <b>%s</b>"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3715
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3716
msgid "Compacting database"
msgstr ""

View File

@ -10,16 +10,16 @@ msgid ""
msgstr ""
"Project-Id-Version: ca\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-10-24 04:12+0000\n"
"PO-Revision-Date: 2012-10-21 14:25+0000\n"
"POT-Creation-Date: 2012-10-26 05:12+0000\n"
"PO-Revision-Date: 2012-10-27 12:43+0000\n"
"Last-Translator: Ferran Rius <frius64@hotmail.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Launchpad-Export-Date: 2012-10-25 05:16+0000\n"
"X-Generator: Launchpad (build 16179)\n"
"X-Launchpad-Export-Date: 2012-10-28 04:40+0000\n"
"X-Generator: Launchpad (build 16194)\n"
#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:56
msgid "Does absolutely nothing"
@ -178,12 +178,12 @@ msgstr "No fa res"
#: /home/kovid/work/calibre/src/calibre/library/database2.py:586
#: /home/kovid/work/calibre/src/calibre/library/database2.py:594
#: /home/kovid/work/calibre/src/calibre/library/database2.py:605
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2273
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2427
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2857
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3504
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3506
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3643
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2274
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2428
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2858
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3505
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3507
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3644
#: /home/kovid/work/calibre/src/calibre/library/server/content.py:250
#: /home/kovid/work/calibre/src/calibre/library/server/content.py:251
#: /home/kovid/work/calibre/src/calibre/library/server/mobile.py:247
@ -1000,26 +1000,26 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/book/base.py:666
#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:67
#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:668
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1061
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1062
#: /home/kovid/work/calibre/src/calibre/utils/formatter_functions.py:887
#: /home/kovid/work/calibre/src/calibre/utils/formatter_functions.py:910
msgid "Yes"
msgstr "Sí"
#: /home/kovid/work/calibre/src/calibre/db/fields.py:163
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1216
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1217
msgid "Main"
msgstr "Inici"
#: /home/kovid/work/calibre/src/calibre/db/fields.py:165
#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:77
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1218
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1219
msgid "Card A"
msgstr "Targeta A"
#: /home/kovid/work/calibre/src/calibre/db/fields.py:167
#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:79
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1220
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1221
msgid "Card B"
msgstr "Targeta B"
@ -1238,14 +1238,14 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:1199
#: /home/kovid/work/calibre/src/calibre/library/database2.py:371
#: /home/kovid/work/calibre/src/calibre/library/database2.py:384
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3361
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3362
#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:187
msgid "News"
msgstr "Notícies"
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:2770
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3317
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3335
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3318
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3336
msgid "Catalog"
msgstr "Catàleg"
@ -1301,10 +1301,10 @@ msgstr "Bambook"
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:128
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:131
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:348
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1307
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1311
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1315
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1635
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1319
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1323
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1642
#: /home/kovid/work/calibre/src/calibre/devices/prst1/driver.py:155
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:144
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:147
@ -3788,6 +3788,12 @@ msgid ""
"to remove fonts from the input document. Note that font embedding only works "
"with some output formats, principally EPUB and AZW3."
msgstr ""
"Incrusta la família de tipus de lletra al llibre. Especifica la lletra "
"«base» que s'utilitza per al llibre. Si el document d'entrada especifica els "
"seus tipus de lletra pot substituir aquesta lletra base. Podeu utilitzar "
"l'opció de la informació del filtre d'estils per suprimir tipus de lletra "
"del document d'entrada. Tingueu en compte que la incrustació de lletra només "
"funciona amb alguns formats de sortida, principalment EPUB i AZW3."
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:209
msgid ""
@ -8711,7 +8717,7 @@ msgstr "Alçada de la &línia:"
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:237
msgid "&Embed font family:"
msgstr ""
msgstr "&Incrusta els tipus de lletra"
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:238
msgid "&Disable font size rescaling"
@ -9142,6 +9148,7 @@ msgstr "Obre un llibre"
#: /home/kovid/work/calibre/src/calibre/gui2/convert/regex_builder.py:215
msgid "Click the Open button below to open a ebook to use for testing."
msgstr ""
"Feu clic al botó «Obre» per obrir un llibre per utilitzar-lo com a proba."
#: /home/kovid/work/calibre/src/calibre/gui2/convert/regex_builder_ui.py:90
msgid "Regex Builder"
@ -13563,7 +13570,7 @@ msgstr "Expressió regular (?P<published>)"
#: /home/kovid/work/calibre/src/calibre/gui2/font_family_chooser.py:122
msgid "Choose font family"
msgstr ""
msgstr "Tria el tipus de lletra"
#: /home/kovid/work/calibre/src/calibre/gui2/font_family_chooser.py:137
#: /home/kovid/work/calibre/src/calibre/gui2/keyboard.py:377
@ -13583,11 +13590,15 @@ msgstr "Cap"
#: /home/kovid/work/calibre/src/calibre/gui2/font_family_chooser.py:159
msgid "Choose a font family from the list below:"
msgstr ""
msgstr "Trieu un tipus de lletra la la llista següent:"
#: /home/kovid/work/calibre/src/calibre/gui2/font_family_chooser.py:187
msgid "Choose &font family"
msgstr ""
msgstr "Tria el &tipus de lletra"
#: /home/kovid/work/calibre/src/calibre/gui2/font_family_chooser.py:196
msgid "Clear the font family"
msgstr "Elimina el tipus de lletra"
#: /home/kovid/work/calibre/src/calibre/gui2/init.py:108
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:296
@ -14307,7 +14318,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/basic_widgets.py:273
#, python-format
msgid "Could not open \"%s\". Is it being used by another program?"
msgstr ""
msgstr "No s'ha pogut obrir «%s». L'està utilitzant un altre programa?"
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/basic_widgets.py:306
msgid ""
@ -15013,13 +15024,13 @@ msgstr "Procés d'addició"
msgid ""
"If set, this option will causes calibre to check if a file\n"
" being auto-added is already in the calibre library.\n"
" If it is, a meesage will pop up asking you whether\n"
" If it is, a message will pop up asking you whether\n"
" you want to add it anyway."
msgstr ""
"Si s'activa, aquesta opció fa que el calibre comprovi si un\n"
" fitxer que s'està afegint automàticament ja està a la\n"
" biblioteca del calibre. Si és així un missatge emergent\n"
" us demanarà si el voleu afegir igualment."
"Si s'estableix fa que el calibre comprovi si un fitxer\n"
" que s'està afegint automàticament ja està a la biblioteca.\n"
" Si hi és, un missatge emergent us pregunarà si voleu\n"
" afegir-lo igualment."
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/adding_ui.py:152
msgid "Check for &duplicates when auto-adding files"
@ -18896,7 +18907,7 @@ msgid "Options to customize the ebook viewer"
msgstr "Opcions per personalitzar el visor de llibres electrònics"
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/config.py:30
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1106
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1107
msgid "Remember last used window size"
msgstr "Recorda la darrera mida de finestra que s'ha fet servir"
@ -19525,38 +19536,38 @@ msgstr "Gestiona els marcadors"
msgid "Loading ebook..."
msgstr "S'està carregant el llibre..."
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:977
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:978
msgid "Could not open ebook"
msgstr "No s'ha pogut obrir el llibre"
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:978
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:979
msgid "Unknown error"
msgstr "Error desconegut"
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1093
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1094
msgid "Options to control the ebook viewer"
msgstr "Opcions de control del visor de llibres"
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1100
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1101
msgid ""
"If specified, viewer window will try to come to the front when started."
msgstr ""
"Si s'indica, la finestra del visor intentarà anar al primer pla quan "
"s'iniciï."
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1103
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1104
msgid ""
"If specified, viewer window will try to open full screen when started."
msgstr ""
"Si s'indica, s'intentarà que la finestra del visor s'obri en pantalla "
"completa."
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1108
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1109
msgid "Print javascript alert and console messages to the console"
msgstr ""
"Dirigeix les alertes de javascript i els missatges de consola a la consola"
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1110
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1111
msgid ""
"The position at which to open the specified book. The position is a location "
"as displayed in the top left corner of the viewer."
@ -19564,7 +19575,7 @@ msgstr ""
"La posició que s'obrirà el llibre especificat. La posició és una ubicació "
"que es mostra a la cantonada superior esquerra del visor."
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1117
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1118
msgid ""
"%prog [options] file\n"
"\n"
@ -21160,6 +21171,23 @@ msgid ""
"that a new OPF has been createdsince the column was added). You will see the "
"JSON for the\"display\" for the new column in the OPF."
msgstr ""
"Un diccionari d'opcions per personalitzar com s'interpretaran les dades de "
"la columna. És una cadena JSON. Per a columnes d'enumeració utilitzeu --"
"display=\"{\\\"enum_values\\\":[\\\"val1\\\", \\\"val2\\\"]}\"\n"
"Hi ha moltes opcions que poden estar amb la variable «display». Les opcions "
"per tipus de columna són:\n"
"composite: composite_template, composite_sort, make_category,contains_html, "
"use_decorations\n"
"datetime: date_format\n"
"enumeration: enum_values, enum_colors, use_decorations\n"
"int, float: number_format\n"
"text: is_names, use_decorations\n"
"\n"
"La millor manera de trobar combinacions vàlides és crear una columna "
"personalitzada del tipus adequat a la interfície gràfica i mirar la còpia de "
"seguretat OPF per a un llibre (assegureu-vos que es crea un nou OPF després "
"de crear la columna). Veureu la cadena JSON per a «display» de la nova "
"columna al fitxer OPF."
#: /home/kovid/work/calibre/src/calibre/library/cli.py:721
msgid "You must specify label, name and datatype"
@ -21572,18 +21600,18 @@ msgstr "s'ha restaurat la preferència "
msgid "creating custom column "
msgstr "s'està creant una columna personalitzada "
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3669
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3670
#, python-format
msgid "<p>Migrating old database to ebook library in %s<br><center>"
msgstr ""
"<p>S'està migrant la base de dades antiga a la biblioteca de %s<br><center>"
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3698
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3699
#, python-format
msgid "Copying <b>%s</b>"
msgstr "S'està copiant <b>%s</b>"
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3715
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3716
msgid "Compacting database"
msgstr "S'està compactant la base de dades"
@ -22231,7 +22259,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/utils/filenames.py:284
msgid "File is open in another process"
msgstr ""
msgstr "El fitxer està obert en un altre procés"
#: /home/kovid/work/calibre/src/calibre/utils/formatter.py:31
#: /home/kovid/work/calibre/src/calibre/utils/formatter.py:182

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: calibre\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-10-24 04:12+0000\n"
"POT-Creation-Date: 2012-10-26 05:12+0000\n"
"PO-Revision-Date: 2012-07-31 12:00+0000\n"
"Last-Translator: Štěpán Krb <stepan.krb@gmail.com>\n"
"Language-Team: Czech <cs@li.org>\n"
@ -15,8 +15,8 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
"X-Launchpad-Export-Date: 2012-10-25 05:16+0000\n"
"X-Generator: Launchpad (build 16179)\n"
"X-Launchpad-Export-Date: 2012-10-27 04:40+0000\n"
"X-Generator: Launchpad (build 16194)\n"
#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:56
msgid "Does absolutely nothing"
@ -175,12 +175,12 @@ msgstr "Nedělá vůbec nic"
#: /home/kovid/work/calibre/src/calibre/library/database2.py:586
#: /home/kovid/work/calibre/src/calibre/library/database2.py:594
#: /home/kovid/work/calibre/src/calibre/library/database2.py:605
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2273
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2427
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2857
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3504
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3506
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3643
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2274
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2428
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2858
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3505
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3507
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3644
#: /home/kovid/work/calibre/src/calibre/library/server/content.py:250
#: /home/kovid/work/calibre/src/calibre/library/server/content.py:251
#: /home/kovid/work/calibre/src/calibre/library/server/mobile.py:247
@ -974,26 +974,26 @@ msgstr "Cesta ke složce knihovny je moc dlouhá. Musí mít méně než %d znak
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/book/base.py:666
#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:67
#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:668
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1061
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1062
#: /home/kovid/work/calibre/src/calibre/utils/formatter_functions.py:887
#: /home/kovid/work/calibre/src/calibre/utils/formatter_functions.py:910
msgid "Yes"
msgstr "Ano"
#: /home/kovid/work/calibre/src/calibre/db/fields.py:163
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1216
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1217
msgid "Main"
msgstr "Hlavní"
#: /home/kovid/work/calibre/src/calibre/db/fields.py:165
#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:77
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1218
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1219
msgid "Card A"
msgstr "Karta A"
#: /home/kovid/work/calibre/src/calibre/db/fields.py:167
#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:79
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1220
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1221
msgid "Card B"
msgstr "Karta B"
@ -1195,14 +1195,14 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:1199
#: /home/kovid/work/calibre/src/calibre/library/database2.py:371
#: /home/kovid/work/calibre/src/calibre/library/database2.py:384
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3361
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3362
#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:187
msgid "News"
msgstr "Zprávy"
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:2770
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3317
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3335
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3318
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3336
msgid "Catalog"
msgstr "Katalog"
@ -1257,10 +1257,10 @@ msgstr "Bambook"
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:128
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:131
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:348
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1307
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1311
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1315
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1635
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1319
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1323
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1642
#: /home/kovid/work/calibre/src/calibre/devices/prst1/driver.py:155
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:144
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:147
@ -12824,6 +12824,10 @@ msgstr ""
msgid "Choose &font family"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/font_family_chooser.py:196
msgid "Clear the font family"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/init.py:108
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:296
msgid "Cover Browser"
@ -14142,7 +14146,7 @@ msgstr ""
msgid ""
"If set, this option will causes calibre to check if a file\n"
" being auto-added is already in the calibre library.\n"
" If it is, a meesage will pop up asking you whether\n"
" If it is, a message will pop up asking you whether\n"
" you want to add it anyway."
msgstr ""
@ -17560,7 +17564,7 @@ msgid "Options to customize the ebook viewer"
msgstr "Možnosti úpravy prohlížeče elektronických knih"
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/config.py:30
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1106
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1107
msgid "Remember last used window size"
msgstr "Zapamatuj si posledně použitou velikost okna"
@ -18162,41 +18166,41 @@ msgstr "Spravovat záložky"
msgid "Loading ebook..."
msgstr "Načítám knihu..."
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:977
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:978
msgid "Could not open ebook"
msgstr "Nemohu otevřít eknihu"
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:978
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:979
msgid "Unknown error"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1093
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1094
msgid "Options to control the ebook viewer"
msgstr "Volby ke kontrole prohlížeče ebooků"
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1100
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1101
msgid ""
"If specified, viewer window will try to come to the front when started."
msgstr "Pokud specifikováno, okno prohlížeče se zobrazí po startu v popředí."
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1103
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1104
msgid ""
"If specified, viewer window will try to open full screen when started."
msgstr ""
"Pokud je zadáno, pokusí se při spuštění otevřít okno prohlížeče na celou "
"obrazovku."
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1108
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1109
msgid "Print javascript alert and console messages to the console"
msgstr "Tisknout upozornění javascriptu a konzolové zprávy do konzole"
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1110
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1111
msgid ""
"The position at which to open the specified book. The position is a location "
"as displayed in the top left corner of the viewer."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1117
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1118
msgid ""
"%prog [options] file\n"
"\n"
@ -19914,17 +19918,17 @@ msgstr ""
msgid "creating custom column "
msgstr "vytváření uživatelských sloupců "
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3669
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3670
#, python-format
msgid "<p>Migrating old database to ebook library in %s<br><center>"
msgstr "<p>Migruji starou databázi do knihovy ebooků v %s<br><center>"
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3698
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3699
#, python-format
msgid "Copying <b>%s</b>"
msgstr "Kopírování <b>%s</b>"
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3715
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3716
msgid "Compacting database"
msgstr "Zhutňování databáze"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: calibre\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-10-24 04:12+0000\n"
"POT-Creation-Date: 2012-10-26 05:12+0000\n"
"PO-Revision-Date: 2012-02-26 20:21+0000\n"
"Last-Translator: Rachael Munns <vashtijoy@gmail.com>\n"
"Language-Team: Welsh <cy@li.org>\n"
@ -16,8 +16,8 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=n==1 ? 0 : n==2 ? 1 : (n != 8 && n != 11) ? "
"2 : 3;\n"
"X-Launchpad-Export-Date: 2012-10-25 05:31+0000\n"
"X-Generator: Launchpad (build 16179)\n"
"X-Launchpad-Export-Date: 2012-10-27 04:55+0000\n"
"X-Generator: Launchpad (build 16194)\n"
#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:56
msgid "Does absolutely nothing"
@ -176,12 +176,12 @@ msgstr "Dim yn gwneud dim byd"
#: /home/kovid/work/calibre/src/calibre/library/database2.py:586
#: /home/kovid/work/calibre/src/calibre/library/database2.py:594
#: /home/kovid/work/calibre/src/calibre/library/database2.py:605
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2273
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2427
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2857
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3504
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3506
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3643
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2274
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2428
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2858
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3505
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3507
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3644
#: /home/kovid/work/calibre/src/calibre/library/server/content.py:250
#: /home/kovid/work/calibre/src/calibre/library/server/content.py:251
#: /home/kovid/work/calibre/src/calibre/library/server/mobile.py:247
@ -940,26 +940,26 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/book/base.py:666
#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:67
#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:668
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1061
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1062
#: /home/kovid/work/calibre/src/calibre/utils/formatter_functions.py:887
#: /home/kovid/work/calibre/src/calibre/utils/formatter_functions.py:910
msgid "Yes"
msgstr "Iawn"
#: /home/kovid/work/calibre/src/calibre/db/fields.py:163
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1216
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1217
msgid "Main"
msgstr "Sail"
#: /home/kovid/work/calibre/src/calibre/db/fields.py:165
#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:77
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1218
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1219
msgid "Card A"
msgstr "Cerdyn A"
#: /home/kovid/work/calibre/src/calibre/db/fields.py:167
#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:79
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1220
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1221
msgid "Card B"
msgstr "Cerdyn B"
@ -1134,14 +1134,14 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:1199
#: /home/kovid/work/calibre/src/calibre/library/database2.py:371
#: /home/kovid/work/calibre/src/calibre/library/database2.py:384
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3361
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3362
#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:187
msgid "News"
msgstr "Newyddion"
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:2770
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3317
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3335
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3318
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3336
msgid "Catalog"
msgstr "Catalog"
@ -1189,10 +1189,10 @@ msgstr "Bambook"
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:128
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:131
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:348
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1307
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1311
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1315
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1635
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1319
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1323
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1642
#: /home/kovid/work/calibre/src/calibre/devices/prst1/driver.py:155
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:144
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:147
@ -12050,6 +12050,10 @@ msgstr ""
msgid "Choose &font family"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/font_family_chooser.py:196
msgid "Clear the font family"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/init.py:108
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:296
msgid "Cover Browser"
@ -13343,7 +13347,7 @@ msgstr ""
msgid ""
"If set, this option will causes calibre to check if a file\n"
" being auto-added is already in the calibre library.\n"
" If it is, a meesage will pop up asking you whether\n"
" If it is, a message will pop up asking you whether\n"
" you want to add it anyway."
msgstr ""
@ -16694,7 +16698,7 @@ msgid "Options to customize the ebook viewer"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/config.py:30
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1106
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1107
msgid "Remember last used window size"
msgstr ""
@ -17285,39 +17289,39 @@ msgstr ""
msgid "Loading ebook..."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:977
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:978
msgid "Could not open ebook"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:978
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:979
msgid "Unknown error"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1093
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1094
msgid "Options to control the ebook viewer"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1100
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1101
msgid ""
"If specified, viewer window will try to come to the front when started."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1103
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1104
msgid ""
"If specified, viewer window will try to open full screen when started."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1108
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1109
msgid "Print javascript alert and console messages to the console"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1110
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1111
msgid ""
"The position at which to open the specified book. The position is a location "
"as displayed in the top left corner of the viewer."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1117
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1118
msgid ""
"%prog [options] file\n"
"\n"
@ -18921,17 +18925,17 @@ msgstr ""
msgid "creating custom column "
msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3669
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3670
#, python-format
msgid "<p>Migrating old database to ebook library in %s<br><center>"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3698
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3699
#, python-format
msgid "Copying <b>%s</b>"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3715
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3716
msgid "Compacting database"
msgstr ""

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: calibre\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-10-24 04:12+0000\n"
"POT-Creation-Date: 2012-10-26 05:12+0000\n"
"PO-Revision-Date: 2012-07-13 17:59+0000\n"
"Last-Translator: Jens Holm <Jens@far-out.dk>\n"
"Language-Team: Danish <da@li.org>\n"
@ -15,8 +15,8 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Launchpad-Export-Date: 2012-10-25 05:16+0000\n"
"X-Generator: Launchpad (build 16179)\n"
"X-Launchpad-Export-Date: 2012-10-27 04:40+0000\n"
"X-Generator: Launchpad (build 16194)\n"
#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:56
msgid "Does absolutely nothing"
@ -175,12 +175,12 @@ msgstr "Gør absolut ingenting"
#: /home/kovid/work/calibre/src/calibre/library/database2.py:586
#: /home/kovid/work/calibre/src/calibre/library/database2.py:594
#: /home/kovid/work/calibre/src/calibre/library/database2.py:605
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2273
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2427
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2857
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3504
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3506
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3643
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2274
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2428
#: /home/kovid/work/calibre/src/calibre/library/database2.py:2858
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3505
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3507
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3644
#: /home/kovid/work/calibre/src/calibre/library/server/content.py:250
#: /home/kovid/work/calibre/src/calibre/library/server/content.py:251
#: /home/kovid/work/calibre/src/calibre/library/server/mobile.py:247
@ -977,26 +977,26 @@ msgstr "Sti til bibliotek for lang. Skal være kortere end %d tegn."
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/book/base.py:666
#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:67
#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:668
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1061
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1062
#: /home/kovid/work/calibre/src/calibre/utils/formatter_functions.py:887
#: /home/kovid/work/calibre/src/calibre/utils/formatter_functions.py:910
msgid "Yes"
msgstr "Ja"
#: /home/kovid/work/calibre/src/calibre/db/fields.py:163
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1216
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1217
msgid "Main"
msgstr "Main/hjem/primær"
#: /home/kovid/work/calibre/src/calibre/db/fields.py:165
#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:77
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1218
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1219
msgid "Card A"
msgstr "Kort A"
#: /home/kovid/work/calibre/src/calibre/db/fields.py:167
#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:79
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1220
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1221
msgid "Card B"
msgstr "Kort B"
@ -1203,14 +1203,14 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:1199
#: /home/kovid/work/calibre/src/calibre/library/database2.py:371
#: /home/kovid/work/calibre/src/calibre/library/database2.py:384
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3361
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3362
#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:187
msgid "News"
msgstr "Nyheder"
#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:2770
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3317
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3335
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3318
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3336
msgid "Catalog"
msgstr "Katalog"
@ -1265,10 +1265,10 @@ msgstr "Bambook"
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:128
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:131
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:348
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1307
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1311
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1315
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1635
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1319
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1323
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:1642
#: /home/kovid/work/calibre/src/calibre/devices/prst1/driver.py:155
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:144
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:147
@ -12584,6 +12584,10 @@ msgstr ""
msgid "Choose &font family"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/font_family_chooser.py:196
msgid "Clear the font family"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/init.py:108
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:296
msgid "Cover Browser"
@ -13900,7 +13904,7 @@ msgstr ""
msgid ""
"If set, this option will causes calibre to check if a file\n"
" being auto-added is already in the calibre library.\n"
" If it is, a meesage will pop up asking you whether\n"
" If it is, a message will pop up asking you whether\n"
" you want to add it anyway."
msgstr ""
@ -17356,7 +17360,7 @@ msgid "Options to customize the ebook viewer"
msgstr "Indstillinger til tilpasning af e-bogsviseren"
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/config.py:30
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1106
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1107
msgid "Remember last used window size"
msgstr "Husk størrelsen på vinduet"
@ -17952,41 +17956,41 @@ msgstr "Administrér bogmærker"
msgid "Loading ebook..."
msgstr "Henter e-bog..."
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:977
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:978
msgid "Could not open ebook"
msgstr "Kunne ikke åbne e-bog"
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:978
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:979
msgid "Unknown error"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1093
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1094
msgid "Options to control the ebook viewer"
msgstr "Valg til at styre e-bogsviser"
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1100
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1101
msgid ""
"If specified, viewer window will try to come to the front when started."
msgstr ""
"Hvis specificeret, vil visningsvindue prøve at komme i front ved start."
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1103
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1104
msgid ""
"If specified, viewer window will try to open full screen when started."
msgstr ""
"Hvis angivet, vil oversigtsvindue prøve at åbne i fuld skærm under start."
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1108
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1109
msgid "Print javascript alert and console messages to the console"
msgstr "Udskriv javascript alert og konsol beskeder til konsolen"
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1110
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1111
msgid ""
"The position at which to open the specified book. The position is a location "
"as displayed in the top left corner of the viewer."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1117
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:1118
msgid ""
"%prog [options] file\n"
"\n"
@ -19805,17 +19809,17 @@ msgstr ""
msgid "creating custom column "
msgstr "opret tilpasset søjle "
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3669
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3670
#, python-format
msgid "<p>Migrating old database to ebook library in %s<br><center>"
msgstr "<p>Flytter gammel database til e-bogsbibliotek i %s<br><center>"
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3698
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3699
#, python-format
msgid "Copying <b>%s</b>"
msgstr "Kopierer <b>%s</b>"
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3715
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3716
msgid "Compacting database"
msgstr "Komprimerer database"

Some files were not shown because too many files have changed in this diff Show More