Merge from trunk

This commit is contained in:
Charles Haley 2010-12-11 12:47:07 +00:00
commit e6e6064532
75 changed files with 234088 additions and 122838 deletions

View File

@ -4,6 +4,81 @@
# for important features/bug fixes.
# Also, each release can have new and improved recipes.
- version: 0.7.33
date: 2010-12-10
new features:
- title: "Language sensitive sorting"
type: major
description: >
"calibre now sorts using language specific rules. The language used is the language of the calibre interface, which can be changed via Preferences->Look & Feel. There is also
a tweak that allows you to use a different language from the one used for the calibre interface. Powered by the ICU library."
- title: "Add an action to merge only formats and leave metadata alone (Shift+Alt+M)"
tickets: [7709]
- title: "Add a tweak to control which custom columns are displayed in the Book details panel."
- title: "Implement a more sophisticated 'functional programming' template language. See the User Manual for details."
- title: "Speed up deleting of large numbers of books and show progress while doing so"
- title: "Adding books: Dont refresh the Tag Browser while adding multiple books. Should speed up the adding of large numbers of books."
- title: "Edit metadata dialog: When trying to download metadata, if there are multiple matches indicate which matches have a cover and summary in the list. Also add an option to automatically download the cover of the selected match."
- title: "Drivers for the HTC Legend and Samsung Epic"
- title: "FB2 Output: Convert SVG images in the input document to raster images"
- title: "News download: Localize the navigation bars in the downloaded news to the language the user has selected for their calibre interface"
bug fixes:
- title: "Various fixes to the Title Case function"
tickets: [7846]
- title: "Content server: Fix --url-prefix being ignored for links at the Top level"
- title: "News download: When generating periodicals for the SONY use the local timezone in the SONY specific metadata"
- title: "Fix bug in cover cache that could cause it to keep a large number of covers in memory. Showed up when adding large numbers of books to calibre."
tickets: [7813]
- title: "Adding books: Run in the main thread to prevent unfortunate interactions with the metadata backup. Also fix regression that broke the Abort button."
- title: "Fix a crash on OS X if OK is clicked inthe edit metadata button while downloading a cover"
tickets: [7716]
- title: "E-book viewer: Fix a regression that prevented booksmarks from working with some EPUB files"
tickets: [7812]
- title: "Save to disk: Refactor to not open a database connection in the worker process. Also fix a bug that could lead to save failures not being reported."
- title: "Fix regression in 0.7.32 that broke opening formats in the ebook viewer from the edit metadata dialog"
- title: "FB2 Output: Generate output 100% compliant with the FB2 spec"
- title: "Fix Saved search dropdown box looses selected search"
tickets: [7787]
- title: "TXT Output: Fix an issue where the br to space conversion was not being handled properly."
improved recipes:
- Le Monde
- Ming Pao
- New Yorker
new recipes:
- title: "ToyoKeizai News and Nikkei Social News"
author: "Hiroshi Miura"
- title: "St. Louis Post Dispatch"
author: "cisaak"
- title: "Heise Open and Technology Review"
author: "Anton Gillert"
- version: 0.7.32
date: 2010-12-03

View File

@ -0,0 +1,38 @@
__license__ = 'GPL v3'
__copyright__ = '2010, Anton Gillert <atx at binaryninja.de>'
'''
Fetch Heise Open.
'''
from calibre.web.feeds.news import BasicNewsRecipe
class HeiseOpenDe(BasicNewsRecipe):
title = 'Heise Open'
description = 'Opensource news from Germany'
__author__ = 'Anton Gillert'
use_embedded_content = False
language = 'de'
timefmt = ' [%d %b %Y]'
max_articles_per_feed = 40
no_stylesheets = True
feeds = [ ('Heise Open', 'http://www.heise.de/open/news/news-atom.xml') ]
def print_version(self, url):
return url + '?view=print'
remove_tags = [dict(id='navi_top'),
dict(id='navi_bottom'),
dict(name='div', attrs={'class':'navi_top_logo'}),
dict(name='img', attrs={'src':'/open/icons/open_logo_2009_weiss.gif'}),
dict(name='h5', attrs={'style':'margin: 0.5em 0;'}),
dict(name='p', attrs={'class':'news_datum'}),
dict(name='p', attrs={'class':'size80'})]
remove_tags_after = [dict(name='p', attrs={'class':'size80'})]
def get_cover_url(self):
return 'http://www.heise.de/open/icons/open_logo_2009_weiss.gif'

View File

@ -64,5 +64,5 @@ class Toyokeizai(BasicNewsRecipe):
br.select_form(nr=0)
br['kaiin_id'] = self.username
br['password'] = self.password
res = br.submit()
br.submit()
return br

View File

@ -0,0 +1,37 @@
__license__ = 'GPL v3'
__copyright__ = '2010, Anton Gillert <atx at binaryninja.de>'
'''
Fetch Technology Review.
'''
from time import strftime
from calibre.web.feeds.news import BasicNewsRecipe
class TechnologyReviewDe(BasicNewsRecipe):
title = 'Technology Review'
description = 'Technology news from Germany'
__author__ = 'Anton Gillert'
use_embedded_content = False
language = 'de'
timefmt = ' [%d %b %Y]'
max_articles_per_feed = 40
no_stylesheets = True
feeds = [ ('Technology Review', 'http://www.heise.de/tr/news-atom.xml') ]
def print_version(self, url):
return url + '?view=print'
remove_tags = [dict(id='navi_top'),
dict(id='navi_bottom'),
dict(name='div', attrs={'class':'navi_top_logo'}),
dict(name='img', attrs={'src':'/tr/icons/tr_logo2006.gif'}),
dict(name='p', attrs={'class':'size80'})]
remove_tags_after = [dict(name='p', attrs={'class':'size80'})]
def get_cover_url(self):
return 'http://www.heise-medien.de/presseinfo/bilder/tr/' + strftime("%y/tr%m%Y.jpg")

View File

@ -2,7 +2,7 @@ __license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
__docformat__ = 'restructuredtext en'
__appname__ = 'calibre'
__version__ = '0.7.32'
__version__ = '0.7.33'
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
import re

View File

@ -240,7 +240,7 @@ class CollectionsBookList(BookList):
return 1
if y is None:
return -1
if isinstance(x, (unicode, str)):
if isinstance(x, basestring) and isinstance(y, basestring):
c = strcmp(force_unicode(x), force_unicode(y))
else:
c = cmp(x, y)

View File

@ -6,6 +6,7 @@ __copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
from uuid import uuid4
import time
from calibre.constants import __appname__, __version__
from calibre import strftime, prepare_string_for_xml as xml
@ -103,7 +104,7 @@ def sony_metadata(oeb):
publisher=xml(publisher), issue_date=xml(date),
language=xml(language))
updated = strftime('%Y-%m-%dT%H:%M:%SZ')
updated = strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())
def cal_id(x):
for k, v in x.attrib.items():

View File

@ -54,6 +54,10 @@ class EditMetadataAction(InterfaceAction):
mb.addAction(_('Merge into first selected book - keep others'),
partial(self.merge_books, safe_merge=True),
Qt.AltModifier+Qt.Key_M)
mb.addSeparator()
mb.addAction(_('Merge only formats into first selected book - delete others'),
partial(self.merge_books, merge_only_formats=True),
Qt.AltModifier+Qt.ShiftModifier+Qt.Key_M)
self.merge_menu = mb
self.action_merge.setMenu(mb)
md.addSeparator()
@ -206,7 +210,7 @@ class EditMetadataAction(InterfaceAction):
self.gui.library_view.select_rows(ids)
# Merge books {{{
def merge_books(self, safe_merge=False):
def merge_books(self, safe_merge=False, merge_only_formats=False):
'''
Merge selected books in library.
'''
@ -220,6 +224,12 @@ class EditMetadataAction(InterfaceAction):
return error_dialog(self.gui, _('Cannot merge books'),
_('At least two books must be selected for merging'),
show=True)
if len(rows) > 5:
if not confirm('<p>'+_('You are about to merge more than 5 books. '
'Are you <b>sure</b> you want to proceed?')
+'</p>', 'merge_too_many_books', self.gui):
return
dest_id, src_books, src_ids = self.books_to_merge(rows)
title = self.gui.library_view.model().db.title(dest_id, index_is_id=True)
if safe_merge:
@ -234,6 +244,22 @@ class EditMetadataAction(InterfaceAction):
return
self.add_formats(dest_id, src_books)
self.merge_metadata(dest_id, src_ids)
elif merge_only_formats:
if not confirm('<p>'+_(
'Book formats from the selected books will be merged '
'into the <b>first selected book</b> (%s). '
'Metadata in the first selected book will not be changed.'
'Author, Title, ISBN and all other metadata will <i>not</i> be merged.<br><br>'
'After merger the second and subsequently '
'selected books, with any metadata they have will be <b>deleted</b>. <br><br>'
'All book formats of the first selected book will be kept '
'and any duplicate formats in the second and subsequently selected books '
'will be permanently <b>deleted</b> from your calibre library.<br><br> '
'Are you <b>sure</b> you want to proceed?')%title
+'</p>', 'merge_only_formats', self.gui):
return
self.add_formats(dest_id, src_books)
self.delete_books_after_merge(src_ids)
else:
if not confirm('<p>'+_(
'Book formats and metadata from the selected books will be merged '
@ -243,15 +269,10 @@ class EditMetadataAction(InterfaceAction):
'subsequently selected books will be <b>deleted</b>. <br><br>'
'All book formats of the first selected book will be kept '
'and any duplicate formats in the second and subsequently selected books '
'will be permanently <b>deleted</b> from your computer.<br><br> '
'will be permanently <b>deleted</b> from your calibre library.<br><br> '
'Are you <b>sure</b> you want to proceed?')%title
+'</p>', 'merge_books', self.gui):
return
if len(rows)>5:
if not confirm('<p>'+_('You are about to merge more than 5 books. '
'Are you <b>sure</b> you want to proceed?')
+'</p>', 'merge_too_many_books', self.gui):
return
self.add_formats(dest_id, src_books)
self.merge_metadata(dest_id, src_ids)
self.delete_books_after_merge(src_ids)

View File

@ -20,5 +20,6 @@ class CommentsDialog(QDialog, Ui_CommentsDialog):
if text is not None:
self.textbox.setPlainText(text)
self.textbox.setTabChangesFocus(True)
self.buttonBox.button(QDialogButtonBox.Ok).setText('&OK')
self.buttonBox.button(QDialogButtonBox.Cancel).setText('&Cancel')
self.buttonBox.button(QDialogButtonBox.Ok).setText(_('&OK'))
self.buttonBox.button(QDialogButtonBox.Cancel).setText(_('&Cancel'))

View File

@ -31,4 +31,5 @@ def confirm(msg, name, parent=None, pixmap='dialog_warning.png'):
d = Dialog(msg, name, parent)
d.label.setPixmap(QPixmap(I(pixmap)))
d.setWindowIcon(QIcon(I(pixmap)))
d.resize(d.sizeHint())
return d.exec_() == d.Accepted

View File

@ -359,7 +359,7 @@ class BrowseServer(object):
icon = 'blank.png'
cats.append((meta['name'], category, icon))
cats = [(u'<li><a title="{2} {0}" href="/browse/category/{1}">&nbsp;</a>'
cats = [(u'<li><a title="{2} {0}" href="{3}/browse/category/{1}">&nbsp;</a>'
u'<img src="{3}{src}" alt="{0}" />'
u'<span class="label">{0}</span>'
u'</li>')

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -4,9 +4,9 @@
#
msgid ""
msgstr ""
"Project-Id-Version: calibre 0.7.32\n"
"POT-Creation-Date: 2010-12-09 08:47+MST\n"
"PO-Revision-Date: 2010-12-09 08:47+MST\n"
"Project-Id-Version: calibre 0.7.33\n"
"POT-Creation-Date: 2010-12-10 14:25+MST\n"
"PO-Revision-Date: 2010-12-10 14:25+MST\n"
"Last-Translator: Automatically generated\n"
"Language-Team: LANGUAGE\n"
"MIME-Version: 1.0\n"
@ -35,7 +35,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/chm/input.py:100
#: /home/kovid/work/calibre/src/calibre/ebooks/chm/metadata.py:56
#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:407
#: /home/kovid/work/calibre/src/calibre/ebooks/epub/periodical.py:124
#: /home/kovid/work/calibre/src/calibre/ebooks/epub/periodical.py:126
#: /home/kovid/work/calibre/src/calibre/ebooks/fb2/input.py:93
#: /home/kovid/work/calibre/src/calibre/ebooks/fb2/input.py:95
#: /home/kovid/work/calibre/src/calibre/ebooks/html/input.py:338
@ -111,8 +111,8 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/rtf/input.py:307
#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:357
#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:364
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:308
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:311
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:329
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:332
#: /home/kovid/work/calibre/src/calibre/gui2/add.py:160
#: /home/kovid/work/calibre/src/calibre/gui2/add.py:167
#: /home/kovid/work/calibre/src/calibre/gui2/convert/__init__.py:42
@ -128,10 +128,10 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:193
#: /home/kovid/work/calibre/src/calibre/gui2/email.py:235
#: /home/kovid/work/calibre/src/calibre/gui2/email.py:244
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:379
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:398
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:925
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1118
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:396
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:415
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:942
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1135
#: /home/kovid/work/calibre/src/calibre/gui2/metadata.py:112
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:190
#: /home/kovid/work/calibre/src/calibre/library/cli.py:215
@ -1932,8 +1932,8 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/delete_matching_from_device.py:75
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:59
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:66
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:376
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:930
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:393
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:947
#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:304
#: /home/kovid/work/calibre/src/calibre/library/server/opds.py:570
msgid "Title"
@ -1942,8 +1942,8 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/book/base.py:608
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:60
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:68
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:381
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:931
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:398
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:948
msgid "Author(s)"
msgstr ""
@ -1964,8 +1964,8 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:189
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:108
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info_ui.py:79
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:328
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1137
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:342
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1154
#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:188
msgid "Comments"
msgstr ""
@ -1975,8 +1975,8 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:30
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories.py:60
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:74
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:316
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1133
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:330
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1150
#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:161
#: /home/kovid/work/calibre/src/calibre/library/server/browse.py:650
msgid "Tags"
@ -1987,8 +1987,8 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:29
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories.py:60
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:75
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:333
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1142
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:347
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1159
#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:109
msgid "Series"
msgstr ""
@ -1998,7 +1998,7 @@ msgid "Language"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/book/base.py:618
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1125
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1142
msgid "Timestamp"
msgstr ""
@ -3138,10 +3138,10 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/catalog.py:30
#: /home/kovid/work/calibre/src/calibre/gui2/actions/convert.py:87
#: /home/kovid/work/calibre/src/calibre/gui2/actions/copy_to_library.py:124
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:76
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:123
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:181
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:218
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:80
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:127
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:185
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:222
#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:92
msgid "No books selected"
msgstr ""
@ -3641,51 +3641,59 @@ msgstr ""
msgid "Merge into first selected book - keep others"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:75
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:58
msgid "Merge only formats into first selected book - delete others"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:79
msgid "Cannot download metadata"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:95
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:99
msgid "social metadata"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:97
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:101
msgid "covers"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:97
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:101
#: /home/kovid/work/calibre/src/calibre/gui2/metadata.py:224
msgid "metadata"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:98
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:102
msgid "Downloading %s for %d book(s)"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:122
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:180
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:126
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:184
msgid "Cannot edit metadata"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:217
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:220
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:221
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:224
msgid "Cannot merge books"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:221
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:225
msgid "At least two books must be selected for merging"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:226
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:228
msgid "You are about to merge more than 5 books. Are you <b>sure</b> you want to proceed?"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:236
msgid "Book formats and metadata from the selected books will be added to the <b>first selected book</b> (%s). ISBN will <i>not</i> be merged.<br><br> The second and subsequently selected books will not be deleted or changed.<br><br>Please confirm you want to proceed."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:238
msgid "Book formats and metadata from the selected books will be merged into the <b>first selected book</b> (%s). ISBN will <i>not</i> be merged.<br><br>After merger the second and subsequently selected books will be <b>deleted</b>. <br><br>All book formats of the first selected book will be kept and any duplicate formats in the second and subsequently selected books will be permanently <b>deleted</b> from your computer.<br><br> Are you <b>sure</b> you want to proceed?"
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:248
msgid "Book formats from the selected books will be merged into the <b>first selected book</b> (%s). Metadata in the first selected book will not be changed.Author, Title, ISBN and all other metadata will <i>not</i> be merged.<br><br>After merger the second and subsequently selected books, with any metadata they have will be <b>deleted</b>. <br><br>All book formats of the first selected book will be kept and any duplicate formats in the second and subsequently selected books will be permanently <b>deleted</b> from your calibre library.<br><br> Are you <b>sure</b> you want to proceed?"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:251
msgid "You are about to merge more than 5 books. Are you <b>sure</b> you want to proceed?"
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:264
msgid "Book formats and metadata from the selected books will be merged into the <b>first selected book</b> (%s). ISBN will <i>not</i> be merged.<br><br>After merger the second and subsequently selected books will be <b>deleted</b>. <br><br>All book formats of the first selected book will be kept and any duplicate formats in the second and subsequently selected books will be permanently <b>deleted</b> from your calibre library.<br><br> Are you <b>sure</b> you want to proceed?"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/fetch_news.py:17
@ -4134,8 +4142,8 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:125
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:135
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/delete_matching_from_device.py:76
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:323
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1123
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:337
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1140
msgid "Path"
msgstr ""
@ -4145,15 +4153,15 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:127
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:128
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:131
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:322
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:336
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/emailp.py:24
#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:118
msgid "Formats"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:28
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:934
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1126
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:951
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1143
msgid "Collections"
msgstr ""
@ -4163,11 +4171,11 @@ msgid "Click to open"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:53
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:315
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:321
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:327
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1132
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1136
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:329
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:335
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:341
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1149
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1153
#: /home/kovid/work/calibre/src/calibre/gui2/shortcuts.py:48
#: /home/kovid/work/calibre/src/calibre/gui2/shortcuts_ui.py:78
#: /home/kovid/work/calibre/src/calibre/gui2/shortcuts_ui.py:83
@ -5621,14 +5629,14 @@ msgid "<p>Cannot upload books to device there is no more free space available "
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/configwidget.py:89
#: /home/kovid/work/calibre/src/calibre/gui2/library/delegates.py:359
#: /home/kovid/work/calibre/src/calibre/gui2/library/delegates.py:368
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/plugboard.py:234
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/save_template.py:57
msgid "Invalid template"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/configwidget.py:90
#: /home/kovid/work/calibre/src/calibre/gui2/library/delegates.py:360
#: /home/kovid/work/calibre/src/calibre/gui2/library/delegates.py:369
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/plugboard.py:235
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/save_template.py:58
msgid "The template %s is invalid:"
@ -5859,7 +5867,17 @@ msgstr ""
msgid "&Profile:"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comments_dialog_ui.py:46
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comments_dialog.py:23
msgid "&OK"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comments_dialog.py:24
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tweak_epub_ui.py:60
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/main.py:225
msgid "&Cancel"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comments_dialog_ui.py:43
msgid "Edit Comments"
msgstr ""
@ -5884,7 +5902,7 @@ msgstr ""
#:
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/delete_matching_from_device.py:76
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:70
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:932
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:949
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/create_custom_column.py:33
#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:295
#: /home/kovid/work/calibre/src/calibre/library/server/opds.py:569
@ -5893,7 +5911,7 @@ msgstr ""
#:
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/delete_matching_from_device.py:76
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1122
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1139
msgid "Format"
msgstr ""
@ -7184,11 +7202,6 @@ msgstr ""
msgid "Discard changes"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tweak_epub_ui.py:60
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/main.py:225
msgid "&Cancel"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tweak_epub_ui.py:61
msgid "<p>Explode the ePub to display contents in a file browser window. To tweak individual files, right-click, then 'Open with...' your editor of choice. When tweaks are complete, close the file browser window <b>and the editor windows you used to edit files in the epub</b>.</p><p>Rebuild the ePub, updating your calibre library.</p>"
msgstr ""
@ -7687,6 +7700,10 @@ msgstr ""
msgid "Y"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/library/delegates.py:355
msgid "Edit template"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:67
#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:241
msgid "On Device"
@ -7697,38 +7714,38 @@ msgstr ""
msgid "Size (MB)"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:334
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:348
msgid "Book %s of %s."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:696
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1242
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:713
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1259
#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:454
msgid "The lookup/search name is \"{0}\""
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:702
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1244
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:719
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1261
msgid "This book's UUID is \"{0}\""
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:929
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:946
msgid "In Library"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:933
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:950
msgid "Size"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1142
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1159
msgid "Book <font face=\"serif\">%s</font> of %s."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1222
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1239
msgid "Marked for deletion"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1225
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1242
msgid "Double click to <b>edit</b> me<br><br>"
msgstr ""
@ -11232,23 +11249,51 @@ msgstr ""
msgid "How and when calibre updates metadata on the device."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/utils/formatter.py:36
msgid "lookup requires either 2 or an odd number of arguments"
#: /home/kovid/work/calibre/src/calibre/utils/formatter.py:77
msgid "failed to scan program. Invalid input {0}"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/utils/formatter.py:59
msgid "switch requires an odd number of arguments"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/utils/formatter.py:116
msgid "format: type {0} requires an integer value, got {1}"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/utils/formatter.py:122
msgid "format: type {0} requires a decimal (float) value, got {1}"
#: /home/kovid/work/calibre/src/calibre/utils/formatter.py:82
msgid " near "
msgstr ""
#: /home/kovid/work/calibre/src/calibre/utils/formatter.py:124
msgid "syntax error - program ends before EOF"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/utils/formatter.py:141
msgid "unknown id "
msgstr ""
#: /home/kovid/work/calibre/src/calibre/utils/formatter.py:146
msgid "unknown function {0}"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/utils/formatter.py:165
msgid "missing closing parenthesis"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/utils/formatter.py:183
msgid "expression is not function or constant"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/utils/formatter.py:210
msgid "lookup requires either 2 or an odd number of arguments"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/utils/formatter.py:233
msgid "switch requires an odd number of arguments"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/utils/formatter.py:290
msgid "format: type {0} requires an integer value, got {1}"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/utils/formatter.py:296
msgid "format: type {0} requires a decimal (float) value, got {1}"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/utils/formatter.py:298
msgid "format: unknown format type letter {0}"
msgstr ""

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

12391
src/calibre/translations/sc.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -329,7 +329,7 @@ icu_lower(PyObject *self, PyObject *args) {
PyMem_Free(input);
return ret;
}
} // }}}
// title {{{
static PyObject *
@ -374,9 +374,22 @@ icu_title(PyObject *self, PyObject *args) {
PyMem_Free(input);
return ret;
} // }}}
// set_default_encoding {{{
static PyObject *
icu_set_default_encoding(PyObject *self, PyObject *args) {
char *encoding;
if (!PyArg_ParseTuple(args, "s:setdefaultencoding", &encoding))
return NULL;
if (PyUnicode_SetDefaultEncoding(encoding))
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
// }}}
static PyMethodDef icu_methods[] = {
{"upper", icu_upper, METH_VARARGS,
@ -391,6 +404,10 @@ static PyMethodDef icu_methods[] = {
"title(locale, unicode object) -> Title cased unicode object using locale rules."
},
{"set_default_encoding", icu_set_default_encoding, METH_VARARGS,
"set_default_encoding(encoding) -> Set the default encoding for the python unicode implementation."
},
{NULL} /* Sentinel */
};

View File

@ -6,6 +6,7 @@ __copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
# Setup code {{{
import sys
from functools import partial
from calibre.constants import plugins
@ -77,11 +78,20 @@ def py_strcmp(a, b):
def icu_case_sensitive_strcmp(collator, a, b):
return collator.strcmp(a, b)
def icu_capitalize(s):
s = lower(s)
return s.replace(s[0], upper(s[0]), 1)
load_icu()
load_collator()
_icu_not_ok = _icu is None or _collator is None
try:
if sys.getdefaultencoding().lower() == 'ascii':
_icu.set_default_encoding('utf-8')
except:
pass
# }}}
################# The string functions ########################################
@ -104,10 +114,6 @@ lower = (lambda s: s.lower()) if _icu_not_ok else \
title_case = (lambda s: s.title()) if _icu_not_ok else \
partial(_icu.title, get_locale())
def icu_capitalize(s):
s = lower(s)
return s.replace(s[0], upper(s[0]))
capitalize = (lambda s: s.capitalize()) if _icu_not_ok else \
(lambda s: icu_capitalize(s))
@ -226,12 +232,16 @@ pêché'''
test_strcmp(german + french)
print '\nTesting case transforms in current locale'
for x in ('a', 'Alice\'s code'):
from calibre.utils.titlecase import titlecase
for x in ('a', 'Alice\'s code', 'macdonald\'s machine', '02 the wars'):
print 'Upper: ', x, '->', 'py:', x.upper().encode('utf-8'), 'icu:', upper(x).encode('utf-8')
print 'Lower: ', x, '->', 'py:', x.lower().encode('utf-8'), 'icu:', lower(x).encode('utf-8')
print 'Title: ', x, '->', 'py:', x.title().encode('utf-8'), 'icu:', title_case(x).encode('utf-8')
print 'Title: ', x, '->', 'py:', x.title().encode('utf-8'), 'icu:', title_case(x).encode('utf-8'), 'titlecase:', titlecase(x).encode('utf-8')
print 'Capitalize:', x, '->', 'py:', x.capitalize().encode('utf-8'), 'icu:', capitalize(x).encode('utf-8')
print
# }}}
if __name__ == '__main__':
test()

View File

@ -23,11 +23,12 @@ UC_ELSEWHERE = re.compile(r'[%s]*?[a-zA-Z]+[A-Z]+?' % PUNCT)
CAPFIRST = re.compile(r"^[%s]*?([A-Za-z])" % PUNCT)
SMALL_FIRST = re.compile(r'^([%s]*)(%s)\b' % (PUNCT, SMALL), re.I)
SMALL_LAST = re.compile(r'\b(%s)[%s]?$' % (SMALL, PUNCT), re.I)
SMALL_AFTER_NUM = re.compile(r'(\d+\s+)(a|an|the)\b', re.I)
SUBPHRASE = re.compile(r'([:.;?!][ ])(%s)' % SMALL)
APOS_SECOND = re.compile(r"^[dol]{1}[']{1}[a-z]+$", re.I)
ALL_CAPS = re.compile(r'^[A-Z\s%s]+$' % PUNCT)
UC_INITIALS = re.compile(r"^(?:[A-Z]{1}\.{1}|[A-Z]{1}\.{1}[A-Z]{1})+$")
MAC_MC = re.compile(r"^([Mm]a?c)(\w+)")
MAC_MC = re.compile(r"^([Mm]a?c)(.+)")
def titlecase(text):
@ -44,7 +45,7 @@ def titlecase(text):
all_caps = ALL_CAPS.match(text)
words = re.split('\s', text)
words = re.split('\s+', text)
line = []
for word in words:
if all_caps:
@ -55,8 +56,8 @@ def titlecase(text):
word = icu_lower(word)
if APOS_SECOND.match(word):
word = word.replace(word[0], icu_upper(word[0]))
word = word.replace(word[2], icu_upper(word[2]))
word = word.replace(word[0], icu_upper(word[0]), 1)
word = word[:2] + icu_upper(word[2]) + word[3:]
line.append(word)
continue
if INLINE_PERIOD.search(word) or UC_ELSEWHERE.match(word):
@ -67,7 +68,7 @@ def titlecase(text):
continue
match = MAC_MC.match(word)
if match:
if match and not match.group(2).startswith('hin'):
line.append("%s%s" % (capitalize(match.group(1)),
capitalize(match.group(2))))
continue
@ -85,6 +86,10 @@ def titlecase(text):
capitalize(m.group(2))
), result)
result = SMALL_AFTER_NUM.sub(lambda m: '%s%s' % (m.group(1),
capitalize(m.group(2))
), result)
result = SMALL_LAST.sub(lambda m: capitalize(m.group(0)), result)
result = SUBPHRASE.sub(lambda m: '%s%s' % (