From b3cbbd3ea8e05e1cd75b12e70d28ca1decc505d4 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Thu, 26 Aug 2010 14:32:57 +0100 Subject: [PATCH 001/235] Initial attempt, including full cached metadata, json serialization, and custom fields in save paths. Custom fields in collections probably work, but they haven't been tested. --- src/calibre/devices/apple/driver.py | 7 +- src/calibre/devices/interface.py | 4 +- src/calibre/devices/kobo/books.py | 21 +- src/calibre/devices/usbms/books.py | 43 +-- src/calibre/devices/usbms/driver.py | 21 +- src/calibre/ebooks/metadata/__init__.py | 216 +------------ src/calibre/ebooks/metadata/book/__init__.py | 41 ++- src/calibre/ebooks/metadata/book/base.py | 296 +++++++++++++++--- .../ebooks/metadata/book/json_codec.py | 125 ++++++++ src/calibre/ebooks/metadata/isbndb.py | 6 +- src/calibre/ebooks/metadata/opf2.py | 9 +- .../gui2/dialogs/config/save_template.py | 29 +- src/calibre/gui2/library/models.py | 3 +- src/calibre/library/database2.py | 31 +- src/calibre/library/save_to_disk.py | 19 +- 15 files changed, 514 insertions(+), 357 deletions(-) create mode 100644 src/calibre/ebooks/metadata/book/json_codec.py diff --git a/src/calibre/devices/apple/driver.py b/src/calibre/devices/apple/driver.py index 916c88f203..75517e9df7 100644 --- a/src/calibre/devices/apple/driver.py +++ b/src/calibre/devices/apple/driver.py @@ -13,7 +13,8 @@ from calibre.devices.errors import UserFeedback from calibre.devices.usbms.deviceconfig import DeviceConfig from calibre.devices.interface import DevicePlugin from calibre.ebooks.BeautifulSoup import BeautifulSoup -from calibre.ebooks.metadata import MetaInformation, authors_to_string +from calibre.ebooks.metadata import authors_to_string +from calibre.ebooks.metadata.book.base import Metadata from calibre.ebooks.metadata.epub import set_metadata from calibre.library.server.utils import strftime from calibre.utils.config import config_dir @@ -2998,14 +2999,14 @@ class BookList(list): ''' return {} -class Book(MetaInformation): +class Book(Metadata): ''' A simple class describing a book in the iTunes Books Library. - See ebooks.metadata.__init__ for all fields ''' def __init__(self,title,author): - MetaInformation.__init__(self, title, authors=[author]) + Metadata.__init__(self, title, authors=[author]) @dynamic_property def title_sorter(self): diff --git a/src/calibre/devices/interface.py b/src/calibre/devices/interface.py index 1384fa03d9..7783173c9c 100644 --- a/src/calibre/devices/interface.py +++ b/src/calibre/devices/interface.py @@ -316,7 +316,7 @@ class DevicePlugin(Plugin): being uploaded to the device. :param names: A list of file names that the books should have once uploaded to the device. len(names) == len(files) - :param metadata: If not None, it is a list of :class:`MetaInformation` objects. + :param metadata: If not None, it is a list of :class:`Metadata` objects. The idea is to use the metadata to determine where on the device to put the book. len(metadata) == len(files). Apart from the regular cover (path to cover), there may also be a thumbnail attribute, which should @@ -335,7 +335,7 @@ class DevicePlugin(Plugin): the device. :param locations: Result of a call to L{upload_books} - :param metadata: List of :class:`MetaInformation` objects, same as for + :param metadata: List of :class:`Metadata` objects, same as for :meth:`upload_books`. :param booklists: A tuple containing the result of calls to (:meth:`books(oncard=None)`, diff --git a/src/calibre/devices/kobo/books.py b/src/calibre/devices/kobo/books.py index a5b2e98d2f..11ab42c29f 100644 --- a/src/calibre/devices/kobo/books.py +++ b/src/calibre/devices/kobo/books.py @@ -7,11 +7,11 @@ import os import re import time -from calibre.ebooks.metadata import MetaInformation +from calibre.ebooks.metadata.book.base import Metadata from calibre.constants import filesystem_encoding, preferred_encoding from calibre import isbytestring -class Book(MetaInformation): +class Book(Metadata): BOOK_ATTRS = ['lpath', 'size', 'mime', 'device_collections', '_new_book'] @@ -23,9 +23,9 @@ class Book(MetaInformation): 'uuid', ] - def __init__(self, prefix, lpath, title, authors, mime, date, ContentType, thumbnail_name, other=None): - - MetaInformation.__init__(self, '') + def __init__(self, prefix, lpath, title, authors, mime, date, ContentType, + thumbnail_name, other=None): + Metadata.__init__(self, '') self.device_collections = [] self._new_book = False @@ -34,7 +34,7 @@ class Book(MetaInformation): self.path = self.path.replace('/', '\\') self.lpath = lpath.replace('\\', '/') else: - self.lpath = lpath + self.lpath = lpath self.title = title if not authors: @@ -52,10 +52,9 @@ class Book(MetaInformation): else: self.datetime = time.gmtime(os.path.getctime(self.path)) except: - self.datetime = time.gmtime() - - if thumbnail_name is not None: - self.thumbnail = ImageWrapper(thumbnail_name) + self.datetime = time.gmtime() + if thumbnail_name is not None: + self.thumbnail = ImageWrapper(thumbnail_name) self.tags = [] if other: self.smart_update(other) @@ -90,7 +89,7 @@ class Book(MetaInformation): in C{other} takes precedence, unless the information in C{other} is NULL. ''' - MetaInformation.smart_update(self, other) + Metadata.smart_update(self, other) for attr in self.BOOK_ATTRS: if hasattr(other, attr): diff --git a/src/calibre/devices/usbms/books.py b/src/calibre/devices/usbms/books.py index 959f26199c..e3c405ee4e 100644 --- a/src/calibre/devices/usbms/books.py +++ b/src/calibre/devices/usbms/books.py @@ -6,29 +6,18 @@ __docformat__ = 'restructuredtext en' import os, re, time, sys -from calibre.ebooks.metadata import MetaInformation +from calibre.ebooks.metadata.book.base import Metadata from calibre.devices.mime import mime_type_ext from calibre.devices.interface import BookList as _BookList from calibre.constants import filesystem_encoding, preferred_encoding from calibre import isbytestring from calibre.utils.config import prefs -class Book(MetaInformation): - - BOOK_ATTRS = ['lpath', 'size', 'mime', 'device_collections', '_new_book'] - - JSON_ATTRS = [ - 'lpath', 'title', 'authors', 'mime', 'size', 'tags', 'author_sort', - 'title_sort', 'comments', 'category', 'publisher', 'series', - 'series_index', 'rating', 'isbn', 'language', 'application_id', - 'book_producer', 'lccn', 'lcc', 'ddc', 'rights', 'publication_type', - 'uuid', - ] - +class Book(Metadata): def __init__(self, prefix, lpath, size=None, other=None): from calibre.ebooks.metadata.meta import path_to_ext - MetaInformation.__init__(self, '') + Metadata.__init__(self, '') self._new_book = False self.device_collections = [] @@ -72,32 +61,6 @@ class Book(MetaInformation): def thumbnail(self): return None - def smart_update(self, other, replace_metadata=False): - ''' - Merge the information in C{other} into self. In case of conflicts, the information - in C{other} takes precedence, unless the information in C{other} is NULL. - ''' - - MetaInformation.smart_update(self, other, replace_metadata) - - for attr in self.BOOK_ATTRS: - if hasattr(other, attr): - val = getattr(other, attr, None) - setattr(self, attr, val) - - def to_json(self): - json = {} - for attr in self.JSON_ATTRS: - val = getattr(self, attr) - if isbytestring(val): - enc = filesystem_encoding if attr == 'lpath' else preferred_encoding - val = val.decode(enc, 'replace') - elif isinstance(val, (list, tuple)): - val = [x.decode(preferred_encoding, 'replace') if - isbytestring(x) else x for x in val] - json[attr] = val - return json - class BookList(_BookList): def __init__(self, oncard, prefix, settings): diff --git a/src/calibre/devices/usbms/driver.py b/src/calibre/devices/usbms/driver.py index 0d28f06f49..a0d1d9dbf8 100644 --- a/src/calibre/devices/usbms/driver.py +++ b/src/calibre/devices/usbms/driver.py @@ -13,7 +13,6 @@ for a particular device. import os import re import time -import json from itertools import cycle from calibre import prints, isbytestring @@ -21,6 +20,7 @@ from calibre.constants import filesystem_encoding, DEBUG from calibre.devices.usbms.cli import CLI from calibre.devices.usbms.device import Device from calibre.devices.usbms.books import BookList, Book +from calibre.ebooks.metadata.book.json_codec import JsonCodec BASE_TIME = None def debug_print(*args): @@ -288,6 +288,7 @@ class USBMS(CLI, Device): # at the end just before the return def sync_booklists(self, booklists, end_session=True): debug_print('USBMS: starting sync_booklists') + json_codec = JsonCodec() if not os.path.exists(self.normalize_path(self._main_prefix)): os.makedirs(self.normalize_path(self._main_prefix)) @@ -296,10 +297,8 @@ class USBMS(CLI, Device): if prefix is not None and isinstance(booklists[listid], self.booklist_class): if not os.path.exists(prefix): os.makedirs(self.normalize_path(prefix)) - js = [item.to_json() for item in booklists[listid] if - hasattr(item, 'to_json')] with open(self.normalize_path(os.path.join(prefix, self.METADATA_CACHE)), 'wb') as f: - f.write(json.dumps(js, indent=2, encoding='utf-8')) + json_codec.encode_to_file(f, booklists[listid]) write_prefix(self._main_prefix, 0) write_prefix(self._card_a_prefix, 1) write_prefix(self._card_b_prefix, 2) @@ -345,19 +344,13 @@ class USBMS(CLI, Device): @classmethod def parse_metadata_cache(cls, bl, prefix, name): - # bl = cls.booklist_class() - js = [] + json_codec = JsonCodec() need_sync = False cache_file = cls.normalize_path(os.path.join(prefix, name)) if os.access(cache_file, os.R_OK): try: with open(cache_file, 'rb') as f: - js = json.load(f, encoding='utf-8') - for item in js: - book = cls.book_class(prefix, item.get('lpath', None)) - for key in item.keys(): - setattr(book, key, item[key]) - bl.append(book) + json_codec.decode_from_file(f, bl, cls.book_class, prefix) except: import traceback traceback.print_exc() @@ -392,7 +385,7 @@ class USBMS(CLI, Device): @classmethod def book_from_path(cls, prefix, lpath): - from calibre.ebooks.metadata import MetaInformation + from calibre.ebooks.metadata.book.base import Metadata if cls.settings().read_metadata or cls.MUST_READ_METADATA: mi = cls.metadata_from_path(cls.normalize_path(os.path.join(prefix, lpath))) @@ -401,7 +394,7 @@ class USBMS(CLI, Device): mi = metadata_from_filename(cls.normalize_path(os.path.basename(lpath)), cls.build_template_regexp()) if mi is None: - mi = MetaInformation(os.path.splitext(os.path.basename(lpath))[0], + mi = Metadata(os.path.splitext(os.path.basename(lpath))[0], [_('Unknown')]) size = os.stat(cls.normalize_path(os.path.join(prefix, lpath))).st_size book = cls.book_class(prefix, lpath, other=mi, size=size) diff --git a/src/calibre/ebooks/metadata/__init__.py b/src/calibre/ebooks/metadata/__init__.py index d4a21e2c8c..fb894d3bbd 100644 --- a/src/calibre/ebooks/metadata/__init__.py +++ b/src/calibre/ebooks/metadata/__init__.py @@ -221,214 +221,18 @@ class ResourceCollection(object): -class MetaInformation(object): - '''Convenient encapsulation of book metadata''' - - @staticmethod - def copy(mi): - ans = MetaInformation(mi.title, mi.authors) - for attr in ('author_sort', 'title_sort', 'comments', 'category', - 'publisher', 'series', 'series_index', 'rating', - 'isbn', 'tags', 'cover_data', 'application_id', 'guide', - 'manifest', 'spine', 'toc', 'cover', 'language', - 'book_producer', 'timestamp', 'lccn', 'lcc', 'ddc', - 'author_sort_map', - 'pubdate', 'rights', 'publication_type', 'uuid'): - if hasattr(mi, attr): - setattr(ans, attr, getattr(mi, attr)) - - def __init__(self, title, authors=(_('Unknown'),)): - ''' +def MetaInformation(title, authors=(_('Unknown'),)): + ''' Convenient encapsulation of book metadata, needed for compatibility @param title: title or ``_('Unknown')`` or a MetaInformation object @param authors: List of strings or [] - ''' - mi = None - if hasattr(title, 'title') and hasattr(title, 'authors'): - mi = title - title = mi.title - authors = mi.authors - self.title = title - self.author = list(authors) if authors else []# Needed for backward compatibility - #: List of strings or [] - self.authors = list(authors) if authors else [] - self.tags = getattr(mi, 'tags', []) - #: mi.cover_data = (ext, data) - self.cover_data = getattr(mi, 'cover_data', (None, None)) - self.author_sort_map = getattr(mi, 'author_sort_map', {}) - - for x in ('author_sort', 'title_sort', 'comments', 'category', 'publisher', - 'series', 'series_index', 'rating', 'isbn', 'language', - 'application_id', 'manifest', 'toc', 'spine', 'guide', 'cover', - 'book_producer', 'timestamp', 'lccn', 'lcc', 'ddc', 'pubdate', - 'rights', 'publication_type', 'uuid', - ): - setattr(self, x, getattr(mi, x, None)) - - def print_all_attributes(self): - for x in ('title','author', 'author_sort', 'title_sort', 'comments', 'category', 'publisher', - 'series', 'series_index', 'tags', 'rating', 'isbn', 'language', - 'application_id', 'manifest', 'toc', 'spine', 'guide', 'cover', - 'book_producer', 'timestamp', 'lccn', 'lcc', 'ddc', 'pubdate', - 'rights', 'publication_type', 'uuid', 'author_sort_map' - ): - prints(x, getattr(self, x, 'None')) - - def smart_update(self, mi, replace_metadata=False): - ''' - Merge the information in C{mi} into self. In case of conflicts, the - information in C{mi} takes precedence, unless the information in mi is - NULL. If replace_metadata is True, then the information in mi always - takes precedence. - ''' - if mi.title and mi.title != _('Unknown'): - self.title = mi.title - - if mi.authors and mi.authors[0] != _('Unknown'): - self.authors = mi.authors - - for attr in ('author_sort', 'title_sort', 'category', - 'publisher', 'series', 'series_index', 'rating', - 'isbn', 'application_id', 'manifest', 'spine', 'toc', - 'cover', 'guide', 'book_producer', - 'timestamp', 'lccn', 'lcc', 'ddc', 'pubdate', 'rights', - 'publication_type', 'uuid'): - if replace_metadata: - setattr(self, attr, getattr(mi, attr, 1.0 if \ - attr == 'series_index' else None)) - elif hasattr(mi, attr): - val = getattr(mi, attr) - if val is not None: - setattr(self, attr, val) - - if replace_metadata: - self.tags = mi.tags - elif mi.tags: - self.tags += mi.tags - self.tags = list(set(self.tags)) - - if mi.author_sort_map: - self.author_sort_map.update(mi.author_sort_map) - - if getattr(mi, 'cover_data', False): - other_cover = mi.cover_data[-1] - self_cover = self.cover_data[-1] if self.cover_data else '' - if not self_cover: self_cover = '' - if not other_cover: other_cover = '' - if len(other_cover) > len(self_cover): - self.cover_data = mi.cover_data - - if replace_metadata: - self.comments = getattr(mi, 'comments', '') - else: - my_comments = getattr(self, 'comments', '') - other_comments = getattr(mi, 'comments', '') - if not my_comments: - my_comments = '' - if not other_comments: - other_comments = '' - if len(other_comments.strip()) > len(my_comments.strip()): - self.comments = other_comments - - other_lang = getattr(mi, 'language', None) - if other_lang and other_lang.lower() != 'und': - self.language = other_lang - - - def format_series_index(self): - try: - x = float(self.series_index) - except ValueError: - x = 1 - return fmt_sidx(x) - - def authors_from_string(self, raw): - self.authors = string_to_authors(raw) - - def format_authors(self): - return authors_to_string(self.authors) - - def format_tags(self): - return u', '.join([unicode(t) for t in self.tags]) - - def format_rating(self): - return unicode(self.rating) - - def __unicode__(self): - ans = [] - def fmt(x, y): - ans.append(u'%-20s: %s'%(unicode(x), unicode(y))) - - fmt('Title', self.title) - if self.title_sort: - fmt('Title sort', self.title_sort) - if self.authors: - fmt('Author(s)', authors_to_string(self.authors) + \ - ((' [' + self.author_sort + ']') if self.author_sort else '')) - if self.publisher: - fmt('Publisher', self.publisher) - if getattr(self, 'book_producer', False): - fmt('Book Producer', self.book_producer) - if self.category: - fmt('Category', self.category) - if self.comments: - fmt('Comments', self.comments) - if self.isbn: - fmt('ISBN', self.isbn) - if self.tags: - fmt('Tags', u', '.join([unicode(t) for t in self.tags])) - if self.series: - fmt('Series', self.series + ' #%s'%self.format_series_index()) - if self.language: - fmt('Language', self.language) - if self.rating is not None: - fmt('Rating', self.rating) - if self.timestamp is not None: - fmt('Timestamp', isoformat(self.timestamp)) - if self.pubdate is not None: - fmt('Published', isoformat(self.pubdate)) - if self.rights is not None: - fmt('Rights', unicode(self.rights)) - if self.lccn: - fmt('LCCN', unicode(self.lccn)) - if self.lcc: - fmt('LCC', unicode(self.lcc)) - if self.ddc: - fmt('DDC', unicode(self.ddc)) - - return u'\n'.join(ans) - - def to_html(self): - ans = [(_('Title'), unicode(self.title))] - ans += [(_('Author(s)'), (authors_to_string(self.authors) if self.authors else _('Unknown')))] - ans += [(_('Publisher'), unicode(self.publisher))] - ans += [(_('Producer'), unicode(self.book_producer))] - ans += [(_('Comments'), unicode(self.comments))] - ans += [('ISBN', unicode(self.isbn))] - if self.lccn: - ans += [('LCCN', unicode(self.lccn))] - if self.lcc: - ans += [('LCC', unicode(self.lcc))] - if self.ddc: - ans += [('DDC', unicode(self.ddc))] - ans += [(_('Tags'), u', '.join([unicode(t) for t in self.tags]))] - if self.series: - ans += [(_('Series'), unicode(self.series)+ ' #%s'%self.format_series_index())] - ans += [(_('Language'), unicode(self.language))] - if self.timestamp is not None: - ans += [(_('Timestamp'), unicode(self.timestamp.isoformat(' ')))] - if self.pubdate is not None: - ans += [(_('Published'), unicode(self.pubdate.isoformat(' ')))] - if self.rights is not None: - ans += [(_('Rights'), unicode(self.rights))] - for i, x in enumerate(ans): - ans[i] = u'
'+_('The template %s is invalid:')%tmpl + \
- '
'+str(err), show=True)
- return False
+ # TODO: I haven't figured out how to get the custom columns into here,
+ # so for the moment make all templates valid.
return True
+# tmpl = preprocess_template(self.opt_template.text())
+# fa = {}
+# for x in FORMAT_ARG_DESCS.keys():
+# fa[x]='random long string'
+# try:
+# tmpl.format(**fa)
+# except Exception, err:
+# error_dialog(self, _('Invalid template'),
+# '
'+_('The template %s is invalid:')%tmpl + \
+# ' '+_('The template %s is invalid:')%tmpl + \
+ ' '+_('The template %s is invalid:')%tmpl + \
-# ' '+
- _('You can destroy your library '
- 'using this feature. Changes are permanent. There '
- 'is no undo function. You are strongly encouraged '
- 'to back up your library before proceeding.'
- ) + ' ' + _(
- 'Search and replace in text fields using '
- 'regular expressions. The search text is an '
- 'arbitrary python-compatible regular expression. '
- 'The replacement text can contain backreferences '
- 'to parenthesized expressions in the pattern. '
- 'The search is not anchored, and can match and '
- 'replace multiple times on the same string. See '
- ' '
- 'this reference '
- 'for more information, and in particular the \'sub\' '
- 'function.'
- ))
+ self.s_r_heading.setText(' '+ _(
+ 'You can destroy your library using this feature. '
+ 'Changes are permanent. There is no undo function. '
+ ' This feature is experimental, and there may be bugs. '
+ 'You are strongly encouraged to back up your library '
+ 'before proceeding.'
+ ) + ' ' + _(
+ 'Search and replace in text fields using character matching '
+ 'or regular expressions. In character mode, search text '
+ 'found in the specified field is replaced with replace '
+ 'text. In regular expression mode, the search text is an '
+ 'arbitrary python-compatible regular expression. The '
+ 'replacement text can contain backreferences to parenthesized '
+ 'expressions in the pattern. The search is not anchored, '
+ 'and can match and replace multiple times on the same string. '
+ 'See '
+ 'this reference for more information, and in particular '
+ 'the \'sub\' function.'
+ ))
self.search_mode.addItems(self.s_r_match_modes)
- self.search_mode.setCurrentIndex(0)
+ self.search_mode.setCurrentIndex(dynamic.get('s_r_search_mode', 0))
self.replace_mode.addItems(self.s_r_replace_modes)
self.replace_mode.setCurrentIndex(0)
@@ -252,7 +253,7 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
self.search_for.completer().setCaseSensitivity(Qt.CaseSensitive)
self.replace_with.completer().setCaseSensitivity(Qt.CaseSensitive)
- self.s_r_search_mode_changed(0)
+ self.s_r_search_mode_changed(self.search_mode.currentIndex())
def s_r_get_field(self, mi, field):
if field:
@@ -303,6 +304,7 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
self.replace_mode.setVisible(True)
self.replace_mode_label.setVisible(True)
self.comma_separated.setVisible(True)
+ self.s_r_paint_results(None)
def s_r_set_colors(self):
if self.s_r_error is not None:
@@ -325,8 +327,12 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
src_field = unicode(self.search_field.currentText())
src = self.s_r_get_field(mi, src_field)
result = []
+ rfunc = self.s_r_functions[unicode(self.replace_func.currentText())]
for s in src:
- result.append(self.s_r_obj.sub(self.s_r_func, s))
+ t = self.s_r_obj.sub(self.s_r_func, s)
+ if self.search_mode.currentIndex() == 0:
+ t = rfunc(t)
+ result.append(t)
return result
def s_r_do_destination(self, mi, val):
@@ -374,7 +380,10 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
flags = re.I
try:
- self.s_r_obj = re.compile(unicode(self.search_for.text()), flags)
+ if self.search_mode.currentIndex() == 0:
+ self.s_r_obj = re.compile(re.escape(unicode(self.search_for.text())), flags)
+ else:
+ self.s_r_obj = re.compile(unicode(self.search_for.text()), flags)
except Exception as e:
self.s_r_obj = None
self.s_r_error = e
@@ -411,7 +420,7 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
dest = unicode(self.destination_field.currentText())
if not dest:
dest = source
- dfm = self.db.field_metadata[source]
+ dfm = self.db.field_metadata[dest]
for id in self.ids:
mi = self.db.get_metadata(id, index_is_id=True,)
@@ -439,6 +448,7 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
setter = getattr(self.db, 'set_'+dest)
setter(id, val, notify=False, commit=False)
self.db.commit()
+ dynamic['s_r_search_mode'] = self.search_mode.currentIndex()
def create_custom_column_editors(self):
w = self.central_widget.widget(1)
diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py
index 2f9f9b6f89..c1ada94a84 100644
--- a/src/calibre/library/database2.py
+++ b/src/calibre/library/database2.py
@@ -464,11 +464,11 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
# change case don't cause any changes to the directories in the file
# system. This can lead to having the directory names not match the
# title/author, which leads to trouble when libraries are copied to
- # a case-sensitive system. The following code fixes this by checking
- # each segment. If they are different because of case, then rename
- # the segment to some temp file name, then rename it back to the
- # correct name. Note that the code above correctly handles files in
- # the directories, so no need to do them here.
+ # a case-sensitive system. The following code attempts to fix this
+ # by checking each segment. If they are different because of case,
+ # then rename the segment to some temp file name, then rename it
+ # back to the correct name. Note that the code above correctly
+ # handles files in the directories, so no need to do them here.
for oldseg, newseg in zip(c1, c2):
if oldseg.lower() == newseg.lower() and oldseg != newseg:
while True:
@@ -476,8 +476,17 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
tempname = os.path.join(curpath, 'TEMP.%f'%time.time())
if not os.path.exists(tempname):
break
- os.rename(os.path.join(curpath, oldseg), tempname)
- os.rename(tempname, os.path.join(curpath, newseg))
+ try:
+ os.rename(os.path.join(curpath, oldseg), tempname)
+ except (IOError, OSError):
+ # Windows (at least) sometimes refuses to do the rename
+ # probably because a file such a cover is open in the
+ # hierarchy. Just go on -- nothing is hurt beyond the
+ # case of the filesystem not matching the case in
+ # name stored by calibre
+ print 'rename of library component failed'
+ else:
+ os.rename(tempname, os.path.join(curpath, newseg))
curpath = os.path.join(curpath, newseg)
def add_listener(self, listener):
From e2f4b969bc6d36fbb285818cb50184cf83efed6e Mon Sep 17 00:00:00 2001
From: Charles Haley <>
Date: Mon, 20 Sep 2010 19:49:03 +0100
Subject: [PATCH 059/235] 1) add tooltips 2) change main heading text depending
on the mode 3) add an error if attempting to assign '' to authors or title
---
src/calibre/gui2/dialogs/metadata_bulk.py | 48 +++++++++++++++++----
src/calibre/gui2/dialogs/metadata_bulk.ui | 52 +++++++++++++++++++----
2 files changed, 84 insertions(+), 16 deletions(-)
diff --git a/src/calibre/gui2/dialogs/metadata_bulk.py b/src/calibre/gui2/dialogs/metadata_bulk.py
index b01869deaa..681f65b19e 100644
--- a/src/calibre/gui2/dialogs/metadata_bulk.py
+++ b/src/calibre/gui2/dialogs/metadata_bulk.py
@@ -208,25 +208,43 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
self.book_1_text.setObjectName(name)
self.testgrid.addWidget(w, i+offset, 2, 1, 1)
- self.s_r_heading.setText(' '+ _(
+ self.main_heading = _(
'You can destroy your library using this feature. '
'Changes are permanent. There is no undo function. '
' This feature is experimental, and there may be bugs. '
'You are strongly encouraged to back up your library '
'before proceeding.'
- ) + ' ' + _(
+ + ' ' +
'Search and replace in text fields using character matching '
- 'or regular expressions. In character mode, search text '
- 'found in the specified field is replaced with replace '
- 'text. In regular expression mode, the search text is an '
+ 'or regular expressions. ')
+
+ self.character_heading = _(
+ 'In character mode, the field is searched for the entered '
+ 'search text. The text is replaced by the specified replacement '
+ 'text everywhere it is found in the specified field. After '
+ 'replacement is finished, the text can be changed to '
+ 'upper-case, lower-case, or title-case. If the case-sensitive '
+ 'check box is checked, the search text must match exactly. If '
+ 'it is unchecked, the search text will match both upper- and '
+ 'lower-case letters'
+ )
+
+ self.regexp_heading = _(
+ 'In regular expression mode, the search text is an '
'arbitrary python-compatible regular expression. The '
'replacement text can contain backreferences to parenthesized '
'expressions in the pattern. The search is not anchored, '
'and can match and replace multiple times on the same string. '
+ 'The modification functions (lower-case etc) are applied to the '
+ 'matched text, not to the field as a whole. '
+ 'The destination box specifies the field where the result after '
+ 'matching and replacement is to be assigned. You can replace '
+ 'the text in the field, or prepend or append the matched text. '
'See '
- 'this reference for more information, and in particular '
- 'the \'sub\' function.'
- ))
+ 'this reference for more information on python\'s regular '
+ 'expressions, and in particular the \'sub\' function.'
+ )
+
self.search_mode.addItems(self.s_r_match_modes)
self.search_mode.setCurrentIndex(dynamic.get('s_r_search_mode', 0))
self.replace_mode.addItems(self.s_r_replace_modes)
@@ -298,12 +316,14 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
self.replace_mode.setVisible(False)
self.replace_mode_label.setVisible(False)
self.comma_separated.setVisible(False)
+ self.s_r_heading.setText(' '+self.main_heading + self.character_heading)
else:
self.destination_field.setVisible(True)
self.destination_field_label.setVisible(True)
self.replace_mode.setVisible(True)
self.replace_mode_label.setVisible(True)
self.comma_separated.setVisible(True)
+ self.s_r_heading.setText(' '+self.main_heading + self.regexp_heading)
self.s_r_paint_results(None)
def s_r_set_colors(self):
@@ -434,8 +454,20 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
# The standard tags and authors values want to be lists.
# All custom columns are to be strings
val = dfm['is_multiple'].join(val)
+ if dest == 'authors' and len(val) == 0:
+ error_dialog(self, _('Search/replace invalid'),
+ _('Authors cannot be set to the empty string. '
+ 'Book title %s not processed')%mi.title,
+ show=True)
+ continue
else:
val = self.s_r_replace_mode_separator().join(val)
+ if dest == 'title' and len(val) == 0:
+ error_dialog(self, _('Search/replace invalid'),
+ _('Title cannot be set to the empty string. '
+ 'Book title %s not processed')%mi.title,
+ show=True)
+ continue
if dfm['is_custom']:
extra = self.db.get_custom_extra(id, label=dfm['label'], index_is_id=True)
diff --git a/src/calibre/gui2/dialogs/metadata_bulk.ui b/src/calibre/gui2/dialogs/metadata_bulk.ui
index e433aaf327..b2a3e11b4a 100644
--- a/src/calibre/gui2/dialogs/metadata_bulk.ui
+++ b/src/calibre/gui2/dialogs/metadata_bulk.ui
@@ -351,7 +351,11 @@ Future conversion of these books will use the default settings.
'+self.main_heading + self.character_heading)
else:
+ self.search_field.addItems(self.all_fields)
+ self.destination_field.addItems(self.writable_fields)
self.destination_field.setVisible(True)
self.destination_field_label.setVisible(True)
self.replace_mode.setVisible(True)
@@ -367,6 +385,8 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
return ''
dest = unicode(self.destination_field.currentText())
if dest == '':
+ if self.db.metadata_for_field(src)['datatype'] == 'composite':
+ raise Exception(_('You must specify a destination when source is a composite field'))
dest = src
dest_mode = self.replace_mode.currentIndex()
@@ -433,8 +453,6 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
t = self.s_r_replace_mode_separator().join(t)
wr.setText(t)
except Exception as e:
- import traceback
- traceback.print_exc()
self.s_r_error = e
self.s_r_set_colors()
break
@@ -592,11 +610,12 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
do_swap_ta = self.swap_title_and_author.isChecked()
do_remove_conv = self.remove_conversion_settings.isChecked()
do_auto_author = self.auto_author_sort.isChecked()
+ do_title_case = self.change_title_to_title_case.isChecked()
args = (remove, add, au, aus, do_aus, rating, pub, do_series,
do_autonumber, do_remove_format, remove_format, do_swap_ta,
do_remove_conv, do_auto_author, series, do_series_restart,
- series_start_value)
+ series_start_value, do_title_case)
bb = BlockingBusy(_('Applying changes to %d books. This may take a while.')
%len(self.ids), parent=self)
diff --git a/src/calibre/gui2/dialogs/metadata_bulk.ui b/src/calibre/gui2/dialogs/metadata_bulk.ui
index 10e22c5df9..e03a59b7ea 100644
--- a/src/calibre/gui2/dialogs/metadata_bulk.ui
+++ b/src/calibre/gui2/dialogs/metadata_bulk.ui
@@ -270,6 +270,17 @@
'+_('The template %s is invalid:')%tmpl + \
+ ' '+_('The template %s is invalid:')%val + \
+ ' '+_('The template %s is invalid:')%tmpl + \
diff --git a/src/calibre/library/caches.py b/src/calibre/library/caches.py
index 42feb6f8fa..7849eecb2e 100644
--- a/src/calibre/library/caches.py
+++ b/src/calibre/library/caches.py
@@ -546,7 +546,7 @@ class ResultCache(SearchQueryParser):
if len(self.composites) > 0:
mi = db.get_metadata(id, index_is_id=True)
for k,c in self.composites:
- self._data[id][c] = mi.format_field(k)[1]
+ self._data[id][c] = mi.get(k, None)
except IndexError:
return None
try:
diff --git a/src/calibre/library/save_to_disk.py b/src/calibre/library/save_to_disk.py
index 90e5413389..a0f739e4c2 100644
--- a/src/calibre/library/save_to_disk.py
+++ b/src/calibre/library/save_to_disk.py
@@ -9,6 +9,7 @@ __docformat__ = 'restructuredtext en'
import os, traceback, cStringIO, re, string
from calibre.utils.config import Config, StringConfig, tweaks
+from calibre.utils.formatter import TemplateFormatter
from calibre.utils.filenames import shorten_components_to, supports_long_names, \
ascii_filename, sanitize_file_name
from calibre.ebooks.metadata.opf2 import metadata_to_opf
@@ -101,40 +102,20 @@ def preprocess_template(template):
template = template.decode(preferred_encoding, 'replace')
return template
-template_value_re = re.compile(r'^([^\|]*(?=\|))(?:\|?)([^\|]*)(?:\|?)((?<=\|).*?)$',
- flags= re.UNICODE)
-
-def explode_string_template_value(key):
- try:
- matches = template_value_re.match(key)
- if matches.lastindex != 3:
- return key
- return matches.groups()
- except:
- return '', key, ''
-
-class SafeFormat(string.Formatter):
+class SafeFormat(TemplateFormatter):
'''
Provides a format function that substitutes '' for any missing value
'''
def get_value(self, key, args, kwargs):
try:
- prefix, key, suffix = explode_string_template_value(key)
if kwargs[key]:
- return prefix + unicode(kwargs[key]) + suffix
+ return kwargs[key]
return ''
except:
return ''
safe_formatter = SafeFormat()
-def safe_format(x, format_args):
- try:
- ans = safe_formatter.vformat(x, [], format_args).strip()
- except:
- ans = ''
- return re.sub(r'\s+', ' ', ans)
-
def get_components(template, mi, id, timefmt='%b %Y', length=250,
sanitize_func=ascii_filename, replace_whitespace=False,
to_lowercase=False):
@@ -178,8 +159,8 @@ def get_components(template, mi, id, timefmt='%b %Y', length=250,
elif custom_metadata[key]['datatype'] == 'bool':
format_args[key] = _('yes') if format_args[key] else _('no')
- components = [x.strip() for x in template.split('/') if x.strip()]
- components = [safe_format(x, format_args) for x in components]
+ components = safe_formatter.safe_format(template, format_args, '')
+ components = [x.strip() for x in components.split('/') if x.strip()]
components = [sanitize_func(x) for x in components if x]
if not components:
components = [str(id)]
diff --git a/src/calibre/utils/formatter.py b/src/calibre/utils/formatter.py
new file mode 100644
index 0000000000..f9ef4e0846
--- /dev/null
+++ b/src/calibre/utils/formatter.py
@@ -0,0 +1,113 @@
+'''
+Created on 23 Sep 2010
+
+@author: charles
+'''
+
+import re, string
+
+def _lookup(val, mi, field_if_set, field_not_set):
+ if hasattr(mi, 'format_field'):
+ if val:
+ return mi.format_field(field_if_set.strip())[1]
+ else:
+ return mi.format_field(field_not_set.strip())[1]
+ else:
+ if val:
+ return mi.get(field_if_set.strip(), '')
+ else:
+ return mi.get(field_not_set.strip(), '')
+
+def _ifempty(val, mi, value_if_empty):
+ if val:
+ return val
+ else:
+ return value_if_empty
+
+def _shorten(val, mi, leading, center_string, trailing):
+ l = int(leading)
+ t = int(trailing)
+ if len(val) > l + len(center_string) + t:
+ return val[0:l] + center_string + val[-t:]
+ else:
+ return val
+
+class TemplateFormatter(string.Formatter):
+ '''
+ Provides a format function that substitutes '' for any missing value
+ '''
+
+ functions = {
+ 'uppercase' : (0, lambda x: x.upper()),
+ 'lowercase' : (0, lambda x: x.lower()),
+ 'titlecase' : (0, lambda x: x.title()),
+ 'capitalize' : (0, lambda x: x.capitalize()),
+ 'ifempty' : (1, _ifempty),
+ 'lookup' : (2, _lookup),
+ 'shorten' : (3, _shorten),
+ }
+
+ def get_value(self, key, args, mi):
+ raise Exception('get_value must be implemented in the subclass')
+
+ format_string_re = re.compile(r'^(.*)\|(.*)\|(.*)$')
+
+ def _explode_format_string(self, fmt):
+ try:
+ matches = self.format_string_re.match(fmt)
+ if matches is None or matches.lastindex != 3:
+ return fmt, '', ''
+ return matches.groups()
+ except:
+ import traceback
+ traceback.print_exc()
+ return fmt, '', ''
+
+ def format_field(self, val, fmt):
+ fmt, prefix, suffix = self._explode_format_string(fmt)
+
+ p = fmt.find('(')
+ if p >= 0 and fmt[-1] == ')' and fmt[0:p] in self.functions:
+ field = fmt[0:p]
+ func = self.functions[field]
+ args = fmt[p+1:-1].split(',')
+ if (func[0] == 0 and (len(args) != 1 or args[0])) or \
+ (func[0] > 0 and func[0] != len(args)):
+ raise Exception ('Incorrect number of arguments for function '+ fmt[0:p])
+ if func[0] == 0:
+ val = func[1](val, self.mi)
+ else:
+ val = func[1](val, self.mi, *args)
+ else:
+ val = string.Formatter.format_field(self, val, fmt)
+ if not val:
+ return ''
+ return prefix + val + suffix
+
+ compress_spaces = re.compile(r'\s+')
+
+ def vformat(self, fmt, args, kwargs):
+ self.mi = kwargs
+ ans = string.Formatter.vformat(self, fmt, args, kwargs)
+ return self.compress_spaces.sub(' ', ans).strip()
+
+ def safe_format(self, fmt, kwargs, error_value):
+ try:
+ ans = self.vformat(fmt, [], kwargs).strip()
+ except:
+ ans = error_value
+ return ans
+
+class ValidateFormat(TemplateFormatter):
+ '''
+ Provides a format function that substitutes '' for any missing value
+ '''
+ def get_value(self, key, args, kwargs):
+ return 'this is some text that should be long enough'
+
+ def validate(self, x):
+ return self.vformat(x, [], {})
+
+validation_formatter = ValidateFormat()
+
+
From 30c96df50546e9730ad1903ac31e54a05d09f723 Mon Sep 17 00:00:00 2001
From: Kovid Goyal zAugh*GlC`YDKco{^SvXSQwi$ 0DdusUKrIkg&IKYRAV3uX#C_to6p@@YXYaor
ze3ej%fCvE@fdLS}g<8QCE5Lz#5TtA>NP0f=P Title here ]*>`` will match that same opening tag- you'll see why after the next section. Just note that there quite frequently is more than one way to write a regular expression.
+
+Well, these special characters are very neat and all, but what if I wanted to match a dot or a question mark?
+-----------------------------------------------------------------------------------------------------------------
+
+You can of course do that: Just put a backslash in front of any special character and it is interpreted as the literal character, without any special meaning. This pair of a backslash followed by a single character is called an escape sequence, and the act of putting a backslash in front of a special character is called escaping that character. An escape sequence is interpreted as a single element. There are of course escape sequences that do more than just escaping special characters, for example ``"\t"`` means a tabulator. We'll get to some of the escape sequences later. Oh, and by the way, concerning those special characters: Consider any character we discuss in this introduction as having some function to be special and thus needing to be escaped if you want the literal character.
+
+So, what are the most useful sets?
+------------------------------------
+
+Knew you'd ask. Some useful sets are ``[0-9]`` matching a single number, ``[a-z]`` matching a single lowercase letter, ``[A-Z]`` matching a single uppercase letter, ``[a-zA-Z]`` matching a single letter and ``[a-zA-Z0-9]`` matching a single letter or number. You can also use an escape sequence as shorthand::
+
+ \d is equivalent to [0-9]
+ \w is equivalent to [a-zA-Z0-9_]
+ \s is equivalent to any whitespace
+
+.. note::
+ "Whitespace" is a term for anything that won't be printed. These characters include space, tabulator, line feed, form feed and carriage return.
+
+As a last note on sets, you can also define a set as any character *but* those in the set. You do that by including the character ``"^"`` as the *very first character in the set*. Thus, ``[^a]`` would match any character excluding "a". That's called complementing the set. Those escape sequence shorthands we saw earlier can also be complemented: ``"\D"`` means any non-number character, thus being equivalent to ``[^0-9]``. The other shorthands can be complemented by, you guessed it, using the respective uppercase letter instead of the lowercase one. So, going back to the example `` ]*>`` from the previous section, now you can see that the character set it's using tries to match any character except for a closing angle bracket.
+
+But if I had a few varying strings I wanted to match, things get complicated?
+-------------------------------------------------------------------------------
+
+Fear not, life still is good and easy. Consider this example: The book you're converting has "Title" written on every odd page and "Author" written on every even page. Looks great in print, right? But in ebooks, it's annoying. You can group whole expressions in normal parentheses, and the character ``"|"`` will let you match *either* the expression to its right *or* the one to its left. Combine those and you're done. Too fast for you? Okay, first off, we group the expressions for odd and even pages, thus getting ``(Title)(Author)`` as our two needed expressions. Now we make things simpler by using the vertical bar (``"|"`` is called the vertical bar character): If you use the expression ``(Title|Author)`` you'll either get a match for "Title" (on the odd pages) or you'd match "Author" (on the even pages). Well, wasn't that easy?
+
+You can, of course, use the vertical bar without using grouping parentheses, as well. Remember when I said that quantifiers repeat the element preceding them? Well, the vertical bar works a little differently: The expression "Title|Author" will also match either the string "Title" or the string "Author", just as the above example using grouping. *The vertical bar selects between the entire expression preceding and following it*. So, if you wanted to match the strings "Calibre" and "calibre" and wanted to select only between the upper- and lowercase "c", you'd have to use the expression ``(c|C)alibre``, where the grouping ensures that only the "c" will be selected. If you were to use ``c|Calibre``, you'd get a match on the string "c" or on the string "Calibre", which isn't what we wanted. In short: If in doubt, use grouping together with the vertical bar.
+
+You missed...
+-------------------
+
+... wait just a minute, there's one last, really neat thing you can do with groups. If you have a group that you previously matched, you can use references to that group later in the expression: Groups are numbered starting with 1, and you reference them by escaping the number of the group you want to reference, thus, the fifth group would be referenced as ``\5``. So, if you searched for ``([^ ]+) \1`` in the string "Test Test", you'd match the whole string!
+
+
+You missed something. In the beginning, you said there was a way to make a regular expression case insensitive?
+------------------------------------------------------------------------------------------------------------------
+
+Yes, I did, thanks for paying attention and reminding me. You can tell |app| how you want certain things handled by using something called flags. You include flags in your expression by using the special construct ``(?flags go here)`` where, obviously, you'd replace "flags go here" with the specific flags you want. For ignoring case, the flag is ``i``, thus you include ``(?i)`` in your expression. Thus, ``test(?i)`` would match "Test", "tEst", "TEst" and any case variation you could think of.
+
+Another useful flag lets the dot match any character at all, *including* the newline, the flag ``s``. If you want to use multiple flags in an expression, just put them in the same statement: ``(?is)`` would ignore case and make the dot match all. It doesn't matter which flag you state first, ``(?si)`` would be equivalent to the above. By the way, good places for putting flags in your expression would be either the very beginning or the very end. That way, they don't get mixed up with anything else.
+
+I think I'm beginning to understand these regular expressions now... how do I use them in |app|?
+-----------------------------------------------------------------------------------------------------
+
+Conversions
+^^^^^^^^^^^^^^
+
+Let's begin with the conversion settings, which is really neat. In the structure detection part, you can input a regexp (short for regular expression) that describes the header or footer string that will be removed during the conversion. The neat part is the wizard. Click on the wizard staff and you get a preview of what |app| "sees" during the conversion process. Scroll down to the header or footer you want to remove, select and copy it, paste it into the regexp field on top of the window. If there are variable parts, like page numbers or so, use sets and quantifiers to cover those, and while you're at it, remember to escape special characters, if there are some. Hit the button labeled :guilabel:`Test` and |app| highlights the parts it would remove were you to use the regexp. Once you're satisfied, hit OK and convert. Be careful if your conversion source has tags like this example::
+
+ Maybe, but the cops feel like you do, Anita. What's one more dead vampire?
+ New laws don't change that. Generated by ABC Amber LIT Conv
+ erter,
+ http://www.processtext.com/abclit.html It had only been two years since Addison v. Clark.
+ The court case gave us a revised version of what life was
+
+(shamelessly ripped out of `this thread ' +
_('Editing meta information for %d books') %
len(rows))
@@ -170,7 +171,7 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
self.tag_editor_button.clicked.connect(self.tag_editor)
self.autonumber_series.stateChanged[int].connect(self.auto_number_changed)
- if len(db.custom_field_keys(include_composites=False)) == 0:
+ if len(self.db.custom_field_keys(include_composites=False)) == 0:
self.central_widget.removeTab(1)
else:
self.create_custom_column_editors()
@@ -617,8 +618,15 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
self.worker = Worker(args, self.db, self.ids,
getattr(self, 'custom_column_widgets', []),
Dispatcher(bb.accept, parent=bb))
- self.worker.start()
- bb.exec_()
+
+ # The metadata backup thread causes database commits
+ # which can slow down bulk editing of large numbers of books
+ self.model.stop_metadata_backup()
+ try:
+ self.worker.start()
+ bb.exec_()
+ finally:
+ self.model.start_metadata_backup()
if self.worker.error is not None:
return error_dialog(self, _('Failed'),
diff --git a/src/calibre/gui2/library/models.py b/src/calibre/gui2/library/models.py
index b2a7f08055..9da5420681 100644
--- a/src/calibre/gui2/library/models.py
+++ b/src/calibre/gui2/library/models.py
@@ -159,17 +159,24 @@ class BooksModel(QAbstractTableModel): # {{{
# do something on the GUI thread. Deadlock.
self.cover_cache = CoverCache(db, FunctionDispatcher(self.db.cover))
self.cover_cache.start()
- if self.metadata_backup is not None:
- self.metadata_backup.stop()
- # Would like to to a join here, but the thread might be waiting to
- # do something on the GUI thread. Deadlock.
- self.metadata_backup = MetadataBackup(db)
- self.metadata_backup.start()
+ self.stop_metadata_backup()
+ self.start_metadata_backup()
def refresh_cover(event, ids):
if event == 'cover' and self.cover_cache is not None:
self.cover_cache.refresh(ids)
db.add_listener(refresh_cover)
+ def start_metadata_backup(self):
+ self.metadata_backup = MetadataBackup(self.db)
+ self.metadata_backup.start()
+
+ def stop_metadata_backup(self):
+ if getattr(self, 'metadata_backup', None) is not None:
+ self.metadata_backup.stop()
+ # Would like to to a join here, but the thread might be waiting to
+ # do something on the GUI thread. Deadlock.
+
+
def refresh_ids(self, ids, current_row=-1):
rows = self.db.refresh_ids(ids)
if rows:
diff --git a/src/calibre/gui2/preferences/misc.py b/src/calibre/gui2/preferences/misc.py
index 865115c2ed..582d110c6c 100644
--- a/src/calibre/gui2/preferences/misc.py
+++ b/src/calibre/gui2/preferences/misc.py
@@ -106,14 +106,13 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
d.exec_()
def compact(self, *args):
- from calibre.library.caches import MetadataBackup
m = self.gui.library_view.model()
- if m.metadata_backup is not None:
- m.metadata_backup.stop()
- d = CheckIntegrity(m.db, self)
- d.exec_()
- m.metadata_backup = MetadataBackup(m.db)
- m.metadata_backup.start()
+ m.stop_metadata_backup()
+ try:
+ d = CheckIntegrity(m.db, self)
+ d.exec_()
+ finally:
+ m.start_metadata_backup()
def open_config_dir(self, *args):
from calibre.utils.config import config_dir
From fef738c53b8d5a980423d1930e6a94d4ffc8a6a8 Mon Sep 17 00:00:00 2001
From: Kovid Goyal '+
+ _('Book metadata files remaining to be written: %s') % dirty_text,
+ show=True)
def switch_requested(self, location):
if not self.change_library_allowed():
diff --git a/src/calibre/gui2/dialogs/metadata_bulk.py b/src/calibre/gui2/dialogs/metadata_bulk.py
index b0ce0a1e6d..4fc85f2b30 100644
--- a/src/calibre/gui2/dialogs/metadata_bulk.py
+++ b/src/calibre/gui2/dialogs/metadata_bulk.py
@@ -3,42 +3,109 @@ __copyright__ = '2008, Kovid Goyal '+_('The template %s is invalid:')%s + \
+ ' '+_('The destination field cannot be blank'),
+ show=True)
+ return
+
if len(pb) == 0:
if self.current_format in self.current_plugboards:
fpb = self.current_plugboards[self.current_format]
diff --git a/src/calibre/gui2/preferences/plugboard.ui b/src/calibre/gui2/preferences/plugboard.ui
index 79a07be1f7..4a3192aab5 100644
--- a/src/calibre/gui2/preferences/plugboard.ui
+++ b/src/calibre/gui2/preferences/plugboard.ui
@@ -17,7 +17,12 @@
or or calibre can scan your computer for existing books automatically. These books will then be copied into the calibre library. This wizard will help you customize the scanning and import process for your existing book collection. Choose a root folder. Books will be searched for only inside this folder and any sub-folders. Make sure that the folder you chose for your calibre library is not under the root folder you choose. This wizard will help you choose an appropriate font size key for your needs. Just enter the base font size of the input document and then enter an input font size. The wizard will display what font size it will be mapped to, by the font rescaling algorithm. You can adjust the algorithm by adjusting the output base font size and font key below. When you find values suitable for you, click OK. By default, if the output base font size is zero and/or no font size key is specified, calibre will use the values from the current Output Profile. See the User Manual for a discussion of how font size rescaling works. When calibre removes inter paragraph spacing, it automatically sets a paragraph indent, to ensure that paragraphs can be easily distinguished. This option controls the width of that indent."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:135
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel_ui.py:135
msgid " em"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:136
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel_ui.py:136
msgid "Text justification:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:137
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel_ui.py:137
msgid "&Linearize tables"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:138
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel_ui.py:138
msgid "Extra &CSS"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:139
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel_ui.py:139
msgid "&Transliterate unicode characters to ASCII"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:140
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel_ui.py:140
msgid "Insert &blank line"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:141
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel_ui.py:141
msgid "Keep &ligatures"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:142
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel_ui.py:142
msgid "Smarten &punctuation"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output.py:19
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output.py:19
msgid "LRF Output"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:116
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output_ui.py:116
msgid "Enable &autorotation of wide images"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:117
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output_ui.py:117
msgid "&Wordspace:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:119
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output_ui.py:119
msgid "Minimum para. &indent:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:121
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output_ui.py:121
msgid "Render &tables as images"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:122
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output_ui.py:122
msgid "Text size multiplier for text in rendered tables:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:123
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output_ui.py:123
msgid "Add &header"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:124
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output_ui.py:124
msgid "Header &separation:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:126
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output_ui.py:126
msgid "Header &format:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:127
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output_ui.py:127
msgid "&Embed fonts"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:128
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output_ui.py:128
msgid "&Serif font family:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:129
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output_ui.py:129
msgid "S&ans-serif font family:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:130
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output_ui.py:130
msgid "&Monospaced font family:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata.py:41
-#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:114
-#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main_ui.py:200
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata.py:41
+#: /home/kovid/work/trunk/src/calibre/gui2/viewer/main.py:114
+#: /home/kovid/work/trunk/src/calibre/gui2/viewer/main_ui.py:200
msgid "Metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata.py:43
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata.py:43
msgid "Set the metadata. The output file will contain as much of this metadata as possible."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata.py:165
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:109
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata.py:165
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:109
msgid "Choose cover for "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata.py:172
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:116
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata.py:172
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:116
msgid "Cannot read"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata.py:173
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:117
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata.py:173
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:117
msgid "You do not have permission to read the file: "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata.py:181
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata.py:188
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:125
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata.py:181
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata.py:188
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:125
msgid "Error reading file"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata.py:182
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:126
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata.py:182
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:126
msgid " There was an error reading from file: Markdown is a simple markup language for text files, that allows for advanced formatting. To learn more visit markdown."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_input_ui.py:51
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/txt_input_ui.py:51
msgid "Do not insert Table of Contents into output text when using markdown"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_input_ui.py:52
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/txt_input_ui.py:52
msgid "Preserve &spaces"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output.py:16
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/txt_output.py:16
msgid "TXT Output"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output_ui.py:46
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/txt_output_ui.py:46
msgid "&Line ending style:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output_ui.py:48
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/txt_output_ui.py:48
msgid "&Maximum line length:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output_ui.py:49
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/txt_output_ui.py:49
msgid "Force maximum line length"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/xexp_edit_ui.py:56
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info_ui.py:70
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info_ui.py:71
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_format_ui.py:46
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/confirm_delete_ui.py:54
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/password_ui.py:62
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/progress_ui.py:54
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/progress_ui.py:55
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/xexp_edit_ui.py:56
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/book_info_ui.py:70
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/book_info_ui.py:71
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_format_ui.py:46
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/confirm_delete_ui.py:54
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/password_ui.py:62
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/progress_ui.py:54
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/progress_ui.py:55
msgid "TextLabel"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/xexp_edit_ui.py:57
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/xexp_edit_ui.py:57
msgid "Use a wizard to help construct the XPath expression"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:68
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:68
msgid "Match HTML &tags with tag name:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:69
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:69
msgid "*"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:70
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:70
msgid "a"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:71
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:71
msgid "br"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:72
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:72
msgid "div"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:73
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:73
msgid "h1"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:74
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:74
msgid "h2"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:75
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:75
msgid "h3"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:76
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:76
msgid "h4"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:77
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:77
msgid "h5"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:78
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:78
msgid "h6"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:79
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:79
msgid "hr"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:80
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:80
msgid "span"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:81
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:81
msgid "Having the &attribute:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:82
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:82
msgid "With &value:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:83
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:83
msgid "(A regular expression)"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:84
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:84
msgid " For example, to match all h2 tags that have class=\"chapter\", set tag to h2, attribute to class and value to chapter. Leaving attribute blank will match any attribute and leaving value blank will match any value. Setting tag to * will match any tag. To learn more advanced usage of XPath see the XPath Tutorial."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/cover_flow.py:118
+#: /home/kovid/work/trunk/src/calibre/gui2/cover_flow.py:118
msgid "Browse by covers"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/cover_flow.py:149
+#: /home/kovid/work/trunk/src/calibre/gui2/cover_flow.py:149
msgid "Cover browser could not be loaded"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:59
-#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:84
-#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:108
-#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:145
-#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:164
-#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:270
-#: /home/kovid/work/calibre/src/calibre/gui2/library/delegates.py:110
-#: /home/kovid/work/calibre/src/calibre/gui2/library/delegates.py:130
-#: /home/kovid/work/calibre/src/calibre/gui2/library/delegates.py:205
-#: /home/kovid/work/calibre/src/calibre/gui2/library/delegates.py:238
-#: /home/kovid/work/calibre/src/calibre/gui2/library/delegates.py:242
+#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:59
+#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:84
+#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:108
+#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:145
+#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:164
+#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:270
+#: /home/kovid/work/trunk/src/calibre/gui2/library/delegates.py:110
+#: /home/kovid/work/trunk/src/calibre/gui2/library/delegates.py:130
+#: /home/kovid/work/trunk/src/calibre/gui2/library/delegates.py:205
+#: /home/kovid/work/trunk/src/calibre/gui2/library/delegates.py:238
+#: /home/kovid/work/trunk/src/calibre/gui2/library/delegates.py:242
msgid "Undefined"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:59
-#: /home/kovid/work/calibre/src/calibre/library/server/mobile.py:241
-#: /home/kovid/work/calibre/src/calibre/library/server/xml.py:119
+#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:59
+#: /home/kovid/work/trunk/src/calibre/library/server/mobile.py:244
+#: /home/kovid/work/trunk/src/calibre/library/server/xml.py:122
msgid "Yes"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:59
-#: /home/kovid/work/calibre/src/calibre/library/server/mobile.py:243
-#: /home/kovid/work/calibre/src/calibre/library/server/xml.py:121
+#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:59
+#: /home/kovid/work/trunk/src/calibre/library/server/mobile.py:246
+#: /home/kovid/work/trunk/src/calibre/library/server/xml.py:124
msgid "No"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:122
+#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:122
msgid "star(s)"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:123
+#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:123
msgid "Unrated"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:156
+#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:156
msgid "Set '%s' to today"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:266
+#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:266
msgid " index:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:451
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:257
+#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:451
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:257
msgid "Automatically number books in this series"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:498
+#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:498
msgid "Remove all tags"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:519
+#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:519
msgid "tags to add"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:524
+#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:524
msgid "tags to remove"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:48
-#: /home/kovid/work/calibre/src/calibre/utils/ipc/job.py:136
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:48
+#: /home/kovid/work/trunk/src/calibre/utils/ipc/job.py:136
msgid "No details available."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:165
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:165
msgid "Device no longer connected."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:283
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:283
msgid "Get device information"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:294
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:294
msgid "Get list of books on device"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:304
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:304
msgid "Get annotations from device"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:313
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:313
msgid "Send metadata to device"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:318
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:318
msgid "Send collections to device"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:342
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:342
msgid "Upload %d books to device"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:357
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:357
msgid "Delete books from device"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:374
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:374
msgid "Download books from device"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:384
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:384
msgid "View book on device"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:418
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:418
msgid "Set default send to device action"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:424
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:424
msgid "Send to main memory"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:426
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:426
msgid "Send to storage card A"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:428
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:428
msgid "Send to storage card B"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:433
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:442
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:433
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:442
msgid "Main Memory"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:453
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:453
msgid "Send and delete from library"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:454
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:454
msgid "Send specific format"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:490
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:490
msgid "Eject device"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:608
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:608
msgid "Error communicating with device"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:629
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:629
msgid "Select folder to open as device"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:676
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:676
msgid "Error talking to device"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:677
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:677
msgid "There was a temporary error talking to the device. Please unplug and reconnect the device and or reboot."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:720
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:720
msgid "Device: "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:722
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:722
msgid " detected."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:812
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:812
msgid "selected to send"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:817
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:817
msgid "Choose format to send to device"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:826
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:826
msgid "No device"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:827
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:827
msgid "Cannot send: No device is connected"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:830
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:834
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:830
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:834
msgid "No card"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:831
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:835
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:831
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:835
msgid "Cannot send: Device has no storage card"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:876
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:876
msgid "E-book:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:879
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:879
msgid "Attached, you will find the e-book"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:880
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/plugins.py:107
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:880
+#: /home/kovid/work/trunk/src/calibre/gui2/preferences/plugins.py:107
msgid "by"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:881
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:881
msgid "in the %s format."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:894
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:894
msgid "Sending email to"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:924
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:932
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:1025
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:1087
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:1206
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:1214
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:924
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:932
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:1025
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:1087
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:1206
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:1214
msgid "No suitable formats"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:925
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:925
msgid "Auto convert the following books before sending via email?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:933
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:933
msgid "Could not email the following books as no suitable formats were found:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:951
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:951
msgid "Failed to email books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:952
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:952
msgid "Failed to email the following books:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:956
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:956
msgid "Sent by email:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:984
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:984
msgid "News:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:985
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:985
msgid "Attached is the"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:996
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:996
msgid "Sent news to"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:1026
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:1088
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:1207
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:1026
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:1088
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:1207
msgid "Auto convert the following books before uploading to the device?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:1056
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:1056
msgid "Sending catalogs to device."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:1120
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:1120
msgid "Sending news to device."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:1173
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:1173
msgid "Sending books to device."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:1215
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:1215
msgid "Could not upload the following books to the device, as no suitable formats were found. Convert the book(s) to a format supported by your device first."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:1277
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:1277
msgid "No space on device"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:1278
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:1278
msgid " Cannot upload books to device there is no more free space available "
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/configwidget_ui.py:83
+#: /home/kovid/work/trunk/src/calibre/gui2/device_drivers/configwidget_ui.py:83
msgid "Select available formats and their order for this device"
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/configwidget_ui.py:87
+#: /home/kovid/work/trunk/src/calibre/gui2/device_drivers/configwidget_ui.py:87
msgid "Use sub directories"
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/configwidget_ui.py:88
+#: /home/kovid/work/trunk/src/calibre/gui2/device_drivers/configwidget_ui.py:88
msgid "Use author sort for author"
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/configwidget_ui.py:90
+#: /home/kovid/work/trunk/src/calibre/gui2/device_drivers/configwidget_ui.py:90
msgid "Save &template:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/add_from_isbn_ui.py:48
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/add_from_isbn_ui.py:48
msgid "Add books by ISBN"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/add_from_isbn_ui.py:49
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/add_from_isbn_ui.py:49
msgid " Enter a list of ISBNs in the box to the left, one per line. calibre will automatically create entries for books based on the ISBN and download metadata and covers for them. Any invalid ISBNs in the list will be ignored."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/add_from_isbn_ui.py:50
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/add_from_isbn_ui.py:50
msgid "&Paste from clipboard"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info_ui.py:73
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/book_info_ui.py:73
msgid "Fit &cover within view"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info_ui.py:74
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/book_info_ui.py:74
msgid "&Previous"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info_ui.py:75
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/book_info_ui.py:75
msgid "&Next"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/catalog.py:38
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/catalog.py:38
msgid "My Books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/catalog_ui.py:69
-#: /home/kovid/work/calibre/src/calibre/gui2/tools.py:301
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/catalog_ui.py:69
+#: /home/kovid/work/trunk/src/calibre/gui2/tools.py:304
msgid "Generate catalog"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/catalog_ui.py:70
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/catalog_ui.py:70
msgid "Generate catalog for {0} books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/catalog_ui.py:71
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/catalog_ui.py:71
msgid "Catalog &format:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/catalog_ui.py:72
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/catalog_ui.py:72
msgid "Catalog &title (existing catalog with the same title will be replaced):"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/catalog_ui.py:73
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/catalog_ui.py:73
msgid "&Send catalog to device automatically"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/catalog_ui.py:74
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/catalog_ui.py:74
msgid "Catalog options"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_format_ui.py:45
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_format_ui.py:45
msgid "Choose Format"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library.py:38
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library.py:38
msgid "Choose location for calibre library"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library.py:45
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library.py:45
msgid "Same as current"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library.py:46
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library.py:46
msgid "The location %s contains the current calibre library"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library.py:51
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library.py:51
msgid "No existing library found"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library.py:52
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library.py:52
msgid "There is no existing calibre library at %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library.py:56
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library.py:56
msgid "Not empty"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library.py:57
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library.py:57
msgid "The folder %s is not empty. Please choose an empty folder"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library.py:80
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library.py:80
msgid "No location"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library.py:80
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library.py:80
msgid "No location selected"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library.py:84
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library.py:84
+#: /home/kovid/work/trunk/src/calibre/gui2/wizard/__init__.py:620
msgid "Bad location"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library.py:85
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library.py:85
msgid "%s is not an existing folder"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library_ui.py:71
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library_ui.py:71
msgid "Choose your calibre library"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library_ui.py:72
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library_ui.py:72
msgid "Your calibre library is currently located at {0}"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library_ui.py:73
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library_ui.py:73
msgid "New &Location:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library_ui.py:74
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library_ui.py:74
msgid "Use &existing library at the new location"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library_ui.py:75
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library_ui.py:75
msgid "&Create an empty library at the new location"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library_ui.py:76
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library_ui.py:76
msgid "&Move current library to new location"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comicconf.py:33
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/comicconf.py:33
msgid "Set defaults for conversion of comics (CBR/CBZ files)"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comicconf.py:48
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/comicconf.py:48
msgid "Set options for converting %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comicconf_ui.py:97
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/comicconf_ui.py:97
msgid "&Title:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comicconf_ui.py:98
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/comicconf_ui.py:98
msgid "&Author(s):"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comicconf_ui.py:100
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/comicconf_ui.py:100
msgid "&Profile:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comments_dialog_ui.py:41
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/comments_dialog_ui.py:41
msgid "Edit Comments"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/confirm_delete_ui.py:55
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/confirm_delete_ui.py:55
msgid "&Show this warning again"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/conversion_error_ui.py:47
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/conversion_error_ui.py:47
msgid "ERROR"
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/delete_matching_from_device.py:67
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/delete_matching_from_device.py:67
msgid "All checked books will be permanently deleted from your device. Please verify the list."
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/delete_matching_from_device.py:75
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/delete_matching_from_device.py:75
msgid "Location"
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:69
-#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:884
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/create_custom_column.py:31
-#: /home/kovid/work/calibre/src/calibre/library/server/opds.py:588
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/delete_matching_from_device.py:76
+#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:69
+#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:884
+#: /home/kovid/work/trunk/src/calibre/gui2/preferences/create_custom_column.py:31
+#: /home/kovid/work/trunk/src/calibre/library/server/opds.py:588
msgid "Date"
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:1066
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/delete_matching_from_device.py:76
+#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:1066
msgid "Format"
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/delete_matching_from_device_ui.py:50
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/delete_matching_from_device_ui.py:50
msgid "Delete from device"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/edit_authors_dialog.py:33
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/edit_authors_dialog.py:33
msgid "Author sort"
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/edit_authors_dialog_ui.py:66
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/edit_authors_dialog_ui.py:66
msgid "Manage authors"
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/edit_authors_dialog_ui.py:67
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/edit_authors_dialog_ui.py:67
msgid "Sort by author"
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/edit_authors_dialog_ui.py:68
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/edit_authors_dialog_ui.py:68
msgid "Sort by author sort"
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/edit_authors_dialog_ui.py:69
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/edit_authors_dialog_ui.py:69
msgid "Reset all the author sort values to a value automatically generated from the author. Exactly how this value is automatically generated can be controlled via Preferences->Advanced->Tweaks"
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/edit_authors_dialog_ui.py:70
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/edit_authors_dialog_ui.py:70
msgid "Recalculate all author sort values"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:60
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata.py:60
msgid "Author Sort"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:62
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata.py:62
msgid "ISBN"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:162
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata.py:162
msgid "Finding metadata..."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:176
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata.py:176
msgid "Could not find metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:177
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata.py:177
msgid "The metadata download seems to have stalled. Try again later."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:186
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata.py:186
msgid "Warning"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:187
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata.py:187
msgid "Could not fetch metadata from:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:191
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata.py:191
msgid "No metadata found"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:192
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata.py:192
msgid "No metadata found, try adjusting the title and author or the ISBN key."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata_ui.py:90
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata_ui.py:90
msgid "Fetch metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata_ui.py:91
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata_ui.py:91
msgid " calibre can find metadata for your books from two locations: Google Books and isbndb.com. To use isbndb.com you must sign up for a free account and enter your access key below."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata_ui.py:92
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata_ui.py:92
msgid "&Access Key:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata_ui.py:93
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata_ui.py:93
msgid "Fetch"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata_ui.py:94
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata_ui.py:94
msgid "Matches"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata_ui.py:95
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata_ui.py:95
msgid "Select the book that most closely matches your copy from the list below"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata_ui.py:96
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata_ui.py:96
msgid "Download &social metadata (tags/rating/etc.) for the selected book"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata_ui.py:97
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata_ui.py:97
msgid "Overwrite author and title with author and title of selected book"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/job_view_ui.py:42
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/job_view_ui.py:42
msgid "Details of job"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/jobs_ui.py:49
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/jobs_ui.py:49
msgid "Active Jobs"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/jobs_ui.py:50
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/jobs_ui.py:50
msgid "&Stop selected job"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/jobs_ui.py:51
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/jobs_ui.py:51
msgid "Show job &details"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/jobs_ui.py:52
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/jobs_ui.py:52
msgid "Stop &all non device jobs"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:107
-#: /home/kovid/work/calibre/src/calibre/gui2/widgets.py:385
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk.py:107
+#: /home/kovid/work/trunk/src/calibre/gui2/widgets.py:385
msgid "Lower Case"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:108
-#: /home/kovid/work/calibre/src/calibre/gui2/widgets.py:384
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk.py:108
+#: /home/kovid/work/trunk/src/calibre/gui2/widgets.py:384
msgid "Upper Case"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:109
-#: /home/kovid/work/calibre/src/calibre/gui2/widgets.py:387
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk.py:109
+#: /home/kovid/work/trunk/src/calibre/gui2/widgets.py:387
msgid "Title Case"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:119
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk.py:119
msgid "Editing meta information for %d books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:166
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk.py:166
msgid "Book %d:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:182
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk.py:182
msgid "Search and replace in text fields using regular expressions. The search text is an arbitrary python-compatible regular expression. The replacement text can contain backreferences to parenthesized expressions in the pattern. The search is not anchored, and can match and replace multiple times on the same string. See this reference for more information, and in particular the 'sub' function."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:192
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk.py:192
msgid "Note: you can destroy your library using this feature. Changes are permanent. There is no undo function. You are strongly encouraged to back up your library before proceeding."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:386
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk.py:386
msgid "Search/replace invalid"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:387
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk.py:387
msgid "Search pattern is invalid: %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:419
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk.py:419
msgid "Applying changes to %d books. This may take a while."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:229
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:229
msgid "Edit Meta information"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:231
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:231
msgid "A&utomatically set author sort"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:232
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:232
msgid "Author s&ort: "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:233
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:233
msgid "Specify how the author(s) of this book should be sorted. For example Charles Dickens should be sorted as Dickens, Charles."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:234
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:383
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:234
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:383
msgid "&Rating:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:235
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:236
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:384
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:385
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:235
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:236
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:384
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:385
msgid "Rating of this book. 0-5 stars"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:237
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:237
msgid "No change"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:238
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:386
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:238
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:386
msgid " stars"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:240
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:240
msgid "Add ta&gs: "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:242
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:243
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:390
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:391
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:242
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:243
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:390
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:391
msgid "Open Tag Editor"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:244
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:244
msgid "&Remove tags:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:245
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:245
msgid "Comma separated list of tags to remove from the books. "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:246
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:246
msgid "Check this box to remove all tags from the books."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:247
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:247
msgid "Remove all"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:251
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:251
msgid "Remove &format:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:252
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:252
msgid "&Swap title and author"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:253
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:253
msgid ""
"Selected books will be automatically numbered,\n"
"in the order you selected them.\n"
@@ -5621,915 +5621,915 @@ msgid ""
"Book A will have series number 1 and Book B series number 2."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:258
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:258
msgid ""
"Remove stored conversion settings for the selected books.\n"
"\n"
"Future conversion of these books will use the default settings."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:261
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:261
msgid "Remove &stored conversion settings for the selected books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:262
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:422
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:262
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:422
msgid "&Basic metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:263
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:423
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:263
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:423
msgid "&Custom metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:264
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:264
msgid "Search &field:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:265
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:265
msgid "&Search for:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:266
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:266
msgid "&Replace with:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:267
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:267
msgid "Apply function &after replace:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:268
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:268
msgid "Test &text"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:269
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:269
msgid "Test re&sult"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:270
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:270
msgid "Your test:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:271
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:271
msgid "&Search and replace (experimental)"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:91
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:91
msgid "Last modified: %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:133
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:133
msgid "Not a valid picture"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:150
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:150
msgid "Specify title and author"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:151
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:151
msgid "You must specify a title and author before generating a cover"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:169
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:169
msgid "Choose formats for "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:200
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:200
msgid "No permission"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:201
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:201
msgid "You do not have permission to read the following files:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:228
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:229
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:228
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:229
msgid "No format selected"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:240
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:240
msgid "Could not read metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:241
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:241
msgid "Could not read metadata from %s format"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:289
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:295
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:289
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:295
msgid "Could not read cover"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:290
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:290
msgid "Could not read cover from %s format"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:296
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:296
msgid "The cover in the %s format is invalid"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:351
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:351
msgid " The green color indicates that the current author sort matches the current author"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:354
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:354
msgid " The red color indicates that the current author sort does not match the current author"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:359
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:359
msgid "Abort the editing of all remaining books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:524
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:529
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:524
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:529
msgid "This ISBN number is valid"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:532
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:532
msgid "This ISBN number is invalid"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:611
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:611
msgid "Cannot use tag editor"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:612
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:612
msgid "The tags editor cannot be used if you have modified the tags"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:632
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:632
msgid "Downloading cover..."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:644
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:649
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:655
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:660
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:644
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:649
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:655
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:660
msgid "Cannot fetch cover"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:645
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:656
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:661
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:645
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:656
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:661
msgid "Could not fetch cover. Negate this match. That is, only return results that do not match this query."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_item_ui.py:39
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_item_ui.py:39
msgid "Negate"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_ui.py:118
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_ui.py:118
msgid "Advanced Search"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_ui.py:119
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_ui.py:119
msgid "Find entries that have..."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_ui.py:120
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_ui.py:120
msgid "&All these words:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_ui.py:121
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_ui.py:121
msgid "This exact &phrase:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_ui.py:122
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_ui.py:122
msgid "&One or more of these words:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_ui.py:123
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_ui.py:123
msgid "But dont show entries that have..."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_ui.py:124
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_ui.py:124
msgid "Any of these &unwanted words:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_ui.py:125
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_ui.py:125
msgid "What kind of match to use:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_ui.py:126
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_ui.py:126
msgid "Contains: the word or phrase matches anywhere in the metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_ui.py:127
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_ui.py:127
msgid "Equals: the word or phrase must match an entire metadata field"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_ui.py:128
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_ui.py:128
msgid "Regular expression: the expression must match anywhere in the metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_ui.py:129
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_ui.py:129
msgid " "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_ui.py:130
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_ui.py:130
msgid "See the User Manual for more help"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/select_formats.py:45
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/select_formats.py:45
msgid "Choose formats"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories.py:50
-#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:82
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories.py:50
+#: /home/kovid/work/trunk/src/calibre/library/field_metadata.py:82
msgid "Authors"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories.py:50
-#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:113
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories.py:50
+#: /home/kovid/work/trunk/src/calibre/library/field_metadata.py:113
msgid "Publishers"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories.py:114
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories.py:114
msgid " (not on any book)"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories.py:166
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories.py:166
msgid "The current tag category will be permanently deleted. Are you sure?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories_ui.py:158
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories_ui.py:158
msgid "User Categories Editor"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories_ui.py:159
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories_ui.py:159
msgid "A&vailable items"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories_ui.py:160
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories_ui.py:160
msgid "Apply tags to current tag category"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories_ui.py:162
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories_ui.py:162
msgid "A&pplied items"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories_ui.py:163
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories_ui.py:163
msgid "Unapply (remove) tag from current tag category"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories_ui.py:165
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories_ui.py:165
msgid "Category name: "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories_ui.py:166
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories_ui.py:166
msgid "Select a category to edit"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories_ui.py:167
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories_ui.py:167
msgid "Delete this selected tag category"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories_ui.py:169
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories_ui.py:169
msgid "Enter a new category name. Select the kind before adding it."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories_ui.py:170
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories_ui.py:170
msgid "Add the new category"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories_ui.py:172
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories_ui.py:172
msgid "Category filter: "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories_ui.py:173
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories_ui.py:173
msgid "Select the content kind of the new category"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_editor.py:68
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor.py:105
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_editor.py:68
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_list_editor.py:105
msgid "Are your sure?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_editor.py:69
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_editor.py:69
msgid "The following tags are used by one or more books. Are you certain you want to delete them?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_editor_ui.py:128
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_editor_ui.py:128
msgid "Tag Editor"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_editor_ui.py:129
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_editor_ui.py:129
msgid "A&vailable tags"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_editor_ui.py:130
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_editor_ui.py:130
msgid "Delete tag from database. This will unapply the tag from all books and then remove it from the database."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_editor_ui.py:132
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_editor_ui.py:132
msgid "Apply tag to current book"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_editor_ui.py:134
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_editor_ui.py:134
msgid "A&pplied tags"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_editor_ui.py:135
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_editor_ui.py:135
msgid "Unapply (remove) tag from current book"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_editor_ui.py:137
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_editor_ui.py:137
msgid "&Add tag:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_editor_ui.py:138
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_editor_ui.py:138
msgid "If the tag you want is not in the available list, you can add it here. Accepts a comma separated list of tags."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_editor_ui.py:139
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_editor_ui.py:139
msgid "Add tag to available tags and apply it to current book"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor.py:20
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_list_editor.py:20
msgid "%s (was %s)"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor.py:74
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:501
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_list_editor.py:74
+#: /home/kovid/work/trunk/src/calibre/gui2/tag_view.py:501
msgid "Item is blank"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor.py:75
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:502
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_list_editor.py:75
+#: /home/kovid/work/trunk/src/calibre/gui2/tag_view.py:502
msgid "An item cannot be set to nothing. Delete it instead."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor.py:91
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_list_editor.py:91
msgid "No item selected"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor.py:92
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_list_editor.py:92
msgid "You must select one item from the list of Available items."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor.py:101
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_list_editor.py:101
msgid "No items selected"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor.py:102
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_list_editor.py:102
msgid "You must select at least one items from the list."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor.py:106
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_list_editor.py:106
msgid "Are you certain you want to delete the following items?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor_ui.py:77
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_list_editor_ui.py:77
msgid "Category Editor"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor_ui.py:78
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_list_editor_ui.py:78
msgid "Items in use"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor_ui.py:79
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_list_editor_ui.py:79
msgid "Delete item from database. This will unapply the item from all books and then remove it from the database."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor_ui.py:81
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_list_editor_ui.py:81
msgid "Rename the item in every book where it is used."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor_ui.py:83
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/toolbar_ui.py:106
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_list_editor_ui.py:83
+#: /home/kovid/work/trunk/src/calibre/gui2/preferences/toolbar_ui.py:106
msgid "Ctrl+S"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/test_email_ui.py:56
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/test_email_ui.py:56
msgid "Test email settings"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/test_email_ui.py:57
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/test_email_ui.py:57
msgid "Send test mail from %s to:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/test_email_ui.py:58
-#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:120
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/test_email_ui.py:58
+#: /home/kovid/work/trunk/src/calibre/gui2/filename_pattern_ui.py:120
msgid "&Test"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tweak_epub_ui.py:55
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tweak_epub_ui.py:55
msgid "Display contents of exploded ePub"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tweak_epub_ui.py:56
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tweak_epub_ui.py:56
msgid "&Explode ePub"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tweak_epub_ui.py:57
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tweak_epub_ui.py:57
msgid "Rebuild ePub from exploded contents"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tweak_epub_ui.py:58
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tweak_epub_ui.py:58
msgid "&Rebuild ePub"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tweak_epub_ui.py:59
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tweak_epub_ui.py:59
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:218
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tweak_epub_ui.py:60
+#: /home/kovid/work/trunk/src/calibre/gui2/preferences/main.py:218
msgid "&Cancel"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tweak_epub_ui.py:61
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tweak_epub_ui.py:61
msgid "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. Rebuild the ePub, updating your calibre library."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:127
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:127
msgid "No recipe selected"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:132
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:132
msgid "The attached file: %s is a recipe to download %s."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:133
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:133
msgid "Recipe for "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:150
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:161
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles_ui.py:260
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:150
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:161
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles_ui.py:260
msgid "Switch to Advanced mode"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:156
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:164
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:156
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:164
msgid "Switch to Basic mode"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:174
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:174
msgid "Feed must have a title"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:175
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:175
msgid "The feed must have a title"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:179
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:179
msgid "Feed must have a URL"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:180
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:180
msgid "The feed %s must have a URL"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:186
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:186
msgid "This feed has already been added to the recipe"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:227
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:236
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:286
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:227
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:236
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:286
msgid "Invalid input"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:228
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:237
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:287
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:228
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:237
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:287
msgid " Could not create recipe. Error:
'+str(err), show=True)
+# return False
+# return True
def save_settings(self, config, name):
val = unicode(self.opt_template.text())
config.set(name, val)
self.opt_template.save_history(self.option_name+'_template_history')
-
-
-
-
diff --git a/src/calibre/gui2/library/models.py b/src/calibre/gui2/library/models.py
index 89008735fe..fdf21ecc23 100644
--- a/src/calibre/gui2/library/models.py
+++ b/src/calibre/gui2/library/models.py
@@ -372,7 +372,6 @@ class BooksModel(QAbstractTableModel): # {{{
return ans
def get_metadata(self, rows, rows_are_ids=False, full_metadata=False):
- # Should this add the custom columns? It doesn't at the moment
metadata, _full_metadata = [], []
if not rows_are_ids:
rows = [self.db.id(row.row()) for row in rows]
@@ -1053,7 +1052,7 @@ class DeviceBooksModel(BooksModel): # {{{
if hasattr(cdata, 'image_path'):
img.load(cdata.image_path)
else:
- img.loadFromData(cdata)
+ img.loadFromData(cdata[2])
if img.isNull():
img = self.default_image
data['cover'] = img
diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py
index ef74188bdf..9f21fe0eda 100644
--- a/src/calibre/library/database2.py
+++ b/src/calibre/library/database2.py
@@ -509,15 +509,15 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
'''
Convenience method to return metadata as a L{MetaInformation} object.
'''
- aum = self.authors(idx, index_is_id=index_is_id)
- if aum: aum = [a.strip().replace('|', ',') for a in aum.split(',')]
+ aut_list = self.authors_with_sort_strings(idx, index_is_id=index_is_id)
+ aum = []
+ aus = {}
+ for (author, author_sort) in aut_list:
+ aum.append(author)
+ aus[author] = author_sort
mi = MetaInformation(self.title(idx, index_is_id=index_is_id), aum)
mi.author_sort = self.author_sort(idx, index_is_id=index_is_id)
- if mi.authors:
- mi.author_sort_map = {}
- for name, sort in zip(mi.authors, self.authors_sort_strings(idx,
- index_is_id)):
- mi.author_sort_map[name] = sort
+ mi.author_sort_map = aus
mi.comments = self.comments(idx, index_is_id=index_is_id)
mi.publisher = self.publisher(idx, index_is_id=index_is_id)
mi.timestamp = self.timestamp(idx, index_is_id=index_is_id)
@@ -534,6 +534,10 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
mi.isbn = self.isbn(idx, index_is_id=index_is_id)
id = idx if index_is_id else self.id(idx)
mi.application_id = id
+ for key,meta in self.field_metadata.iteritems():
+ if meta['is_custom']:
+ mi.set_user_metadata(key, meta)
+ mi.set(key, self.get_custom(idx, label=meta['label'], index_is_id=index_is_id))
if get_cover:
mi.cover = self.cover(id, index_is_id=True, as_path=True)
return mi
@@ -1049,6 +1053,19 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
result.append(sort)
return result
+ # Given a book, return the map of author sort strings for the book's authors
+ def authors_with_sort_strings(self, id, index_is_id=False):
+ id = id if index_is_id else self.id(id)
+ aut_strings = self.conn.get('''
+ SELECT authors.name, authors.sort
+ FROM authors, books_authors_link as bl
+ WHERE bl.book=? and authors.id=bl.author
+ ORDER BY bl.id''', (id,))
+ result = []
+ for (author, sort,) in aut_strings:
+ result.append((author.replace('|', ','), sort))
+ return result
+
# Given a book, return the author_sort string for authors of the book
def author_sort_from_book(self, id, index_is_id=False):
auts = self.authors_sort_strings(id, index_is_id)
diff --git a/src/calibre/library/save_to_disk.py b/src/calibre/library/save_to_disk.py
index 15020855f7..258ea7ba9e 100644
--- a/src/calibre/library/save_to_disk.py
+++ b/src/calibre/library/save_to_disk.py
@@ -105,6 +105,8 @@ def safe_format(x, format_args):
pass
except AttributeError: # Thrown if user used a non existing attribute
pass
+ except KeyError: # Thrown if user used custom field w/value None
+ pass
return ''
def get_components(template, mi, id, timefmt='%b %Y', length=250,
@@ -113,13 +115,12 @@ def get_components(template, mi, id, timefmt='%b %Y', length=250,
library_order = tweaks['save_template_title_series_sorting'] == 'library_order'
tsfmt = title_sort if library_order else lambda x: x
format_args = dict(**FORMAT_ARGS)
+ format_args.update(mi.all_attributes)
if mi.title:
format_args['title'] = tsfmt(mi.title)
if mi.authors:
format_args['authors'] = mi.format_authors()
format_args['author'] = format_args['authors']
- if mi.author_sort:
- format_args['author_sort'] = mi.author_sort
if mi.tags:
format_args['tags'] = mi.format_tags()
if format_args['tags'].startswith('/'):
@@ -132,15 +133,21 @@ 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()
- if mi.isbn:
- format_args['isbn'] = mi.isbn
- if mi.publisher:
- format_args['publisher'] = mi.publisher
if hasattr(mi.timestamp, 'timetuple'):
format_args['timestamp'] = strftime(timefmt, mi.timestamp.timetuple())
if hasattr(mi.pubdate, 'timetuple'):
format_args['pubdate'] = strftime(timefmt, mi.pubdate.timetuple())
format_args['id'] = str(id)
+
+ # These are not necessary any more. The values are set by
+ # 'format_args.update' above, and there is no special formatting
+# if mi.author_sort:
+# format_args['author_sort'] = mi.author_sort
+# if mi.isbn:
+# format_args['isbn'] = mi.isbn
+# if mi.publisher:
+# format_args['publisher'] = mi.publisher
+
components = [x.strip() for x in template.split('/') if x.strip()]
components = [safe_format(x, format_args) for x in components]
components = [sanitize_func(x) for x in components if x]
From b04faf70c2378c3569a4d1cf010da3d57a707c42 Mon Sep 17 00:00:00 2001
From: Charles Haley <>
Date: Fri, 27 Aug 2010 08:22:08 +0100
Subject: [PATCH 002/235] Make Kobo driver use new metadata framework
---
src/calibre/devices/kobo/books.py | 80 ++----------------------------
src/calibre/devices/kobo/driver.py | 2 +-
2 files changed, 5 insertions(+), 77 deletions(-)
diff --git a/src/calibre/devices/kobo/books.py b/src/calibre/devices/kobo/books.py
index f0cf7c3763..1c3d05ea12 100644
--- a/src/calibre/devices/kobo/books.py
+++ b/src/calibre/devices/kobo/books.py
@@ -4,37 +4,15 @@ __copyright__ = '2010, Timothy Legge '%x
- # CUSTFIELD: What to do about custom fields
+ # TODO: NEWMETA: What to do about custom fields
return u'%s %s %s
'%u'\n'.join(ans)
def __str__(self):
From 11f7bd06a82a0b1d03afffd374344593dfb0c5dc Mon Sep 17 00:00:00 2001
From: Charles Haley <>
Date: Mon, 30 Aug 2010 17:47:25 +0100
Subject: [PATCH 007/235] Format custom fields in save_to_disk.
---
src/calibre/library/save_to_disk.py | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/src/calibre/library/save_to_disk.py b/src/calibre/library/save_to_disk.py
index 963afd4085..2bc71cde9c 100644
--- a/src/calibre/library/save_to_disk.py
+++ b/src/calibre/library/save_to_disk.py
@@ -14,6 +14,7 @@ from calibre.utils.filenames import shorten_components_to, supports_long_names,
from calibre.ebooks.metadata.opf2 import metadata_to_opf
from calibre.ebooks.metadata.meta import set_metadata
from calibre.constants import preferred_encoding, filesystem_encoding
+from calibre.ebooks.metadata import fmt_sidx
from calibre.ebooks.metadata import title_sort
from calibre import strftime
@@ -131,8 +132,6 @@ def get_components(template, mi, id, timefmt='%b %Y', length=250,
format_args['series_index'] = mi.format_series_index()
else:
template = re.sub(r'\{series_index[^}]*?\}', '', template)
- ## TODO: NEWMETA: format custom values. Check all the datatypes.
-
if mi.rating is not None:
format_args['rating'] = mi.format_rating()
if hasattr(mi.timestamp, 'timetuple'):
@@ -140,6 +139,19 @@ def get_components(template, mi, id, timefmt='%b %Y', length=250,
if hasattr(mi.pubdate, 'timetuple'):
format_args['pubdate'] = strftime(timefmt, mi.pubdate.timetuple())
format_args['id'] = str(id)
+ # Now format the custom fields
+ custom_metadata = mi.get_all_user_metadata(make_copy=False)
+ for key in custom_metadata:
+ if key in format_args:
+ ## TODO: NEWMETA: should ratings be divided by 2? The standard rating isn't...
+ if custom_metadata[key]['datatype'] == 'series':
+ format_args[key] = tsfmt(format_args[key])
+ if key+'_index' in format_args:
+ format_args[key+'_index'] = fmt_sidx(format_args[key+'_index'])
+ elif custom_metadata[key]['datatype'] == 'datetime':
+ format_args[key] = strftime(timefmt, format_args[key].timetuple())
+ elif custom_metadata[key]['datatype'] == 'bool':
+ format_args[key] = _('yes') if format_args[key] else _('no')
components = [x.strip() for x in template.split('/') if x.strip()]
components = [safe_format(x, format_args) for x in components]
From 16e5b2f3b0204efefe1c73531c4ce98376342fc7 Mon Sep 17 00:00:00 2001
From: Charles Haley <>
Date: Wed, 1 Sep 2010 16:44:12 +0100
Subject: [PATCH 008/235] Add code for Sony collections
---
resources/default_tweaks.py | 32 ++++++-
src/calibre/devices/usbms/books.py | 95 ++++++++++++++------
src/calibre/ebooks/metadata/book/__init__.py | 2 +-
src/calibre/ebooks/metadata/book/base.py | 17 ++--
4 files changed, 111 insertions(+), 35 deletions(-)
diff --git a/resources/default_tweaks.py b/resources/default_tweaks.py
index e03b0680be..e68096ecd5 100644
--- a/resources/default_tweaks.py
+++ b/resources/default_tweaks.py
@@ -90,4 +90,34 @@ save_template_title_series_sorting = 'library_order'
# Examples:
# auto_connect_to_folder = 'C:\\Users\\someone\\Desktop\\testlib'
# auto_connect_to_folder = '/home/dropbox/My Dropbox/someone/library'
-auto_connect_to_folder = ''
\ No newline at end of file
+auto_connect_to_folder = ''
+
+# Specify renaming rules for sony collections. Collections on Sonys are named
+# depending upon whether the field is standard or custom. A collection derived
+# from a standard field is named for the value in that field. For example, if
+# the standard 'series' column contains the name 'Darkover', then the series
+# will be named 'Darkover'. A collection derived from a custom field will have
+# the name of the field added to the value. For example, if a custom series
+# column named 'My Series' contains the name 'Darkover', then the collection
+# will be named 'Darkover (My Series)'. If two books have fields that generate
+# the same collection name, then both books will be in that collection. This
+# tweak lets you specify for a standard or custom field the value to be put
+# inside the parentheses. You can use it to add a parenthetical description to a
+# standard field, for example 'Foo (Tag)' instead of the 'Foo'. You can also use
+# it to force multiple fields to end up in the same collection. For example, you
+# could force the values in 'series', '#my_series_1', and '#my_series_2' to
+# appear in collections named 'some_value (Series)', thereby merging all of the
+# fields into one set of collections. The syntax of this tweak is
+# {'field_lookup_name':'name_to_use', 'lookup_name':'name', ...}
+# Example 1: I want three series columns to be merged into one set of
+# collections. If the column lookup names are 'series', '#series_1' and
+# '#series_2', and if I want nothing in the parenthesis, then the value to use
+# in the tweak value would be:
+# sony_collection_renaming_rules={'series':'', '#series_1':'', '#series_2':''}
+# Example 2: I want the word '(Series)' to appear on collections made from
+# series, and the word '(Tag)' to appear on collections made from tags. Use:
+# sony_collection_renaming_rules={'series':'Series', 'tags':'Tag'}
+# Example 3: I want 'series' and '#myseries' to be merged, and for the
+# collection name to have '(Series)' appended. The renaming rule is:
+# sony_collection_renaming_rules={'series':'Series', '#myseries':'Series'}
+sony_collection_renaming_rules={}
\ No newline at end of file
diff --git a/src/calibre/devices/usbms/books.py b/src/calibre/devices/usbms/books.py
index 0efa507e09..3e13527bd0 100644
--- a/src/calibre/devices/usbms/books.py
+++ b/src/calibre/devices/usbms/books.py
@@ -9,9 +9,10 @@ import os, re, time, sys
from calibre.ebooks.metadata.book.base import Metadata
from calibre.devices.mime import mime_type_ext
from calibre.devices.interface import BookList as _BookList
-from calibre.constants import filesystem_encoding, preferred_encoding
+from calibre.constants import preferred_encoding
from calibre import isbytestring
-from calibre.utils.config import prefs
+from calibre.utils.config import prefs, tweaks
+from calibre.utils.date import format_date
class Book(Metadata):
def __init__(self, prefix, lpath, size=None, other=None):
@@ -94,11 +95,38 @@ class CollectionsBookList(BookList):
def supports_collections(self):
return True
+ def compute_category_name(self, attr, category, cust_field_meta):
+ renames = tweaks['sony_collection_renaming_rules']
+ attr_name = renames.get(attr, None)
+ if attr_name is None:
+ if attr in cust_field_meta:
+ attr_name = '(%s)'%cust_field_meta[attr]['name']
+ else:
+ attr_name = ''
+ elif attr_name != '':
+ attr_name = '(%s)'%attr_name
+
+ if attr not in cust_field_meta:
+ cat_name = '%s %s'%(category, attr_name)
+ else:
+ fm = cust_field_meta[attr]
+ if fm['datatype'] == 'bool':
+ if category:
+ cat_name = '%s %s'%(_('Yes'), attr_name)
+ else:
+ cat_name = '%s %s'%(_('No'), attr_name)
+ elif fm['datatype'] == 'datetime':
+ cat_name = '%s %s'%(format_date(category,
+ fm['display'].get('date_format','dd MMM yyyy')), attr_name)
+ else:
+ cat_name = '%s %s'%(category, attr_name)
+ return cat_name.strip()
+
def get_collections(self, collection_attributes):
from calibre.devices.usbms.driver import debug_print
debug_print('Starting get_collections:', prefs['manage_device_metadata'])
+ debug_print('Renaming rules:', tweaks['sony_collection_renaming_rules'])
collections = {}
- series_categories = set([])
# This map of sets is used to avoid linear searches when testing for
# book equality
collections_lpaths = {}
@@ -124,42 +152,55 @@ class CollectionsBookList(BookList):
# For existing books, modify the collections only if the user
# specified 'on_connect'
attrs = collection_attributes
+ meta_vals = book.get_all_non_none_attributes()
+ cust_field_meta = book.get_all_user_metadata(make_copy=False)
for attr in attrs:
attr = attr.strip()
- val = getattr(book, attr, None)
+ val = meta_vals.get(attr, None)
if not val: continue
if isbytestring(val):
val = val.decode(preferred_encoding, 'replace')
if isinstance(val, (list, tuple)):
val = list(val)
- elif isinstance(val, unicode):
+ else:
val = [val]
for category in val:
- # TODO: NEWMETA: format the custom fields
- if attr == 'tags' and len(category) > 1 and \
- category[0] == '[' and category[-1] == ']':
+ is_series = False
+ if attr in cust_field_meta: # is a custom field
+ fm = cust_field_meta[attr]
+ if fm['datatype'] == 'text' and len(category) > 1 and \
+ category[0] == '[' and category[-1] == ']':
+ continue
+ if fm['datatype'] == 'series':
+ is_series = True
+ else: # is a standard field
+ if attr == 'tags' and len(category) > 1 and \
+ category[0] == '[' and category[-1] == ']':
+ continue
+ if attr == 'series' or \
+ ('series' in collection_attributes and
+ meta_vals.get('series', None) == category):
+ is_series = True
+ cat_name = self.compute_category_name(attr, category,
+ cust_field_meta)
+ if cat_name not in collections:
+ collections[cat_name] = []
+ collections_lpaths[cat_name] = set()
+ if lpath in collections_lpaths[cat_name]:
continue
- if category not in collections:
- collections[category] = []
- collections_lpaths[category] = set()
- if lpath not in collections_lpaths[category]:
- collections_lpaths[category].add(lpath)
- collections[category].append(book)
- if attr == 'series' or \
- ('series' in collection_attributes and
- getattr(book, 'series', None) == category):
- series_categories.add(category)
+ collections_lpaths[cat_name].add(lpath)
+ if is_series:
+ collections[cat_name].append(
+ (book, meta_vals.get(attr+'_index', sys.maxint)))
+ else:
+ collections[cat_name].append(
+ (book, meta_vals.get('title_sort', 'zzzz')))
# Sort collections
+ result = {}
for category, books in collections.items():
- def tgetter(x):
- return getattr(x, 'title_sort', 'zzzz')
- books.sort(cmp=lambda x,y:cmp(tgetter(x), tgetter(y)))
- if category in series_categories:
- # Ensures books are sub sorted by title
- def getter(x):
- return getattr(x, 'series_index', sys.maxint)
- books.sort(cmp=lambda x,y:cmp(getter(x), getter(y)))
- return collections
+ books.sort(cmp=lambda x,y:cmp(x[1], y[1]))
+ result[category] = [x[0] for x in books]
+ return result
def rebuild_collections(self, booklist, oncard):
'''
diff --git a/src/calibre/ebooks/metadata/book/__init__.py b/src/calibre/ebooks/metadata/book/__init__.py
index 47eb616394..ca7f4f7074 100644
--- a/src/calibre/ebooks/metadata/book/__init__.py
+++ b/src/calibre/ebooks/metadata/book/__init__.py
@@ -109,7 +109,7 @@ COPYABLE_METADATA_FIELDS = SOCIAL_METADATA_FIELDS.union(
CALIBRE_METADATA_FIELDS) - \
frozenset(['title', 'title_sort', 'authors',
'author_sort', 'author_sort_map' 'comments',
- 'cover_data', 'tags', 'language'])
+ 'cover_data', 'tags', 'language', 'lpath'])
SERIALIZABLE_FIELDS = SOCIAL_METADATA_FIELDS.union(
USER_METADATA_FIELDS).union(
diff --git a/src/calibre/ebooks/metadata/book/base.py b/src/calibre/ebooks/metadata/book/base.py
index dcb31c3ecc..3f5507d676 100644
--- a/src/calibre/ebooks/metadata/book/base.py
+++ b/src/calibre/ebooks/metadata/book/base.py
@@ -117,16 +117,18 @@ class Metadata(object):
res[k] = copy.deepcopy(user_metadata[k])
return res
- def get_user_metadata(self, field):
+ def get_user_metadata(self, field, make_copy):
'''
return field metadata from the object if it is there. Otherwise return
- None. field is the key name, not the label. Return a copy, just in case
- the user wants to change values in the dict (json does).
+ None. field is the key name, not the label. Return a copy if requested,
+ just in case the user wants to change values in the dict.
'''
_data = object.__getattribute__(self, '_data')
_data = _data['user_metadata']
if field in _data:
- return copy.deepcopy(_data[field])
+ if make_copy:
+ return copy.deepcopy(_data[field])
+ return _data[field]
return None
@classmethod
@@ -189,7 +191,7 @@ class Metadata(object):
for x in STANDARD_METADATA_FIELDS:
prints('%s:'%x, getattr(self, x, 'None'))
for x in self.user_metadata_keys:
- meta = self.get_user_metadata(x)
+ meta = self.get_user_metadata(x, make_copy=False)
if meta is not None:
prints(x, meta)
prints('--------------')
@@ -220,6 +222,9 @@ class Metadata(object):
self.set_all_user_metadata(other.get_all_user_metadata(make_copy=True))
self.comments = getattr(other, 'comments', '')
self.language = getattr(other, 'language', None)
+ lpath = getattr(other, 'lpath', None)
+ if lpath is not None:
+ self.lpath = lpath
else:
for attr in COPYABLE_METADATA_FIELDS:
if hasattr(other, attr):
@@ -240,7 +245,7 @@ class Metadata(object):
if getattr(other, 'user_metadata_keys', None):
for x in other.user_metadata_keys:
- meta = other.get_user_metadata(x)
+ meta = other.get_user_metadata(x, make_copy=True)
if meta is not None:
self.set_user_metadata(x, meta) # get... did the deepcopy
From 0606afc8ff6edb0dfb6042bbc6cde3f891a068e9 Mon Sep 17 00:00:00 2001
From: Charles Haley <>
Date: Thu, 2 Sep 2010 13:19:01 +0100
Subject: [PATCH 009/235] 1) make to_html support custom fields 2) clean up the
_extra code 3) add a format_custom_field method to avoid duplicating code 4)
pass custom metadata to book_details
---
src/calibre/ebooks/metadata/book/base.py | 43 ++++++++++++++++++------
src/calibre/gui2/book_details.py | 2 ++
src/calibre/gui2/library/models.py | 6 +++-
src/calibre/library/database2.py | 4 +--
4 files changed, 42 insertions(+), 13 deletions(-)
diff --git a/src/calibre/ebooks/metadata/book/base.py b/src/calibre/ebooks/metadata/book/base.py
index 3f5507d676..caaaccb3d0 100644
--- a/src/calibre/ebooks/metadata/book/base.py
+++ b/src/calibre/ebooks/metadata/book/base.py
@@ -12,7 +12,8 @@ from calibre import prints
from calibre.ebooks.metadata.book import COPYABLE_METADATA_FIELDS
from calibre.ebooks.metadata.book import STANDARD_METADATA_FIELDS
from calibre.ebooks.metadata.book import TOP_LEVEL_CLASSIFIERS
-from calibre.utils.date import isoformat
+from calibre.utils.date import isoformat, format_date
+
NULL_VALUES = {
@@ -94,6 +95,13 @@ class Metadata(object):
return default
return self.__getattribute__(field)
+ def get_extra(self, field):
+ _data = object.__getattribute__(self, '_data')
+ if field in _data['user_metadata'].iterkeys():
+ return _data['user_metadata'][field]['#extra#']
+ raise AttributeError(
+ 'Metadata object has no attribute named: '+ repr(field))
+
def set(self, field, val, extra=None):
self.__setattr__(field, val, extra)
@@ -131,14 +139,6 @@ class Metadata(object):
return _data[field]
return None
- @classmethod
- def get_user_metadata_value(user_mi):
- return user_mi['#value#']
-
- @classmethod
- def get_user_metadata_extra(user_mi):
- return user_mi['#extra#']
-
def set_all_user_metadata(self, metadata):
'''
store custom field metadata into the object. Field is the key name
@@ -284,6 +284,25 @@ class Metadata(object):
def format_rating(self):
return unicode(self.rating)
+ def format_custom_field(self, key):
+ '''
+ returns the tuple (field_name, formatted_value)
+ '''
+ cmeta = self.get_user_metadata(key, make_copy=False)
+ name = unicode(cmeta['name'])
+ res = self.get(key, None)
+ if res is not None:
+ datatype = cmeta['datatype']
+ if datatype == 'text' and cmeta['is_multiple']:
+ res = u', '.join(res)
+ elif datatype == 'series':
+ res = res + ' [%s]'%self.format_series_index(self.get_extra(key))
+ elif datatype == 'datetime':
+ res = format_date(res, cmeta['display'].get('date_format','dd MMM yyyy'))
+ elif datatype == 'bool':
+ res = _('Yes') if res else _('No')
+ return (name, unicode(res))
+
def __unicode__(self):
from calibre.ebooks.metadata import authors_to_string
ans = []
@@ -339,9 +358,13 @@ class Metadata(object):
ans += [(_('Published'), unicode(self.pubdate.isoformat(' ')))]
if self.rights is not None:
ans += [(_('Rights'), unicode(self.rights))]
+ for key in self.user_metadata_keys:
+ val = self.get(key, None)
+ if val is not None:
+ (name, val) = self.format_custom_field(key)
+ ans += [(name, val)]
for i, x in enumerate(ans):
ans[i] = u' '%x
- # TODO: NEWMETA: What to do about custom fields
return u'%s %s %s
'%u'\n'.join(ans)
def __str__(self):
diff --git a/src/calibre/gui2/book_details.py b/src/calibre/gui2/book_details.py
index f08dd09429..4e11e0c84f 100644
--- a/src/calibre/gui2/book_details.py
+++ b/src/calibre/gui2/book_details.py
@@ -28,6 +28,8 @@ WEIGHTS[_('Tags')] = 4
def render_rows(data):
keys = data.keys()
+ # First sort by name. The WEIGHTS sort will preserve this sub-order
+ keys.sort(cmp=lambda x, y: cmp(x.lower(), y.lower()))
keys.sort(cmp=lambda x, y: cmp(WEIGHTS[x], WEIGHTS[y]))
rows = []
for key in keys:
diff --git a/src/calibre/gui2/library/models.py b/src/calibre/gui2/library/models.py
index fdf21ecc23..2711756856 100644
--- a/src/calibre/gui2/library/models.py
+++ b/src/calibre/gui2/library/models.py
@@ -323,7 +323,11 @@ class BooksModel(QAbstractTableModel): # {{{
data[_('Series')] = \
_('Book %s of %s.')%\
(sidx, prepare_string_for_xml(series))
-
+ mi = self.db.get_metadata(idx)
+ for key in mi.user_metadata_keys:
+ name, val = mi.format_custom_field(key)
+ if val is not None:
+ data[name] = val
return data
def set_cache(self, idx):
diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py
index 6457e12905..bb6d72bcff 100644
--- a/src/calibre/library/database2.py
+++ b/src/calibre/library/database2.py
@@ -1052,8 +1052,8 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
if key in self.field_metadata and \
user_mi[key]['datatype'] == self.field_metadata[key]['datatype']:
doit(self.set_custom, id,
- val=Metadata.get_user_metadata_value(user_mi[key]),
- extra=Metadata.get_user_metadata_extra(user_mi[key]),
+ val=mi.get(key),
+ extra=mi.get_extra(key),
label=user_mi[key]['label'])
self.notify('metadata', [id])
From 7ff7da0fbb2485301142a6ba2e6c04923a6d4a59 Mon Sep 17 00:00:00 2001
From: Charles Haley <>
Date: Fri, 3 Sep 2010 18:43:17 +0100
Subject: [PATCH 010/235] Remove relative import
---
src/calibre/ebooks/metadata/book/json_codec.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/calibre/ebooks/metadata/book/json_codec.py b/src/calibre/ebooks/metadata/book/json_codec.py
index 7a80e16854..96178c4a63 100644
--- a/src/calibre/ebooks/metadata/book/json_codec.py
+++ b/src/calibre/ebooks/metadata/book/json_codec.py
@@ -9,7 +9,7 @@ import json
import traceback
from PIL import Image
-from . import SERIALIZABLE_FIELDS
+from calibre.ebooks.metadata.book import SERIALIZABLE_FIELDS
from calibre.constants import filesystem_encoding, preferred_encoding
from calibre.library.field_metadata import FieldMetadata
from calibre.utils.date import parse_date, isoformat, UNDEFINED_DATE
From 0ba513e2879b5e476d4787b333fb82b8dbe2e914 Mon Sep 17 00:00:00 2001
From: Charles Haley <>
Date: Sun, 5 Sep 2010 11:01:55 +0100
Subject: [PATCH 011/235] Add a comment about not using the Metadata class, and
why
---
src/calibre/library/server/mobile.py | 4 ++++
src/calibre/library/server/xml.py | 7 ++++---
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/src/calibre/library/server/mobile.py b/src/calibre/library/server/mobile.py
index 229e0c21c4..6e08581aed 100644
--- a/src/calibre/library/server/mobile.py
+++ b/src/calibre/library/server/mobile.py
@@ -199,6 +199,10 @@ class MobileServer(object):
CKEYS = [key for key in sorted(CFM.get_custom_fields(),
cmp=lambda x,y: cmp(CFM[x]['name'].lower(),
CFM[y]['name'].lower()))]
+ # This method uses its own book dict, not the Metadata dict. The loop
+ # below could be changed to use db.get_metadata instead of reading
+ # info directly from the record made by the view, but it doesn't seem
+ # worth it at the moment.
books = []
for record in items[(start-1):(start-1)+num]:
book = {'formats':record[FM['formats']], 'size':record[FM['size']]}
diff --git a/src/calibre/library/server/xml.py b/src/calibre/library/server/xml.py
index ed8479980e..5bf2783f96 100644
--- a/src/calibre/library/server/xml.py
+++ b/src/calibre/library/server/xml.py
@@ -66,6 +66,10 @@ class XMLServer(object):
return x.decode(preferred_encoding, 'replace')
return unicode(x)
+ # This method uses its own book dict, not the Metadata dict. The loop
+ # below could be changed to use db.get_metadata instead of reading
+ # info directly from the record made by the view, but it doesn't seem
+ # worth it at the moment.
for record in items[start:start+num]:
kwargs = {}
aus = record[FM['authors']] if record[FM['authors']] else __builtin__._('Unknown')
@@ -138,6 +142,3 @@ class XMLServer(object):
return etree.tostring(ans, encoding='utf-8', pretty_print=True,
xml_declaration=True)
-
-
-
From 38c6199c7b54b243d039aba25cad86125326a582 Mon Sep 17 00:00:00 2001
From: Charles Haley <>
Date: Sun, 5 Sep 2010 11:06:54 +0100
Subject: [PATCH 012/235] Change some comments from 'class:MetaInformation' to
'class:Metadata'
---
src/calibre/customize/__init__.py | 4 ++--
src/calibre/devices/apple/driver.py | 2 +-
src/calibre/ebooks/metadata/epub.py | 2 +-
src/calibre/ebooks/metadata/fetch.py | 2 +-
4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/calibre/customize/__init__.py b/src/calibre/customize/__init__.py
index 27e319de14..8ddc791b2f 100644
--- a/src/calibre/customize/__init__.py
+++ b/src/calibre/customize/__init__.py
@@ -218,7 +218,7 @@ class MetadataReaderPlugin(Plugin): # {{{
with the input data.
:param type: The type of file. Guaranteed to be one of the entries
in :attr:`file_types`.
- :return: A :class:`calibre.ebooks.metadata.MetaInformation` object
+ :return: A :class:`calibre.ebooks.metadata.book.Metadata` object
'''
return None
# }}}
@@ -248,7 +248,7 @@ class MetadataWriterPlugin(Plugin): # {{{
with the input data.
:param type: The type of file. Guaranteed to be one of the entries
in :attr:`file_types`.
- :param mi: A :class:`calibre.ebooks.metadata.MetaInformation` object
+ :param mi: A :class:`calibre.ebooks.metadata.book.Metadata` object
'''
pass
diff --git a/src/calibre/devices/apple/driver.py b/src/calibre/devices/apple/driver.py
index 75517e9df7..94aea1e79d 100644
--- a/src/calibre/devices/apple/driver.py
+++ b/src/calibre/devices/apple/driver.py
@@ -872,7 +872,7 @@ class ITUNES(DriverBase):
once uploaded to the device. len(names) == len(files)
:return: A list of 3-element tuples. The list is meant to be passed
to L{add_books_to_metadata}.
- :metadata: If not None, it is a list of :class:`MetaInformation` objects.
+ :metadata: If not None, it is a list of :class:`Metadata` objects.
The idea is to use the metadata to determine where on the device to
put the book. len(metadata) == len(files). Apart from the regular
cover (path to cover), there may also be a thumbnail attribute, which should
diff --git a/src/calibre/ebooks/metadata/epub.py b/src/calibre/ebooks/metadata/epub.py
index 041a1ee603..ac6b5feebe 100644
--- a/src/calibre/ebooks/metadata/epub.py
+++ b/src/calibre/ebooks/metadata/epub.py
@@ -164,7 +164,7 @@ def get_cover(opf, opf_path, stream, reader=None):
return render_html_svg_workaround(cpage, default_log)
def get_metadata(stream, extract_cover=True):
- """ Return metadata as a :class:`MetaInformation` object """
+ """ Return metadata as a :class:`Metadata` object """
stream.seek(0)
reader = OCFZipReader(stream)
mi = MetaInformation(reader.opf)
diff --git a/src/calibre/ebooks/metadata/fetch.py b/src/calibre/ebooks/metadata/fetch.py
index 96807c06ae..9b8a42e482 100644
--- a/src/calibre/ebooks/metadata/fetch.py
+++ b/src/calibre/ebooks/metadata/fetch.py
@@ -29,7 +29,7 @@ class MetadataSource(Plugin): # {{{
future use.
The fetch method must store the results in `self.results` as a list of
- :class:`MetaInformation` objects. If there is an error, it should be stored
+ :class:`Metadata` objects. If there is an error, it should be stored
in `self.exception` and `self.tb` (for the traceback).
'''
From 06b266840c8785aa93aa265c0c20308c1c7286f7 Mon Sep 17 00:00:00 2001
From: Charles Haley <>
Date: Sun, 5 Sep 2010 12:35:35 +0100
Subject: [PATCH 013/235] Make gui version of content server able to show both
abbreviated and full lists of tags.
---
resources/content_server/gui.js | 34 ++++++++++++++++++++++++
src/calibre/ebooks/metadata/book/base.py | 7 ++---
src/calibre/library/server/utils.py | 9 ++++---
src/calibre/library/server/xml.py | 6 +++--
4 files changed, 47 insertions(+), 9 deletions(-)
diff --git a/resources/content_server/gui.js b/resources/content_server/gui.js
index 8368866a5e..abbd409dc8 100644
--- a/resources/content_server/gui.js
+++ b/resources/content_server/gui.js
@@ -59,14 +59,44 @@ function render_book(book) {
title = title.slice(0, title.length-2);
title += ' ({0} MB) '.format(size);
}
+ title += ''
+ if (tags) {
+ t = tags.split(':&:', 2);
+ m = parseInt(t[0]);
+ t = t[1].split(',', m);
+ if (t.length == m) t[m] = '...'
+ title += 'Tags=[{0}] '.format(t.join(','));
+ }
+ custcols = book.attr("custcols").split(',')
+ for ( i = 0; i < custcols.length; i++) {
+ if (custcols[i].length > 0) {
+ vals = book.attr(custcols[i]).split(':#:', 2);
+ if (vals[0].indexOf('#T#') == 0) { //startswith
+ vals[0] = vals[0].substr(3, vals[0].length)
+ t = vals[1].split(':&:', 2);
+ m = parseInt(t[0]);
+ t = t[1].split(',', m);
+ if (t.length == m) t[m] = '...';
+ vals[1] = t.join(',');
+ }
+ title += '{0}=[{1}] '.format(vals[0], vals[1]);
+ }
+ }
+ title += ''
+ title += ' '
title += ' '.format(id);
title += '
')%rating)
tags = item[FM['tags']]
if tags:
- extra.append(_('TAGS: %s
')%\
- ', '.join(tags.split(',')))
+ extra.append(_('TAGS: %s
')%format_tag_string(tags, ',',
+ ignore_max=True,
+ no_tag_count=True))
series = item[FM['series']]
if series:
extra.append(_('SERIES: %s [%s]
')%\
@@ -160,7 +162,9 @@ def ACQUISITION_ENTRY(item, version, FM, updated, CFM, CKEYS):
name = CFM[key]['name']
datatype = CFM[key]['datatype']
if datatype == 'text' and CFM[key]['is_multiple']:
- extra.append('%s: %s
'%(name, ', '.join(val.split('|'))))
+ extra.append('%s: %s
'%(name, format_tag_string(val, '|',
+ ignore_max=True,
+ no_tag_count=True)))
elif datatype == 'series':
extra.append('%s: %s [%s]
'%(name, val,
fmt_sidx(item[CFM.cc_series_index_column_for(key)])))
diff --git a/src/calibre/library/server/utils.py b/src/calibre/library/server/utils.py
index 373653c15f..9a64948a3d 100644
--- a/src/calibre/library/server/utils.py
+++ b/src/calibre/library/server/utils.py
@@ -44,7 +44,7 @@ def strftime(fmt='%Y/%m/%d %H:%M:%S', dt=None):
except:
return _strftime(fmt, nowf().timetuple())
-def format_tag_string(tags, sep, ignore_max=False):
+def format_tag_string(tags, sep, ignore_max=False, no_tag_count=False):
MAX = sys.maxint if ignore_max else tweaks['max_content_server_tags_shown']
if tags:
tlist = [t.strip() for t in tags.split(sep)]
@@ -53,6 +53,9 @@ def format_tag_string(tags, sep, ignore_max=False):
tlist.sort(cmp=lambda x,y:cmp(x.lower(), y.lower()))
if len(tlist) > MAX:
tlist = tlist[:MAX]+['...']
- return u'%s:&:%s'%(tweaks['max_content_server_tags_shown'],
+ if no_tag_count:
+ return ', '.join(tlist) if tlist else ''
+ else:
+ return u'%s:&:%s'%(tweaks['max_content_server_tags_shown'],
', '.join(tlist)) if tlist else ''
From 240c9428f5da2c5452dd7f0ab6cc8a6c8cd67afe Mon Sep 17 00:00:00 2001
From: Kovid Goyal '%x
diff --git a/src/calibre/gui2/library/models.py b/src/calibre/gui2/library/models.py
index 09a28fb04e..5fa514ae8a 100644
--- a/src/calibre/gui2/library/models.py
+++ b/src/calibre/gui2/library/models.py
@@ -320,7 +320,7 @@ class BooksModel(QAbstractTableModel): # {{{
(sidx, prepare_string_for_xml(series))
mi = self.db.get_metadata(idx)
for key in mi.user_metadata_keys:
- name, val = mi.format_custom_field(key)
+ name, val = mi.format_field(key)
if val is not None:
data[name] = val
return data
diff --git a/src/calibre/library/field_metadata.py b/src/calibre/library/field_metadata.py
index 276a6ba971..2773f573b2 100644
--- a/src/calibre/library/field_metadata.py
+++ b/src/calibre/library/field_metadata.py
@@ -5,6 +5,7 @@ Created on 25 May 2010
'''
from calibre.utils.ordered_dict import OrderedDict
+from calibre.utils.config import tweaks
class TagsIcons(dict):
'''
@@ -213,7 +214,7 @@ class FieldMetadata(dict):
'datatype':'text',
'is_multiple':None,
'kind':'field',
- 'name':None,
+ 'name':_('On Device'),
'search_terms':['ondevice'],
'is_custom':False,
'is_category':False}),
@@ -231,7 +232,7 @@ class FieldMetadata(dict):
'datatype':'datetime',
'is_multiple':None,
'kind':'field',
- 'name':None,
+ 'name':_('Published'),
'search_terms':['pubdate'],
'is_custom':False,
'is_category':False}),
@@ -258,7 +259,7 @@ class FieldMetadata(dict):
'datatype':'float',
'is_multiple':None,
'kind':'field',
- 'name':None,
+ 'name':_('Size (MB)'),
'search_terms':['size'],
'is_custom':False,
'is_category':False}),
@@ -267,7 +268,7 @@ class FieldMetadata(dict):
'datatype':'datetime',
'is_multiple':None,
'kind':'field',
- 'name':None,
+ 'name':_('Date'),
'search_terms':['date'],
'is_custom':False,
'is_category':False}),
@@ -276,7 +277,7 @@ class FieldMetadata(dict):
'datatype':'text',
'is_multiple':None,
'kind':'field',
- 'name':None,
+ 'name':_('Title'),
'search_terms':['title'],
'is_custom':False,
'is_category':False}),
@@ -310,6 +311,10 @@ class FieldMetadata(dict):
self._tb_cats[k]['display'] = {}
self._tb_cats[k]['is_editable'] = True
self._add_search_terms_to_map(k, v['search_terms'])
+ self._tb_cats['timestamp']['display'] = {
+ 'date_format': tweaks['gui_timestamp_display_format']}
+ self._tb_cats['pubdate']['display'] = {
+ 'date_format': tweaks['gui_pubdate_display_format']}
self.custom_field_prefix = '#'
self.get = self._tb_cats.get
@@ -410,7 +415,7 @@ class FieldMetadata(dict):
if datatype == 'series':
key += '_index'
self._tb_cats[key] = {'table':None, 'column':None,
- 'datatype':'float', 'is_multiple':False,
+ 'datatype':'float', 'is_multiple':None,
'kind':'field', 'name':'',
'search_terms':[key], 'label':label+'_index',
'colnum':None, 'display':{},
From 2a654f3062401e864cdd357850033ad05937f34e Mon Sep 17 00:00:00 2001
From: Charles Haley <>
Date: Tue, 14 Sep 2010 07:41:06 +0100
Subject: [PATCH 034/235] Fix stupidity in collectiions_management where I
broke tag splitting
---
src/calibre/devices/usbms/books.py | 4 +++-
src/calibre/ebooks/metadata/book/base.py | 13 ++++++++-----
2 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/src/calibre/devices/usbms/books.py b/src/calibre/devices/usbms/books.py
index cf60f1311c..d25787fc89 100644
--- a/src/calibre/devices/usbms/books.py
+++ b/src/calibre/devices/usbms/books.py
@@ -141,7 +141,9 @@ class CollectionsBookList(BookList):
cust_field_meta = book.get_all_user_metadata(make_copy=False)
for attr in attrs:
attr = attr.strip()
- ign, val = book.format_field(attr, ignore_series_index=True)
+ ign, val = book.format_field(attr,
+ ignore_series_index=True,
+ return_multiples_as_list=True)
if not val: continue
if isbytestring(val):
val = val.decode(preferred_encoding, 'replace')
diff --git a/src/calibre/ebooks/metadata/book/base.py b/src/calibre/ebooks/metadata/book/base.py
index 6e0351353f..7405f20a7c 100644
--- a/src/calibre/ebooks/metadata/book/base.py
+++ b/src/calibre/ebooks/metadata/book/base.py
@@ -343,7 +343,8 @@ class Metadata(object):
def format_rating(self):
return unicode(self.rating)
- def format_field(self, key, ignore_series_index=False):
+ def format_field(self, key, ignore_series_index=False,
+ return_multiples_as_list=False):
from calibre.ebooks.metadata import authors_to_string
'''
returns the tuple (field_name, formatted_value)
@@ -356,7 +357,8 @@ class Metadata(object):
name = unicode(cmeta['name'])
datatype = cmeta['datatype']
if datatype == 'text' and cmeta['is_multiple']:
- res = u', '.join(res)
+ if not return_multiples_as_list:
+ res = u', '.join(res)
elif datatype == 'series':
if not ignore_series_index:
res = res + \
@@ -365,7 +367,7 @@ class Metadata(object):
res = format_date(res, cmeta['display'].get('date_format','dd MMM yyyy'))
elif datatype == 'bool':
res = _('Yes') if res else _('No')
- return (name, unicode(res))
+ return (name, res)
if key in field_metadata and field_metadata[key]['kind'] == 'field':
res = self.get(key, None)
@@ -377,13 +379,14 @@ class Metadata(object):
if key == 'authors':
res = authors_to_string(res)
elif datatype == 'text' and fmeta['is_multiple']:
- res = u', '.join(res)
+ if not return_multiples_as_list:
+ res = u', '.join(res)
elif datatype == 'series':
if not ignore_series_index:
res = res + ' [%s]'%self.format_series_index()
elif datatype == 'datetime':
res = format_date(res, fmeta['display'].get('date_format','dd MMM yyyy'))
- return (name, unicode(res))
+ return (name, res)
return (None, None)
From 6653fff4cd3228629c879e0e534024a9cc203fd2 Mon Sep 17 00:00:00 2001
From: Kovid Goyal %s %s '%
+ rows.append(u'%s %s '%
(var, FORMAT_ARG_DESCS[var]))
+ rows.append(u'%s %s '%(
+ _('Any custom field'),
+ _('The lookup name of any custom field. These names begin with "#")')))
table = u'%s %s %s
'%(u'\n'.join(rows))
self.template_variables.setText(table)
@@ -39,21 +44,21 @@ class SaveTemplate(QWidget, Ui_Form):
self.changed_signal.emit()
def validate(self):
- # TODO: NEWMETA: I haven't figured out how to get the custom columns
- # into here, so for the moment make all templates valid.
+ '''
+ Do a syntax check on the format string. Doing a semantic check
+ (verifying that the fields exist) is not useful in the presence of
+ custom fields, because they may or may not exist.
+ '''
+ tmpl = preprocess_template(self.opt_template.text())
+ fa = {}
+ try:
+ safe_format(tmpl, fa)
+ except Exception, err:
+ error_dialog(self, _('Invalid template'),
+ '
'+str(err), show=True)
+ return False
return True
-# tmpl = preprocess_template(self.opt_template.text())
-# fa = {}
-# for x in FORMAT_ARG_DESCS.keys():
-# fa[x]='random long string'
-# try:
-# tmpl.format(**fa)
-# except Exception, err:
-# error_dialog(self, _('Invalid template'),
-# '
'+str(err), show=True)
-# return False
-# return True
def set_value(self, val):
self.opt_template.set_value(val)
diff --git a/src/calibre/gui2/preferences/sending.ui b/src/calibre/gui2/preferences/sending.ui
index b9d1d1e1d2..75b1899a3a 100644
--- a/src/calibre/gui2/preferences/sending.ui
+++ b/src/calibre/gui2/preferences/sending.ui
@@ -103,7 +103,7 @@
'%(name, format_tag_string(val, '|',
+ extra.append('%s: %s
'%(name, format_tag_string(val, ',',
ignore_max=True,
no_tag_count=True)))
- elif datatype == 'series':
- extra.append('%s: %s [%s]
'%(name, val,
- fmt_sidx(item[CFM.cc_series_index_column_for(key)])))
- elif datatype == 'datetime':
- extra.append('%s: %s
'%(name,
- format_date(val, CFM[key]['display'].get('date_format','dd MMM yyyy'))))
else:
- extra.append('%s: %s
' % (CFM[key]['name'], val))
+ extra.append('%s: %s
'%(name, val))
comments = item[FM['comments']]
if comments:
comments = comments_to_html(comments)
@@ -280,13 +275,14 @@ class NavFeed(Feed):
class AcquisitionFeed(NavFeed):
def __init__(self, updated, id_, items, offsets, page_url, up_url, version,
- FM, CFM):
+ db):
NavFeed.__init__(self, id_, updated, version, offsets, page_url, up_url)
+ CFM = db.field_metadata
CKEYS = [key for key in sorted(CFM.get_custom_fields(),
cmp=lambda x,y: cmp(CFM[x]['name'].lower(),
CFM[y]['name'].lower()))]
for item in items:
- self.root.append(ACQUISITION_ENTRY(item, version, FM, updated,
+ self.root.append(ACQUISITION_ENTRY(item, version, db, updated,
CFM, CKEYS))
class CategoryFeed(NavFeed):
@@ -384,7 +380,7 @@ class OPDSServer(object):
cherrypy.response.headers['Last-Modified'] = self.last_modified(updated)
cherrypy.response.headers['Content-Type'] = 'application/atom+xml;profile=opds-catalog'
return str(AcquisitionFeed(updated, id_, items, offsets,
- page_url, up_url, version, self.db.FIELD_MAP, self.db.field_metadata))
+ page_url, up_url, version, self.db))
def opds_search(self, query=None, version=0, offset=0):
try:
diff --git a/src/calibre/library/server/xml.py b/src/calibre/library/server/xml.py
index 8715dda7d0..7f5bc31e70 100644
--- a/src/calibre/library/server/xml.py
+++ b/src/calibre/library/server/xml.py
@@ -102,31 +102,21 @@ class XMLServer(object):
for key in CKEYS:
def concat(name, val):
return '%s:#:%s'%(name, unicode(val))
- val = record[CFM[key]['rec_index']]
- if val:
- datatype = CFM[key]['datatype']
- if datatype in ['comments']:
- continue
- k = str('CF_'+key[1:])
- name = CFM[key]['name']
- custcols.append(k)
- if datatype == 'text' and CFM[key]['is_multiple']:
- kwargs[k] = concat('#T#'+name,
- format_tag_string(val,'|',
- ignore_max=True))
- elif datatype == 'series':
- kwargs[k] = concat(name, '%s [%s]'%(val,
- fmt_sidx(record[CFM.cc_series_index_column_for(key)])))
- elif datatype == 'datetime':
- kwargs[k] = concat(name,
- format_date(val, CFM[key]['display'].get('date_format','dd MMM yyyy')))
- elif datatype == 'bool':
- if val:
- kwargs[k] = concat(name, __builtin__._('Yes'))
- else:
- kwargs[k] = concat(name, __builtin__._('No'))
- else:
- kwargs[k] = concat(name, val)
+ mi = self.db.get_metadata(record[CFM['id']['rec_index']], index_is_id=True)
+ name, val = mi.format_field(key)
+ if not val:
+ continue
+ datatype = CFM[key]['datatype']
+ if datatype in ['comments']:
+ continue
+ k = str('CF_'+key[1:])
+ name = CFM[key]['name']
+ custcols.append(k)
+ if datatype == 'text' and CFM[key]['is_multiple']:
+ kwargs[k] = concat('#T#'+name, format_tag_string(val,',',
+ ignore_max=True))
+ else:
+ kwargs[k] = concat(name, val)
kwargs['custcols'] = ','.join(custcols)
books.append(E.book(c, **kwargs))
From 83fc5b2cc0452533cdcdc342d8ce21e3ab5501a4 Mon Sep 17 00:00:00 2001
From: Charles Haley <>
Date: Sat, 18 Sep 2010 11:38:51 +0100
Subject: [PATCH 042/235] Small cleanup of composite field code.
---
src/calibre/ebooks/metadata/book/base.py | 12 ++++++++----
src/calibre/gui2/library/models.py | 2 +-
2 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/src/calibre/ebooks/metadata/book/base.py b/src/calibre/ebooks/metadata/book/base.py
index 31485dfe1b..ce6e2ee78d 100644
--- a/src/calibre/ebooks/metadata/book/base.py
+++ b/src/calibre/ebooks/metadata/book/base.py
@@ -46,7 +46,10 @@ composite_formatter = SafeFormat()
compress_spaces = re.compile(r'\s+')
def format_composite(x, mi):
- ans = composite_formatter.vformat(x, [], mi).strip()
+ try:
+ ans = composite_formatter.vformat(x, [], mi).strip()
+ except:
+ ans = x
return compress_spaces.sub(' ', ans)
class Metadata(object):
@@ -86,7 +89,10 @@ class Metadata(object):
except AttributeError:
pass
if field in _data['user_metadata'].iterkeys():
- return _data['user_metadata'][field]['#value#']
+ d = _data['user_metadata'][field]
+ if d['datatype'] != 'composite':
+ return d['#value#']
+ return format_composite(d['display']['composite_template'], self)
raise AttributeError(
'Metadata object has no attribute named: '+ repr(field))
@@ -386,8 +392,6 @@ class Metadata(object):
res = format_date(res, cmeta['display'].get('date_format','dd MMM yyyy'))
elif datatype == 'bool':
res = _('Yes') if res else _('No')
- elif datatype == 'composite':
- res = format_composite(cmeta['display']['composite_template'], self)
return (name, res, orig_res, cmeta)
if key in field_metadata and field_metadata[key]['kind'] == 'field':
diff --git a/src/calibre/gui2/library/models.py b/src/calibre/gui2/library/models.py
index 7839b89d7e..2a116f6f3d 100644
--- a/src/calibre/gui2/library/models.py
+++ b/src/calibre/gui2/library/models.py
@@ -605,7 +605,7 @@ class BooksModel(QAbstractTableModel): # {{{
def composite_type(r, key=None):
mi = self.get_cached_metadata(r)
- return QVariant(mi.format_field(key)[1])
+ return QVariant(mi.get(key, ''))
self.dc = {
'title' : functools.partial(text_type,
From c59545a96a968488221f494fcee0baccab642a63 Mon Sep 17 00:00:00 2001
From: Charles Haley <>
Date: Sat, 18 Sep 2010 13:45:01 +0100
Subject: [PATCH 043/235] Change composites to use the cache correctly, so that
searches & sorts used. In the process, remove the metadata cache from
models.py.
Fix some bugs introduced by composite columns:
1) no edit widget in bulk_metadata edit
2) explicitly do not make a delegate in views.py
---
src/calibre/gui2/custom_column_widgets.py | 2 ++
src/calibre/gui2/library/models.py | 28 ++---------------------
src/calibre/gui2/library/views.py | 3 +++
src/calibre/library/caches.py | 20 +++++++++++++++-
src/calibre/library/database2.py | 11 ++++-----
5 files changed, 31 insertions(+), 33 deletions(-)
diff --git a/src/calibre/gui2/custom_column_widgets.py b/src/calibre/gui2/custom_column_widgets.py
index 67ab94d29a..d16233be1a 100644
--- a/src/calibre/gui2/custom_column_widgets.py
+++ b/src/calibre/gui2/custom_column_widgets.py
@@ -348,6 +348,8 @@ def populate_metadata_page(layout, db, book_id, bulk=False, two_column=False, pa
ans = []
column = row = comments_row = 0
for col in cols:
+ if not x[col]['editable']:
+ continue
dt = x[col]['datatype']
if dt == 'comments':
continue
diff --git a/src/calibre/gui2/library/models.py b/src/calibre/gui2/library/models.py
index 2a116f6f3d..be1bf9bc2d 100644
--- a/src/calibre/gui2/library/models.py
+++ b/src/calibre/gui2/library/models.py
@@ -86,7 +86,6 @@ class BooksModel(QAbstractTableModel): # {{{
self.last_search = '' # The last search performed on this model
self.column_map = []
self.headers = {}
- self.metadata_cache = {}
self.alignment_map = {}
self.buffer_size = buffer
self.cover_cache = None
@@ -115,16 +114,6 @@ class BooksModel(QAbstractTableModel): # {{{
def clear_caches(self):
if self.cover_cache:
self.cover_cache.clear_cache()
- self.metadata_cache = {}
-
- def get_cached_metadata(self, idx):
- if idx not in self.metadata_cache:
- self.metadata_cache[idx] = self.db.get_metadata(idx)
- return self.metadata_cache[idx]
-
- def remove_cached_metadata(self, idx):
- if idx in self.metadata_cache:
- del self.metadata_cache[idx]
def read_config(self):
self.use_roman_numbers = config['use_roman_numerals_for_series_number']
@@ -157,7 +146,6 @@ class BooksModel(QAbstractTableModel): # {{{
elif col in self.custom_columns:
self.headers[col] = self.custom_columns[col]['name']
- self.metadata_cache = {}
self.build_data_convertors()
self.reset()
self.database_changed.emit(db)
@@ -171,13 +159,11 @@ class BooksModel(QAbstractTableModel): # {{{
db.add_listener(refresh_cover)
def refresh_ids(self, ids, current_row=-1):
- self.metadata_cache = {}
rows = self.db.refresh_ids(ids)
if rows:
self.refresh_rows(rows, current_row=current_row)
def refresh_rows(self, rows, current_row=-1):
- self.metadata_cache = {}
for row in rows:
if row == current_row:
self.new_bookdisplay_data.emit(
@@ -207,7 +193,6 @@ class BooksModel(QAbstractTableModel): # {{{
return ret
def count_changed(self, *args):
- self.metadata_cache = {}
self.count_changed_signal.emit(self.db.count())
def row_indices(self, index):
@@ -277,7 +262,6 @@ class BooksModel(QAbstractTableModel): # {{{
self.sorting_done.emit(self.db.index)
def refresh(self, reset=True):
- self.metadata_cache = {}
self.db.refresh(field=None)
self.resort(reset=reset)
@@ -334,7 +318,7 @@ class BooksModel(QAbstractTableModel): # {{{
data[_('Series')] = \
_('Book %s of %s.')%\
(sidx, prepare_string_for_xml(series))
- mi = self.get_cached_metadata(idx)
+ mi = self.db.get_metadata(idx)
for key in mi.user_metadata_keys:
name, val = mi.format_field(key)
if val is not None:
@@ -343,7 +327,6 @@ class BooksModel(QAbstractTableModel): # {{{
def set_cache(self, idx):
l, r = 0, self.count()-1
- self.remove_cached_metadata(idx)
if self.cover_cache is not None:
l = max(l, idx-self.buffer_size)
r = min(r, idx+self.buffer_size)
@@ -603,10 +586,6 @@ class BooksModel(QAbstractTableModel): # {{{
def number_type(r, idx=-1):
return QVariant(self.db.data[r][idx])
- def composite_type(r, key=None):
- mi = self.get_cached_metadata(r)
- return QVariant(mi.get(key, ''))
-
self.dc = {
'title' : functools.partial(text_type,
idx=self.db.field_metadata['title']['rec_index'], mult=False),
@@ -640,7 +619,7 @@ class BooksModel(QAbstractTableModel): # {{{
for col in self.custom_columns:
idx = self.custom_columns[col]['rec_index']
datatype = self.custom_columns[col]['datatype']
- if datatype in ('text', 'comments'):
+ if datatype in ('text', 'comments', 'composite'):
self.dc[col] = functools.partial(text_type, idx=idx,
mult=self.custom_columns[col]['is_multiple'])
elif datatype in ('int', 'float'):
@@ -657,8 +636,6 @@ class BooksModel(QAbstractTableModel): # {{{
elif datatype == 'series':
self.dc[col] = functools.partial(series_type, idx=idx,
siix=self.db.field_metadata.cc_series_index_column_for(col))
- elif datatype == 'composite':
- self.dc[col] = functools.partial(composite_type, key=col)
else:
print 'What type is this?', col, datatype
# build a index column to data converter map, to remove the string lookup in the data loop
@@ -753,7 +730,6 @@ class BooksModel(QAbstractTableModel): # {{{
if role == Qt.EditRole:
row, col = index.row(), index.column()
column = self.column_map[col]
- self.remove_cached_metadata(row)
if self.is_custom_column(column):
if not self.set_custom_column_data(row, column, value):
return False
diff --git a/src/calibre/gui2/library/views.py b/src/calibre/gui2/library/views.py
index d67d286aeb..9951edf21b 100644
--- a/src/calibre/gui2/library/views.py
+++ b/src/calibre/gui2/library/views.py
@@ -391,6 +391,9 @@ class BooksView(QTableView): # {{{
self.setItemDelegateForColumn(cm.index(colhead), self.cc_bool_delegate)
elif cc['datatype'] == 'rating':
self.setItemDelegateForColumn(cm.index(colhead), self.rating_delegate)
+ elif cc['datatype'] == 'composite':
+ pass
+ # no delegate for composite columns, as they are not editable
else:
dattr = colhead+'_delegate'
delegate = colhead if hasattr(self, dattr) else 'text'
diff --git a/src/calibre/library/caches.py b/src/calibre/library/caches.py
index 4f795ab733..a013d23cb9 100644
--- a/src/calibre/library/caches.py
+++ b/src/calibre/library/caches.py
@@ -121,6 +121,11 @@ class ResultCache(SearchQueryParser):
self.build_date_relop_dict()
self.build_numeric_relop_dict()
+ self.composites = []
+ for key in field_metadata:
+ if field_metadata[key]['datatype'] == 'composite':
+ self.composites.append((key, field_metadata[key]['rec_index']))
+
def __getitem__(self, row):
return self._data[self._map_filtered[row]]
@@ -372,7 +377,7 @@ class ResultCache(SearchQueryParser):
if len(self.field_metadata[x]['search_terms']):
db_col[x] = self.field_metadata[x]['rec_index']
if self.field_metadata[x]['datatype'] not in \
- ['text', 'comments', 'series']:
+ ['composite', 'text', 'comments', 'series']:
exclude_fields.append(db_col[x])
col_datatype[db_col[x]] = self.field_metadata[x]['datatype']
is_multiple_cols[db_col[x]] = self.field_metadata[x]['is_multiple']
@@ -534,6 +539,10 @@ class ResultCache(SearchQueryParser):
self._data[id] = db.conn.get('SELECT * from meta2 WHERE id=?', (id,))[0]
self._data[id].append(db.has_cover(id, index_is_id=True))
self._data[id].append(db.book_on_device_string(id))
+ if len(self.composites) > 0:
+ mi = db.get_metadata(id, index_is_id=True)
+ for k,c in self.composites:
+ self._data[id][c] = mi.format_field(k)[1]
except IndexError:
return None
try:
@@ -550,6 +559,10 @@ class ResultCache(SearchQueryParser):
self._data[id] = db.conn.get('SELECT * from meta2 WHERE id=?', (id,))[0]
self._data[id].append(db.has_cover(id, index_is_id=True))
self._data[id].append(db.book_on_device_string(id))
+ if len(self.composites) > 0:
+ mi = db.get_metadata(id, index_is_id=True)
+ for k,c in self.composites:
+ self._data[id][c] = mi.format_field(k)[1]
self._map[0:0] = ids
self._map_filtered[0:0] = ids
@@ -575,6 +588,11 @@ class ResultCache(SearchQueryParser):
if item is not None:
item.append(db.has_cover(item[0], index_is_id=True))
item.append(db.book_on_device_string(item[0]))
+ if len(self.composites) > 0:
+ mi = db.get_metadata(item[0], index_is_id=True)
+ for k,c in self.composites:
+ item[c] = mi.format_field(k)[1]
+
self._map = [i[0] for i in self._data if i is not None]
if field is not None:
self.sort(field, ascending)
diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py
index d06d217b76..d51a8a62c0 100644
--- a/src/calibre/library/database2.py
+++ b/src/calibre/library/database2.py
@@ -323,12 +323,6 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
self.has_id = self.data.has_id
self.count = self.data.count
- self.refresh_ondevice = functools.partial(self.data.refresh_ondevice, self)
-
- self.refresh()
- self.last_update_check = self.last_modified()
-
-
for prop in ('author_sort', 'authors', 'comment', 'comments', 'isbn',
'publisher', 'rating', 'series', 'series_index', 'tags',
'title', 'timestamp', 'uuid', 'pubdate', 'ondevice'):
@@ -337,6 +331,11 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
setattr(self, 'title_sort', functools.partial(self.get_property,
loc=self.FIELD_MAP['sort']))
+ self.refresh_ondevice = functools.partial(self.data.refresh_ondevice, self)
+ self.refresh()
+ self.last_update_check = self.last_modified()
+
+
def initialize_database(self):
metadata_sqlite = open(P('metadata_sqlite.sql'), 'rb').read()
self.conn.executescript(metadata_sqlite)
From ed7597ae5f142998c3444f1ad941725fa4d21b0d Mon Sep 17 00:00:00 2001
From: Charles Haley <>
Date: Sat, 18 Sep 2010 19:40:44 +0100
Subject: [PATCH 044/235] Playing with search & replace. Added 'global'
template values to the replace expression. Also fixed some problems with
exceptions, and problems with case-insensitive matching in the history boxes.
---
src/calibre/ebooks/metadata/book/base.py | 9 +++
src/calibre/gui2/dialogs/metadata_bulk.py | 68 +++++++++++++++++++----
2 files changed, 66 insertions(+), 11 deletions(-)
diff --git a/src/calibre/ebooks/metadata/book/base.py b/src/calibre/ebooks/metadata/book/base.py
index ce6e2ee78d..1eae2e5326 100644
--- a/src/calibre/ebooks/metadata/book/base.py
+++ b/src/calibre/ebooks/metadata/book/base.py
@@ -12,6 +12,7 @@ from calibre.ebooks.metadata.book import SC_COPYABLE_FIELDS
from calibre.ebooks.metadata.book import SC_FIELDS_COPY_NOT_NULL
from calibre.ebooks.metadata.book import STANDARD_METADATA_FIELDS
from calibre.ebooks.metadata.book import TOP_LEVEL_CLASSIFIERS
+from calibre.ebooks.metadata.book import ALL_METADATA_FIELDS
from calibre.library.field_metadata import FieldMetadata
from calibre.utils.date import isoformat, format_date
@@ -131,6 +132,14 @@ class Metadata(object):
def set(self, field, val, extra=None):
self.__setattr__(field, val, extra)
+ @property
+ def all_keys(self):
+ '''
+ All attribute keys known by this instance, even if their value is None
+ '''
+ _data = object.__getattribute__(self, '_data')
+ return frozenset(ALL_METADATA_FIELDS.union(_data['user_metadata'].iterkeys()))
+
@property
def user_metadata_keys(self):
'The set of user metadata names this object knows about'
diff --git a/src/calibre/gui2/dialogs/metadata_bulk.py b/src/calibre/gui2/dialogs/metadata_bulk.py
index b7d1d0c54b..1fb889757f 100644
--- a/src/calibre/gui2/dialogs/metadata_bulk.py
+++ b/src/calibre/gui2/dialogs/metadata_bulk.py
@@ -4,15 +4,15 @@ __copyright__ = '2008, Kovid Goyal
'%(name, format_tag_string(val, '|',
+ extra.append('%s: %s
'%(name, format_tag_string(val, ',',
ignore_max=True,
no_tag_count=True)))
- elif datatype == 'series':
- extra.append('%s: %s [%s]
'%(name, val,
- fmt_sidx(item[CFM.cc_series_index_column_for(key)])))
- elif datatype == 'datetime':
- extra.append('%s: %s
'%(name,
- format_date(val, CFM[key]['display'].get('date_format','dd MMM yyyy'))))
else:
- extra.append('%s: %s
' % (CFM[key]['name'], val))
+ extra.append('%s: %s
'%(name, val))
comments = item[FM['comments']]
if comments:
comments = comments_to_html(comments)
@@ -280,13 +274,14 @@ class NavFeed(Feed):
class AcquisitionFeed(NavFeed):
def __init__(self, updated, id_, items, offsets, page_url, up_url, version,
- FM, CFM):
+ db):
NavFeed.__init__(self, id_, updated, version, offsets, page_url, up_url)
+ CFM = db.field_metadata
CKEYS = [key for key in sorted(CFM.get_custom_fields(),
cmp=lambda x,y: cmp(CFM[x]['name'].lower(),
CFM[y]['name'].lower()))]
for item in items:
- self.root.append(ACQUISITION_ENTRY(item, version, FM, updated,
+ self.root.append(ACQUISITION_ENTRY(item, version, db, updated,
CFM, CKEYS))
class CategoryFeed(NavFeed):
@@ -384,7 +379,7 @@ class OPDSServer(object):
cherrypy.response.headers['Last-Modified'] = self.last_modified(updated)
cherrypy.response.headers['Content-Type'] = 'application/atom+xml;profile=opds-catalog'
return str(AcquisitionFeed(updated, id_, items, offsets,
- page_url, up_url, version, self.db.FIELD_MAP, self.db.field_metadata))
+ page_url, up_url, version, self.db))
def opds_search(self, query=None, version=0, offset=0):
try:
diff --git a/src/calibre/library/server/xml.py b/src/calibre/library/server/xml.py
index 8715dda7d0..7f5bc31e70 100644
--- a/src/calibre/library/server/xml.py
+++ b/src/calibre/library/server/xml.py
@@ -102,31 +102,21 @@ class XMLServer(object):
for key in CKEYS:
def concat(name, val):
return '%s:#:%s'%(name, unicode(val))
- val = record[CFM[key]['rec_index']]
- if val:
- datatype = CFM[key]['datatype']
- if datatype in ['comments']:
- continue
- k = str('CF_'+key[1:])
- name = CFM[key]['name']
- custcols.append(k)
- if datatype == 'text' and CFM[key]['is_multiple']:
- kwargs[k] = concat('#T#'+name,
- format_tag_string(val,'|',
- ignore_max=True))
- elif datatype == 'series':
- kwargs[k] = concat(name, '%s [%s]'%(val,
- fmt_sidx(record[CFM.cc_series_index_column_for(key)])))
- elif datatype == 'datetime':
- kwargs[k] = concat(name,
- format_date(val, CFM[key]['display'].get('date_format','dd MMM yyyy')))
- elif datatype == 'bool':
- if val:
- kwargs[k] = concat(name, __builtin__._('Yes'))
- else:
- kwargs[k] = concat(name, __builtin__._('No'))
- else:
- kwargs[k] = concat(name, val)
+ mi = self.db.get_metadata(record[CFM['id']['rec_index']], index_is_id=True)
+ name, val = mi.format_field(key)
+ if not val:
+ continue
+ datatype = CFM[key]['datatype']
+ if datatype in ['comments']:
+ continue
+ k = str('CF_'+key[1:])
+ name = CFM[key]['name']
+ custcols.append(k)
+ if datatype == 'text' and CFM[key]['is_multiple']:
+ kwargs[k] = concat('#T#'+name, format_tag_string(val,',',
+ ignore_max=True))
+ else:
+ kwargs[k] = concat(name, val)
kwargs['custcols'] = ','.join(custcols)
books.append(E.book(c, **kwargs))
From 7eaf417bb10e9d87038b47941c524ea9aa121ad2 Mon Sep 17 00:00:00 2001
From: Charles Haley <>
Date: Sun, 19 Sep 2010 07:47:03 +0100
Subject: [PATCH 046/235] Fix content server tags display problem
---
resources/content_server/gui.js | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/resources/content_server/gui.js b/resources/content_server/gui.js
index afc21137e1..bd0743a854 100644
--- a/resources/content_server/gui.js
+++ b/resources/content_server/gui.js
@@ -84,7 +84,10 @@ function render_book(book) {
}
title += ''
title += ' '
title += 'eeUO
zAf}7bs+VyzWgh^5bduC;Ao2I!l{S~xQc~blJ1S2U$CtDi5-$Tq($u5cAYxIi#Q)bW
zBz<3JAAdAyAHYRIi&O0qhnkW4e^G!!KRPjqSch+Iamn3BbM^sZ`c@r_)AIik$uc23
z5=1acjsJQ;9SjgnwZU>UwEVw>{&fT{Do1E+g!U{}`Ujfi0_aIqfUr0ns!i|PfBJN>
z(?8JEeE
'+str(err), show=True)
+
+ return False
diff --git a/src/calibre/gui2/library/delegates.py b/src/calibre/gui2/library/delegates.py
index bf233b1175..ceb1cf14a8 100644
--- a/src/calibre/gui2/library/delegates.py
+++ b/src/calibre/gui2/library/delegates.py
@@ -15,10 +15,11 @@ from PyQt4.Qt import QColor, Qt, QModelIndex, QSize, \
QStyledItemDelegate, QCompleter, \
QComboBox
-from calibre.gui2 import UNDEFINED_QDATE
+from calibre.gui2 import UNDEFINED_QDATE, error_dialog
from calibre.gui2.widgets import EnLineEdit, TagsLineEdit
from calibre.utils.date import now, format_date
from calibre.utils.config import tweaks
+from calibre.utils.formatter import validation_formatter
from calibre.gui2.dialogs.comments_dialog import CommentsDialog
class RatingDelegate(QStyledItemDelegate): # {{{
@@ -303,6 +304,31 @@ class CcBoolDelegate(QStyledItemDelegate): # {{{
val = 2 if val is None else 1 if not val else 0
editor.setCurrentIndex(val)
+class CcTemplateDelegate(QStyledItemDelegate): # {{{
+ def __init__(self, parent):
+ '''
+ Delegate for custom_column bool data.
+ '''
+ QStyledItemDelegate.__init__(self, parent)
+
+ def createEditor(self, parent, option, index):
+ return EnLineEdit(parent)
+
+ def setModelData(self, editor, model, index):
+ val = unicode(editor.text())
+ try:
+ validation_formatter.validate(val)
+ except Exception, err:
+ error_dialog(self.parent(), _('Invalid template'),
+ '
'+str(err), show=True)
+ model.setData(index, QVariant(val), Qt.EditRole)
+
+ def setEditorData(self, editor, index):
+ m = index.model()
+ val = m.custom_columns[m.column_map[index.column()]]['display']['composite_template']
+ editor.setText(val)
+
# }}}
diff --git a/src/calibre/gui2/library/models.py b/src/calibre/gui2/library/models.py
index 4b1e974b12..fe64a33c47 100644
--- a/src/calibre/gui2/library/models.py
+++ b/src/calibre/gui2/library/models.py
@@ -696,7 +696,8 @@ class BooksModel(QAbstractTableModel): # {{{
return flags
def set_custom_column_data(self, row, colhead, value):
- typ = self.custom_columns[colhead]['datatype']
+ cc = self.custom_columns[colhead]
+ typ = cc['datatype']
label=self.db.field_metadata.key_to_label(colhead)
s_index = None
if typ in ('text', 'comments'):
@@ -722,6 +723,14 @@ class BooksModel(QAbstractTableModel): # {{{
val = qt_to_dt(val, as_utc=False)
elif typ == 'series':
val, s_index = parse_series_string(self.db, label, value.toString())
+ elif typ == 'composite':
+ tmpl = unicode(value.toString()).strip()
+ disp = cc['display']
+ disp['composite_template'] = tmpl
+ self.db.set_custom_column_metadata(cc['colnum'], display = disp)
+ self.refresh(reset=True)
+ return True
+
self.db.set_custom(self.db.id(row), val, extra=s_index,
label=label, num=None, append=False, notify=True)
return True
@@ -768,6 +777,7 @@ class BooksModel(QAbstractTableModel): # {{{
self.db.set_pubdate(id, qt_to_dt(val, as_utc=False))
else:
self.db.set(row, column, val)
+ self.refresh_rows([row], row)
self.dataChanged.emit(index, index)
return True
diff --git a/src/calibre/gui2/library/views.py b/src/calibre/gui2/library/views.py
index d3ead429cf..b113866ecc 100644
--- a/src/calibre/gui2/library/views.py
+++ b/src/calibre/gui2/library/views.py
@@ -13,7 +13,7 @@ from PyQt4.Qt import QTableView, Qt, QAbstractItemView, QMenu, pyqtSignal, \
from calibre.gui2.library.delegates import RatingDelegate, PubDateDelegate, \
TextDelegate, DateDelegate, TagsDelegate, CcTextDelegate, \
- CcBoolDelegate, CcCommentsDelegate, CcDateDelegate
+ CcBoolDelegate, CcCommentsDelegate, CcDateDelegate, CcTemplateDelegate
from calibre.gui2.library.models import BooksModel, DeviceBooksModel
from calibre.utils.config import tweaks, prefs
from calibre.gui2 import error_dialog, gprefs
@@ -47,6 +47,7 @@ class BooksView(QTableView): # {{{
self.cc_text_delegate = CcTextDelegate(self)
self.cc_bool_delegate = CcBoolDelegate(self)
self.cc_comments_delegate = CcCommentsDelegate(self)
+ self.cc_template_delegate = CcTemplateDelegate(self)
self.display_parent = parent
self._model = modelcls(self)
self.setModel(self._model)
@@ -392,8 +393,7 @@ class BooksView(QTableView): # {{{
elif cc['datatype'] == 'rating':
self.setItemDelegateForColumn(cm.index(colhead), self.rating_delegate)
elif cc['datatype'] == 'composite':
- pass
- # no delegate for composite columns, as they are not editable
+ self.setItemDelegateForColumn(cm.index(colhead), self.cc_template_delegate)
else:
dattr = colhead+'_delegate'
delegate = colhead if hasattr(self, dattr) else 'text'
diff --git a/src/calibre/gui2/preferences/columns.py b/src/calibre/gui2/preferences/columns.py
index 761a9880b1..c1b9230f42 100644
--- a/src/calibre/gui2/preferences/columns.py
+++ b/src/calibre/gui2/preferences/columns.py
@@ -155,8 +155,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
name=self.custcols[c]['name'],
datatype=self.custcols[c]['datatype'],
is_multiple=self.custcols[c]['is_multiple'],
- display = self.custcols[c]['display'],
- editable = self.custcols[c]['editable'])
+ display = self.custcols[c]['display'])
must_restart = True
elif '*deleteme' in self.custcols[c]:
db.delete_custom_column(label=self.custcols[c]['label'])
diff --git a/src/calibre/gui2/preferences/create_custom_column.py b/src/calibre/gui2/preferences/create_custom_column.py
index e88949a23c..bec21270df 100644
--- a/src/calibre/gui2/preferences/create_custom_column.py
+++ b/src/calibre/gui2/preferences/create_custom_column.py
@@ -156,9 +156,6 @@ class CreateCustomColumn(QDialog, Ui_QCreateCustomColumn):
return self.simple_error('', _('You must enter a template for'
' composite columns'))
display_dict = {'composite_template':unicode(self.composite_box.text())}
- is_editable = False
- else:
- is_editable = True
db = self.parent.gui.library_view.model().db
key = db.field_metadata.custom_field_prefix+col
@@ -168,7 +165,6 @@ class CreateCustomColumn(QDialog, Ui_QCreateCustomColumn):
'label':col,
'name':col_heading,
'datatype':col_type,
- 'editable':is_editable,
'display':display_dict,
'normalized':None,
'colnum':None,
diff --git a/src/calibre/gui2/preferences/plugins.py b/src/calibre/gui2/preferences/plugins.py
index a26553db1c..388227e438 100644
--- a/src/calibre/gui2/preferences/plugins.py
+++ b/src/calibre/gui2/preferences/plugins.py
@@ -199,7 +199,11 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
config_dialog.exec_()
if config_dialog.result() == QDialog.Accepted:
- plugin.save_settings(config_widget)
+ if hasattr(config_widget, 'validate'):
+ if config_widget.validate():
+ plugin.save_settings(config_widget)
+ else:
+ plugin.save_settings(config_widget)
self._plugin_model.refresh_plugin(plugin)
else:
help_text = plugin.customization_help(gui=True)
diff --git a/src/calibre/gui2/preferences/save_template.py b/src/calibre/gui2/preferences/save_template.py
index 0f48893b69..5b3f0321b2 100644
--- a/src/calibre/gui2/preferences/save_template.py
+++ b/src/calibre/gui2/preferences/save_template.py
@@ -13,17 +13,8 @@ from PyQt4.Qt import QWidget, pyqtSignal
from calibre.gui2 import error_dialog
from calibre.gui2.preferences.save_template_ui import Ui_Form
from calibre.library.save_to_disk import FORMAT_ARG_DESCS, preprocess_template
+from calibre.utils.formatter import validation_formatter
-class ValidateFormat(string.Formatter):
- '''
- Provides a format function that substitutes '' for any missing value
- '''
- def get_value(self, key, args, kwargs):
- return 'this is some text that should be long enough'
-
-validate_formatter = ValidateFormat()
-def validate_format(x, format_args):
- return validate_formatter.vformat(x, [], format_args).strip()
class SaveTemplate(QWidget, Ui_Form):
@@ -62,9 +53,8 @@ class SaveTemplate(QWidget, Ui_Form):
custom fields, because they may or may not exist.
'''
tmpl = preprocess_template(self.opt_template.text())
- fa = {}
try:
- validate_format(tmpl, fa)
+ validation_formatter.validate(tmpl)
except Exception, err:
error_dialog(self, _('Invalid template'),
'
'%(name, format_tag_string(val, ',',
From fb06e4c72eacb21b6f101d6f7e7d7a1785450a86 Mon Sep 17 00:00:00 2001
From: Kovid Goyal 5x~aNo*p$$`u?(wOl1zBwSyrPtVBGXe6EXlNv<$93=OkHXZ{
z=`$mVm`~EN3waPR{$)kdyH3@<-q66m@3!nF7rgFIlwWJq6-Wb#Thr%VeDnVNXTNBg
zr^(w>5~r@PozO-DPwp*8UrUbIKC7T`=2B*dU_EjnZ<`4H!6n(Ses?WG^=-2%Rzapp
z(Txu(+}br_tnun3Y3nEcN&MgfuIg;8Dy@uQeq9}Xv~)tHwoA>Mz4#P68=K3CvWTl)
z_tVI~iC0hz6Vr7oa4De&{KTPPd|}aPf7HTGX<)ImWMDPuu2en;*P!~kGpNB4*W7vX
z*j9JGfzJU4g$aO5GuD8u49zB%D#}Y~Y{MT!EvreX0J>{>^xbXlOl~uz#+~73yb4({
z5u8j9*Sypg-VO^|ojLR_my{F_6!9K(_Prg(1${Ad_t1ENM9>@F%D&^Q>3Mp7{L0R2
znS;+BC}ko+o8_9(Lg759HiSuN5xMh;(dg9xH>Hu&U=jGEDVOHjLA>*#k8QRL?5;T7
zc76)2)HLoEpBN$iq+y_Y*(+rI8+r7fLD=$Oz|JxsFA|;VS-QD)-cxFO&`DZWNzQ$K
zQd9T-XB{+S=kszQ!f3sFU^(LWGSR}KFV-V*-rI&FXPl5aXYD2Tu>ezLyc=tD>t5J@
zb=e1>Ywbj1b%7s~fc_cZu~f3z4yEt1vPh)1YrAJBCq=Ioe0Pv=25|y`K>}S+^)#rk
z5WM<2^l1C+CBL-B6G26eK*1+$K#{LMzstVub8sc9$mE7;eBJfMQP9|Py^$5~*x&l|
z-?nSpLQ`)GhlGA3Hl%fzrn=+jP>sdg$K+F6INDs}0jd|K@j%%Dd*kuGSzNca!zLzB
zE*tyccy7P1OhsjMxXq#ejo*1%?ma>QR6k>iAYknjuCFZr`N8)zCLgA~j=+9At`q4*
z39QD8-uAfq4z*h}BQJgULHyW^nSszQY+A*m610sqdo<(^@1G10$9iaKq*!Oq-F0cO
zlHdqz%akur4Z444l>4<(RjdYuw)z+1O||4)W5c!}VFe%Cn;}_sEzjgF`b>R=KDorO
z5)6H(Wv`PBClMVxAJ(&Ig+X}O+868oy*X4RgyC7fagkMPOW~9Gnzw`!IF$}!=3@s-
z&a1ESfASjLJiUtyr9mmX2~?CgUks%-Z5*CG`?z`a&)F#Xlh_`P{gn;H|>SBQo
zykxAiwD<>H+~}<=WJk|jA+lRoMA~XZ<~*X>7NQ+TB;6A>H8-cW5y1|EDjA-kB|%^e
zOEGfi>_T>$WTX7Fb$nc#*{}*GlgTW{(@vPFNW8$!5Ivc`%FoFg5pgMVIW4WCddf(U
zc%ws>bpkp4R&$5FSiJ>AE!#7P4x$Ex>?C|FR8TM?cwulwo4#5#?qI1bSp~?+f195-
zHJ_%Nb+Z`0KQ6|`E$2JmG1#ojQt(i+0QJ5>uu#cl38)b6;zeG~S#wAv<-D>+iH-IL
z3W6DEZ%ba@ktC{(1Z6y7MhQrpxo!(c2d}GiphRixGa$v+Xw0z4k%K81)GF-ygjHDQ
z?mFw&((DZI0bzNV3h4xQhh$VRQ11=>Fp=54n;TZ?&c=GAA``G0l&x(fUJ_UW=^|9{
z=ChZyij}{VwAOKgCDCS^Hh%_LZuhfhAP?mXW?Put!cupPrhwEs$K30DyST3{#1C
zael@m>*w+uAGC$L@q{+1lqX<46UJvf*k_M^`Tz(UWV{lIUo_Sq@)0MhCrmHEJi-io
zMzC>G9M^7?PZ4P9WS@AS+-iO^x|BeQUW~y5GFY(&2t3QZc{(QNUxcVO-^Z|sBRBgh
z7@u#POtoFADP<9jsh#RQ9LcS)w}MriBrDPC)qIQeePlU=Bafqq+)HG8q~67BQZ;X0
z0RFtF(nlpIzW?`)p&0iqbWWbx%@BIR5rdOgz*{wh9=nJKXQAA*{hU6G=`>g8TAmJy
zE^U0AfGZF|Z@N=HdX+T-Yn}pJs~7tiCm7RoBL>+->8 7jE>CNhj9TMS-r%!Vq
zQz~uKc5O&;ySvy>+rRnRy?^}nJKuffl@B8HG4Z}0!G){KD?&uGs%|J$)3DnmeRRES
zKl!9Rp1uF^r_V1|dozED!$%)}(Dwrwt5Hd%r1awHSD!DMTSv1P`@jC#&kV7fb;0>+
z^dY$G%NHfaI7TLi1_AlS)91)+qNqs8W^F|cF8fU>WwqU0FK@<@6aC5T?@2=cAMa
zRtOA1#GLc}uHUZLT@@@#ThHpMN^uIoRq7R?A14!H=RLY2lC>P1%w0gp8M6@*u$Yl&
zAF7b0sE8o}kOGav
VhO(
'+str(err), show=True)
+ return
pb[s] = self.dest_fields[d]
+ else:
+ error_dialog(self, _('Invalid destination'),
+ ' or
tags that contain the words \"chapter\",\"book\",\"section\" or \"part\" as chapter titles as well as any tags that have class=\"chapter\". The expression used must evaluate to a list of elements. To disable chapter detection, use the expression \"/\". See the XPath Tutorial in the calibre User Manual for further help on using this feature."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:260
+#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:260
msgid "Specify how to mark detected chapters. A value of \"pagebreak\" will insert page breaks before chapters. A value of \"rule\" will insert a line before chapters. A value of \"none\" will disable chapter marking and a value of \"both\" will use both page breaks and lines to mark chapters."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:270
+#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:270
msgid "Either the path to a CSS stylesheet or raw CSS. This CSS will be appended to the style rules from the source file, so it can be used to override those rules."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:279
+#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:279
msgid "An XPath expression. Page breaks are inserted before the specified elements."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:285
+#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:285
msgid "Set the top margin in pts. Default is %default. Note: 72 pts equals 1 inch"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:290
+#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:290
msgid "Set the bottom margin in pts. Default is %default. Note: 72 pts equals 1 inch"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:295
+#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:295
msgid "Set the left margin in pts. Default is %default. Note: 72 pts equals 1 inch"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:300
+#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:300
msgid "Set the right margin in pts. Default is %default. Note: 72 pts equals 1 inch"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:306
+#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:306
msgid "Change text justification. A value of \"left\" converts all justified text in the source to left aligned (i.e. unjustified) text. A value of \"justify\" converts all unjustified text to justified. A value of \"original\" (the default) does not change justification in the source file. Note that only some output formats support justification."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:316
+#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:316
msgid "Remove spacing between paragraphs. Also sets an indent on paragraphs of 1.5em. Spacing removal will not work if the source file does not use paragraphs (
Last Page Read: %d (%d%%)"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/annotate.py:124
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/annotate.py:124
msgid "%s
Last Page Read: Location %d (%d%%)"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/annotate.py:143
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/annotate.py:143
msgid "Location %d • %s
%s
"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/annotate.py:152
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/annotate.py:152
msgid "Page %d • %s
"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/annotate.py:157
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/annotate.py:157
msgid "Location %d • %s
"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/catalog.py:20
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/convert.py:34
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/catalog.py:20
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/convert.py:34
msgid "Create catalog of books in your calibre library"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/catalog.py:31
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/catalog.py:31
msgid "No books selected to generate catalog for"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/catalog.py:53
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/catalog.py:53
msgid "Generating %s catalog..."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/catalog.py:58
-#: /home/kovid/work/calibre/src/calibre/gui2/add.py:229
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/catalog.py:58
+#: /home/kovid/work/trunk/src/calibre/gui2/add.py:229
msgid "No books found"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/catalog.py:59
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/catalog.py:59
msgid ""
"No books to catalog\n"
"Check exclude tags"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/catalog.py:69
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/catalog.py:69
msgid "Catalog generated."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/catalog.py:72
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/catalog.py:72
msgid "Export Catalog Directory"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/catalog.py:73
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/catalog.py:73
msgid "Select destination for %s.%s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/choose_library.py:81
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/toolbar.py:51
-#: /home/kovid/work/calibre/src/calibre/library/server/opds.py:111
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/choose_library.py:81
+#: /home/kovid/work/trunk/src/calibre/gui2/preferences/toolbar.py:51
+#: /home/kovid/work/trunk/src/calibre/library/server/opds.py:111
msgid "%d books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/choose_library.py:82
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/choose_library.py:82
msgid "Choose calibre library to work with"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/choose_library.py:91
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/choose_library.py:91
msgid "Switch/create library..."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/choose_library.py:99
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/choose_library.py:99
msgid "Quick switch"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/choose_library.py:101
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/choose_library.py:101
msgid "Rename library"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/choose_library.py:103
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/choose_library.py:103
msgid "Delete library"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/choose_library.py:168
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/choose_library.py:168
msgid "Rename"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/choose_library.py:169
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/choose_library.py:169
msgid "Choose a new name for the library %s. "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/choose_library.py:170
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/choose_library.py:170
msgid "Note that the actual library folder will be renamed."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/choose_library.py:177
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:185
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/choose_library.py:177
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:185
msgid "Already exists"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/choose_library.py:178
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/choose_library.py:178
msgid "The folder %s already exists. Delete it first."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/choose_library.py:184
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/choose_library.py:184
msgid "Rename failed"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/choose_library.py:185
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/choose_library.py:185
msgid "Failed to rename the library at %s. The most common cause for this is if one of the files in the library is open in another program."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/choose_library.py:195
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/confirm_delete_ui.py:53
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/columns.py:102
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/choose_library.py:195
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/confirm_delete_ui.py:53
+#: /home/kovid/work/trunk/src/calibre/gui2/preferences/columns.py:102
msgid "Are you sure?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/choose_library.py:196
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/choose_library.py:196
msgid "All files from %s will be permanently deleted. Are you sure?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/choose_library.py:216
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/choose_library.py:216
msgid "No library found"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/choose_library.py:217
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/choose_library.py:217
msgid "No existing calibre library was found at %s. It will be removed from the list of known libraries."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/choose_library.py:249
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/choose_library.py:254
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:101
-#: /home/kovid/work/calibre/src/calibre/gui2/library/views.py:584
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/choose_library.py:249
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/choose_library.py:254
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/save_to_disk.py:101
+#: /home/kovid/work/trunk/src/calibre/gui2/library/views.py:584
msgid "Not allowed"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/choose_library.py:250
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/choose_library.py:250
msgid "You cannot change libraries when a device is connected."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/choose_library.py:255
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/choose_library.py:255
msgid "You cannot change libraries while jobs are running."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/convert.py:22
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/convert.py:22
msgid "C"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/convert.py:22
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/convert.py:22
msgid "Convert books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/convert.py:28
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/convert.py:28
msgid "Convert individually"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/convert.py:30
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/convert.py:30
msgid "Bulk convert"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/convert.py:86
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/convert.py:86
msgid "Cannot convert"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/convert.py:115
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/convert.py:115
msgid "Starting conversion of %d book(s)"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/copy_to_library.py:79
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/copy_to_library.py:79
msgid "Copy to library"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/copy_to_library.py:80
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/copy_to_library.py:80
msgid "Copy selected books to the specified library"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/copy_to_library.py:115
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/copy_to_library.py:115
msgid "Cannot copy"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/copy_to_library.py:120
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/copy_to_library.py:120
msgid "No library"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/copy_to_library.py:121
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/copy_to_library.py:121
msgid "No library found at %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/copy_to_library.py:124
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/copy_to_library.py:128
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/copy_to_library.py:124
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/copy_to_library.py:128
msgid "Copying"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/copy_to_library.py:138
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/copy_to_library.py:138
msgid "Could not copy books: "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/copy_to_library.py:138
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:670
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:428
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/copy_to_library.py:138
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:670
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk.py:428
msgid "Failed"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/copy_to_library.py:141
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/copy_to_library.py:141
msgid "Copied %d books to %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:18
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/delete.py:18
msgid "Del"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:18
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/delete.py:18
msgid "Remove books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:24
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/delete.py:24
msgid "Remove selected books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:26
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/delete.py:26
msgid "Remove files of a specific format from selected books.."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:29
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/delete.py:29
msgid "Remove all formats from selected books, except..."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:32
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/delete.py:32
msgid "Remove covers from selected books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:35
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/delete.py:35
msgid "Remove matching books from device"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:53
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/delete.py:53
msgid "Cannot delete"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:66
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/delete.py:66
msgid "Choose formats to be deleted"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:84
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/delete.py:84
msgid "Choose formats not to be deleted"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:104
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/delete.py:104
msgid "Cannot delete books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:105
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/delete.py:105
msgid "No device is connected"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:115
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/delete.py:115
msgid "Main memory"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:116
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:435
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:444
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/delete.py:116
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:435
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:444
msgid "Storage Card A"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:117
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:437
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:446
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/delete.py:117
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:437
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:446
msgid "Storage Card B"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:122
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/delete.py:122
msgid "No books to delete"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:123
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/delete.py:123
msgid "None of the selected books are on the device"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:140
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:195
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/delete.py:140
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/delete.py:195
msgid "Deleting books from device."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:161
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/delete.py:161
msgid "The selected books will be permanently deleted and the files removed from your calibre library. Are you sure?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:180
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/delete.py:180
msgid "The selected books will be permanently deleted from your device. Are you sure?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:26
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/device.py:26
msgid "Connect to folder"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:31
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/device.py:31
msgid "Connect to iTunes"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:40
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:48
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/device.py:40
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/device.py:48
msgid "Start Content Server"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:50
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/device.py:50
msgid "Stop Content Server"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:61
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:67
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:69
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/device.py:61
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/device.py:67
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/device.py:69
msgid "Email to"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:69
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/device.py:69
msgid " and delete from library"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:81
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/device.py:81
msgid "Setup email based sharing of books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:98
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/device.py:98
msgid "D"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:98
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/device.py:98
msgid "Send to device"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:117
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/device.py:117
msgid "Connect/share"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_collections.py:13
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_collections.py:13
msgid "Manage collections"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_collections.py:14
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_collections.py:14
msgid "Manage the collections on this device"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:24
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_metadata.py:24
msgid "E"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:24
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_metadata.py:24
msgid "Edit metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:28
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_metadata.py:28
msgid "Merge book records"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:29
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_metadata.py:29
msgid "M"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:31
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_metadata.py:31
msgid "Edit metadata individually"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:34
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_metadata.py:34
msgid "Edit metadata in bulk"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:37
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_metadata.py:37
msgid "Download metadata and covers"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:40
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_metadata.py:40
msgid "Download only metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:42
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_metadata.py:42
msgid "Download only covers"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:45
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_metadata.py:45
msgid "Download only social metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:51
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_metadata.py:51
msgid "Merge into first selected book - delete others"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:54
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_metadata.py:54
msgid "Merge into first selected book - keep others"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:75
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_metadata.py:75
msgid "Cannot download metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:98
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_metadata.py:98
msgid "social metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:100
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_metadata.py:100
msgid "covers"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:100
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_metadata.py:100
msgid "metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:105
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_metadata.py:105
msgid "Downloading %s for %d book(s)"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:126
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_metadata.py:126
msgid "Failed to download some metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:127
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_metadata.py:127
msgid "Failed to download metadata for the following:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:130
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_metadata.py:130
msgid "Failed to download metadata:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:131
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:607
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/misc.py:65
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/misc.py:112
-#: /home/kovid/work/calibre/src/calibre/utils/ipc/job.py:54
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_metadata.py:131
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:607
+#: /home/kovid/work/trunk/src/calibre/gui2/preferences/misc.py:65
+#: /home/kovid/work/trunk/src/calibre/gui2/preferences/misc.py:112
+#: /home/kovid/work/trunk/src/calibre/utils/ipc/job.py:54
msgid "Error"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:141
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:179
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_metadata.py:141
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_metadata.py:179
msgid "Cannot edit metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:207
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:210
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_metadata.py:207
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_metadata.py:210
msgid "Cannot merge books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:211
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_metadata.py:211
msgid "At least two books must be selected for merging"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:215
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_metadata.py:215
msgid "Book formats and metadata from the selected books will be added to the first selected book. ISBN will not be merged.
The second and subsequently selected books will not be deleted or changed.
Please confirm you want to proceed."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:227
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_metadata.py:227
msgid "Book formats and metadata from the selected books will be merged into the first selected book. ISBN will not be merged.
After merger the second and subsequently selected books will be deleted.
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 deleted from your computer.
Are you sure you want to proceed?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:240
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/edit_metadata.py:240
msgid "You are about to merge more than 5 books. Are you sure you want to proceed?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/fetch_news.py:18
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/fetch_news.py:18
msgid "F"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/fetch_news.py:18
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/fetch_news.py:18
msgid "Fetch news"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/fetch_news.py:53
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/fetch_news.py:53
msgid "Fetching news from "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/fetch_news.py:67
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/fetch_news.py:67
msgid " fetched."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/help.py:16
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/help.py:16
msgid "Browse the calibre User Manual"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/help.py:16
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/help.py:16
msgid "F1"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/help.py:16
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/help.py:16
msgid "Help"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/open.py:14
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/open.py:14
msgid "Open containing folder"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/open.py:15
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/open.py:15
msgid "O"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/preferences.py:17
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/preferences.py:17
msgid "Ctrl+P"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/preferences.py:23
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/preferences.py:23
msgid "Run welcome wizard"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/preferences.py:33
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/preferences.py:38
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/preferences.py:33
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/preferences.py:38
msgid "Cannot configure"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/preferences.py:34
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/preferences.py:34
msgid "Cannot configure while there are running jobs."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/preferences.py:39
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/preferences.py:39
msgid "Cannot configure before calibre is restarted."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/restart.py:14
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/restart.py:14
msgid "&Restart"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/restart.py:14
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/restart.py:14
msgid "Ctrl+R"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:24
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/save_to_disk.py:24
msgid "Save single format to disk..."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:40
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/save_to_disk.py:40
msgid "S"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:40
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:46
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/save_to_disk.py:40
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/save_to_disk.py:46
msgid "Save to disk"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:48
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/save_to_disk.py:48
msgid "Save to disk in a single directory"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:50
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:69
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/save_to_disk.py:50
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/save_to_disk.py:69
msgid "Save only %s format to disk"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:54
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:72
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/save_to_disk.py:54
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/save_to_disk.py:72
msgid "Save only %s format to disk in a single directory"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:91
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/save_to_disk.py:91
msgid "Cannot save to disk"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:94
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/save_to_disk.py:94
msgid "Choose destination directory"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:102
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/save_to_disk.py:102
msgid "You are trying to save files into the calibre library. This can cause corruption of your library. Save to disk is meant to export files from your calibre library elsewhere."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:136
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/save_to_disk.py:136
msgid "Error while saving"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:137
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/save_to_disk.py:137
msgid "There was an error while saving."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:144
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:145
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/save_to_disk.py:144
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/save_to_disk.py:145
msgid "Could not save some books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:146
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/save_to_disk.py:146
msgid "Click the show details button to see which ones."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/show_book_details.py:16
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/show_book_details.py:16
msgid "Show book details"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/show_book_details.py:17
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/show_book_details.py:17
msgid "I"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/show_book_details.py:26
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/show_book_details.py:26
msgid "No detailed info available"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/show_book_details.py:27
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/show_book_details.py:27
msgid "No detailed information is available for books on the device."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/similar_books.py:17
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/similar_books.py:17
msgid "Similar books..."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/similar_books.py:24
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/similar_books.py:24
msgid "Alt+A"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/similar_books.py:24
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/similar_books.py:24
msgid "Books by same author"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/similar_books.py:25
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/similar_books.py:25
msgid "Books in this series"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/similar_books.py:26
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/similar_books.py:26
msgid "Alt+Shift+S"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/similar_books.py:27
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/similar_books.py:27
msgid "Alt+P"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/similar_books.py:27
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/similar_books.py:27
msgid "Books by this publisher"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/similar_books.py:28
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/similar_books.py:28
msgid "Alt+T"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/similar_books.py:28
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/similar_books.py:28
msgid "Books with the same tags"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/tweak_epub.py:15
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tweak_epub_ui.py:54
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/tweak_epub.py:15
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tweak_epub_ui.py:54
msgid "Tweak ePub"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/tweak_epub.py:16
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/tweak_epub.py:16
msgid "Make small changes to ePub format books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/tweak_epub.py:17
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/tweak_epub.py:17
msgid "T"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/tweak_epub.py:27
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/tweak_epub.py:39
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/tweak_epub.py:27
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/tweak_epub.py:39
msgid "Cannot tweak ePub"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/tweak_epub.py:40
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/tweak_epub.py:40
msgid "No ePub available. First convert the book to ePub."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/view.py:24
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/view.py:24
msgid "V"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/view.py:24
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/view.py:32
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/view.py:24
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/view.py:32
msgid "View"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/view.py:33
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/view.py:33
msgid "View specific format"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/view.py:95
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/view.py:156
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/view.py:95
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/view.py:156
msgid "Cannot view"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/view.py:101
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/regex_builder.py:77
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/view.py:101
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/regex_builder.py:77
msgid "Choose the format to view"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/view.py:109
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/view.py:109
msgid "Multiple Books Selected"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/view.py:110
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/view.py:110
msgid "You are attempting to open %d books. Opening too many books at once can be slow and have a negative effect on the responsiveness of your computer. Once started the process cannot be stopped until complete. Do you wish to continue?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/view.py:119
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/view.py:119
msgid "Cannot open folder"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/view.py:157
+#: /home/kovid/work/trunk/src/calibre/gui2/actions/view.py:157
msgid "%s has no available formats."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/add.py:54
+#: /home/kovid/work/trunk/src/calibre/gui2/add.py:54
msgid "Searching in"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/add.py:197
+#: /home/kovid/work/trunk/src/calibre/gui2/add.py:197
msgid "Adding..."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/add.py:210
+#: /home/kovid/work/trunk/src/calibre/gui2/add.py:210
msgid "Searching in all sub-directories..."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/add.py:223
+#: /home/kovid/work/trunk/src/calibre/gui2/add.py:223
msgid "Path error"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/add.py:224
+#: /home/kovid/work/trunk/src/calibre/gui2/add.py:224
msgid "The specified directory could not be processed."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/add.py:228
-#: /home/kovid/work/calibre/src/calibre/gui2/device.py:811
+#: /home/kovid/work/trunk/src/calibre/gui2/add.py:228
+#: /home/kovid/work/trunk/src/calibre/gui2/device.py:811
msgid "No books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/add.py:293
+#: /home/kovid/work/trunk/src/calibre/gui2/add.py:293
msgid "Added"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/add.py:306
+#: /home/kovid/work/trunk/src/calibre/gui2/add.py:306
msgid "Adding failed"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/add.py:307
+#: /home/kovid/work/trunk/src/calibre/gui2/add.py:307
msgid "The add books process seems to have hung. Try restarting calibre and adding the books in smaller increments, until you find the problem book."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/add.py:322
+#: /home/kovid/work/trunk/src/calibre/gui2/add.py:322
msgid "Duplicates found!"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/add.py:323
+#: /home/kovid/work/trunk/src/calibre/gui2/add.py:323
msgid "Books with the same title as the following already exist in the database. Add them anyway?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/add.py:326
+#: /home/kovid/work/trunk/src/calibre/gui2/add.py:326
msgid "Adding duplicates..."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/add.py:393
+#: /home/kovid/work/trunk/src/calibre/gui2/add.py:393
msgid "Saving..."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/add.py:446
+#: /home/kovid/work/trunk/src/calibre/gui2/add.py:446
msgid "Saved"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/__init__.py:57
+#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/__init__.py:57
msgid "Searching for sub-folders"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/__init__.py:62
+#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/__init__.py:62
msgid "Searching for books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/__init__.py:74
+#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/__init__.py:74
msgid "Looking for duplicates based on file hash"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/__init__.py:109
-#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/welcome_ui.py:70
+#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/__init__.py:109
+#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/welcome_ui.py:70
msgid "Choose root folder"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/__init__.py:137
+#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/__init__.py:137
msgid "Invalid root folder"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/__init__.py:138
+#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/__init__.py:138
msgid "is not a valid root folder"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/__init__.py:148
+#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/__init__.py:148
msgid "Add books to calibre"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/scan_ui.py:21
-#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/welcome_ui.py:62
-#: /home/kovid/work/calibre/src/calibre/gui2/wizard/finish_ui.py:41
-#: /home/kovid/work/calibre/src/calibre/gui2/wizard/kindle_ui.py:41
-#: /home/kovid/work/calibre/src/calibre/gui2/wizard/library_ui.py:49
-#: /home/kovid/work/calibre/src/calibre/gui2/wizard/stanza_ui.py:41
+#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/scan_ui.py:21
+#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/welcome_ui.py:62
+#: /home/kovid/work/trunk/src/calibre/gui2/wizard/finish_ui.py:41
+#: /home/kovid/work/trunk/src/calibre/gui2/wizard/kindle_ui.py:41
+#: /home/kovid/work/trunk/src/calibre/gui2/wizard/library_ui.py:49
+#: /home/kovid/work/trunk/src/calibre/gui2/wizard/stanza_ui.py:41
msgid "WizardPage"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/scan_ui.py:22
+#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/scan_ui.py:22
msgid "Scanning root folder for books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/scan_ui.py:23
+#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/scan_ui.py:23
msgid "This may take a few minutes"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/welcome_ui.py:63
+#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/welcome_ui.py:63
msgid "Choose the location to add books from"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/welcome_ui.py:64
+#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/welcome_ui.py:64
msgid "Select a folder on your hard disk"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/welcome_ui.py:65
+#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/welcome_ui.py:65
msgid ""
"
"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata.py:189
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:134
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata.py:189
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:134
msgid " is not a valid picture"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:172
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:413
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:172
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:413
msgid "Book Cover"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:173
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:173
msgid "Use cover from &source file"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:174
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:414
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:174
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:414
msgid "Change &cover image:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:175
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:175
msgid "Browse for an image to use as the cover of this book."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:177
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:372
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:177
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:372
msgid "&Title: "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:178
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:373
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:178
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:373
msgid "Change the title of this book"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:179
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:230
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:376
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:179
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:230
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:376
msgid "&Author(s): "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:180
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:180
msgid "Author So&rt:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:181
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:181
msgid "Change the author(s) of this book. Multiple authors should be separated by a comma"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:182
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:239
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:387
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:182
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:239
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:387
msgid "&Publisher: "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:183
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:388
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:183
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:388
msgid "Ta&gs: "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:184
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:241
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:389
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:184
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:241
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:389
msgid "Tags categorize the book. This is particularly useful while searching.
They can be any words or phrases, separated by commas."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:185
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:248
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:392
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:185
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:248
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:392
msgid "&Series:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:186
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:187
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:249
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:250
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:393
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:394
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:186
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:187
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:249
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:250
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:393
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:394
msgid "List of known series. You can add new series."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:188
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:399
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:188
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:399
msgid "Book "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output.py:20
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/mobi_output.py:20
msgid "MOBI Output"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output.py:43
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/mobi_output.py:43
msgid "Default"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output_ui.py:67
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/mobi_output_ui.py:67
msgid "&Title for Table of Contents:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output_ui.py:68
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/mobi_output_ui.py:68
msgid "Rescale images for &Palm devices"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output_ui.py:69
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/mobi_output_ui.py:69
msgid "Use author &sort for author"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output_ui.py:70
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/mobi_output_ui.py:70
msgid "Disable compression of the file contents"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output_ui.py:71
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/mobi_output_ui.py:71
msgid "Do not add Table of Contents to book"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output_ui.py:72
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/mobi_output_ui.py:72
msgid "Kindle options"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output_ui.py:73
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/mobi_output_ui.py:73
msgid "Periodical masthead font:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output_ui.py:74
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/mobi_output_ui.py:74
msgid "Personal Doc tag:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/page_setup.py:35
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/page_setup.py:35
msgid "Page Setup"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/page_setup_ui.py:116
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/page_setup_ui.py:116
msgid "&Output profile:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/page_setup_ui.py:117
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/page_setup_ui.py:117
msgid "Profile description"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/page_setup_ui.py:118
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/page_setup_ui.py:118
msgid "&Input profile:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/page_setup_ui.py:119
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/page_setup_ui.py:119
msgid "Margins"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/page_setup_ui.py:120
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/page_setup_ui.py:120
msgid "&Left:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/page_setup_ui.py:122
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/page_setup_ui.py:122
msgid "&Top:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/page_setup_ui.py:124
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/page_setup_ui.py:124
msgid "&Right:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/page_setup_ui.py:126
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/page_setup_ui.py:126
msgid "&Bottom:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_input.py:12
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdb_input.py:12
msgid "PDB Input"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_input_ui.py:32
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_input_ui.py:47
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdb_input_ui.py:32
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/txt_input_ui.py:47
msgid "Treat each &line as a paragraph"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_input_ui.py:33
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_input_ui.py:48
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdb_input_ui.py:33
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/txt_input_ui.py:48
msgid "Assume print formatting"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_output.py:16
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdb_output.py:16
msgid "PDB Output"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_output_ui.py:36
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdb_output_ui.py:36
msgid "&Format:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_input.py:12
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdf_input.py:12
msgid "PDF Input"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_input_ui.py:39
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdf_input_ui.py:39
msgid "Line &Un-Wrapping Factor:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_input_ui.py:40
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdf_input_ui.py:40
msgid "No &Images"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_output.py:17
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdf_output.py:17
msgid "PDF Output"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_output_ui.py:43
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdf_output_ui.py:43
msgid "&Paper Size:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_output_ui.py:44
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdf_output_ui.py:44
msgid "&Orientation:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_output_ui.py:45
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdf_output_ui.py:45
msgid "Preserve &aspect ratio of cover"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/rb_output.py:14
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/rb_output.py:14
msgid "RB Output"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/regex_builder.py:83
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/regex_builder.py:83
msgid "No formats available"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/regex_builder.py:84
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/regex_builder.py:84
msgid "Cannot build regex using the GUI builder without a book."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/regex_builder.py:103
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/regex_builder.py:103
msgid "Open book"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/regex_builder_ui.py:52
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/regex_builder_ui.py:52
msgid "Regex Builder"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/regex_builder_ui.py:53
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/regex_builder_ui.py:53
msgid "Preview"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/regex_builder_ui.py:54
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/regex_builder_ui.py:54
msgid "Regex:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/regex_builder_ui.py:55
-#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:122
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/regex_builder_ui.py:55
+#: /home/kovid/work/trunk/src/calibre/gui2/filename_pattern_ui.py:122
msgid "Test"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/single.py:171
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/single.py:171
msgid "Convert"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/single.py:196
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/single.py:196
msgid "Options specific to the input format."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/single_ui.py:117
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info_ui.py:69
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comicconf_ui.py:96
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/progress_ui.py:53
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/single_ui.py:117
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/book_info_ui.py:69
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/comicconf_ui.py:96
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/progress_ui.py:53
msgid "Dialog"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/single_ui.py:118
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/single_ui.py:118
msgid "&Input format:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/single_ui.py:119
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/single_ui.py:119
msgid "Use &saved conversion settings for individual books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:17
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection.py:17
msgid ""
"Structure\n"
"Detection"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:19
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection.py:19
msgid "Fine tune the detection of chapter headings and other document structure."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:37
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection.py:37
msgid "Detect chapters at (XPath expression):"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:38
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection.py:38
msgid "Insert page breaks before (XPath expression):"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:40
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection.py:40
msgid "Header regular expression:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:43
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection.py:43
msgid "Footer regular expression:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:59
-#: /home/kovid/work/calibre/src/calibre/gui2/widgets.py:87
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection.py:59
+#: /home/kovid/work/trunk/src/calibre/gui2/widgets.py:87
msgid "Invalid regular expression"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:60
-#: /home/kovid/work/calibre/src/calibre/gui2/widgets.py:88
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection.py:60
+#: /home/kovid/work/trunk/src/calibre/gui2/widgets.py:88
msgid "Invalid regular expression: %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:65
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/toc.py:39
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection.py:65
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/toc.py:39
msgid "Invalid XPath"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:66
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/toc.py:40
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection.py:66
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/toc.py:40
msgid "The XPath expression %s is invalid."
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:81
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection_ui.py:81
msgid "Chapter &mark:"
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:82
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection_ui.py:82
msgid "Remove first &image"
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:83
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection_ui.py:83
msgid "Insert &metadata as page at start of book"
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:84
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection_ui.py:84
msgid "Remove F&ooter"
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:85
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection_ui.py:85
msgid "Remove H&eader"
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:86
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection_ui.py:86
msgid "Line &un-wrap factor during preprocess:"
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:87
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection_ui.py:87
msgid "&Preprocess input file to possibly improve structure detection"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/toc.py:16
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/toc.py:16
msgid ""
"Table of\n"
"Contents"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/toc.py:18
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/toc.py:18
msgid "Control the creation/conversion of the Table of Contents."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/toc.py:30
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/toc.py:30
msgid "Level &1 TOC (XPath expression):"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/toc.py:31
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/toc.py:31
msgid "Level &2 TOC (XPath expression):"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/toc.py:32
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/toc.py:32
msgid "Level &3 TOC (XPath expression):"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/toc_ui.py:63
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/toc_ui.py:63
msgid "Do not add &detected chapters to the Table of Contents"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/toc_ui.py:64
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/toc_ui.py:64
msgid "Number of &links to add to Table of Contents"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/toc_ui.py:65
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/toc_ui.py:65
msgid "Chapter &threshold"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/toc_ui.py:66
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/toc_ui.py:66
msgid "&Force use of auto-generated Table of Contents"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/toc_ui.py:67
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/toc_ui.py:67
msgid "TOC &Filter:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_input.py:12
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/txt_input.py:12
msgid "TXT Input"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_input_ui.py:49
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/txt_input_ui.py:49
msgid "Process using markdown"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_input_ui.py:50
+#: /home/kovid/work/trunk/src/calibre/gui2/convert/txt_input_ui.py:50
msgid "
"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:646
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:646
msgid "The download timed out."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:650
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:650
msgid "Could not find cover for this book. Try specifying the ISBN first."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:662
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:662
msgid "For the error message from each cover source, click Show details below."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:669
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:669
msgid "Bad cover"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:670
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:670
msgid "The cover is not a valid picture"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:703
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:703
msgid "There were errors"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:704
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:704
msgid "There were errors downloading social metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:733
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:733
msgid "Cannot fetch metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:734
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:734
msgid "You must specify at least one of ISBN, Title, Authors or Publisher"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:820
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:820
msgid "Permission denied"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:821
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:821
msgid "Could not open %s. Is it being used by another program?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:370
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:370
msgid "Edit Meta Information"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:371
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:371
msgid "Meta information"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:374
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:374
msgid "Swap the author and title"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:377
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:377
msgid "Author S&ort: "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:378
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:378
msgid ""
"Specify how the author(s) of this book should be sorted. For example Charles Dickens should be sorted as Dickens, Charles.\n"
"If the box is colored green, then text matches the individual author's sort strings. If it is colored red, then the authors and this text do not match."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:380
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:380
msgid ""
"Automatically create the author sort entry based on the current author entry.\n"
"Using this button to create author sort will change author sort from red to green."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:395
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:395
msgid "Remove unused series (Series that have no books)"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:397
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:397
msgid "IS&BN:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:398
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:398
msgid "Publishe&d:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:401
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:401
msgid "dd MMM yyyy"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:402
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:402
msgid "&Date:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:403
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:403
msgid "&Comments"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:404
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:404
msgid "&Fetch metadata from server"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:405
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:405
msgid "Available Formats"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:406
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:406
msgid "Add a new format for this book to the database"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:408
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:408
msgid "Remove the selected formats for this book from the database."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:410
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:410
msgid "Set the cover for the book from the selected format"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:412
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:412
msgid "Update metadata from the metadata in the selected format"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:415
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:415
msgid "&Browse"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:416
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:416
msgid "Remove border (if any) from cover"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:417
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:417
msgid "Reset cover to default"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:419
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:419
msgid "Download co&ver"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:420
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:420
msgid "Generate a default cover based on the title and author"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:421
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:421
msgid "&Generate cover"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/password_ui.py:61
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/password_ui.py:61
msgid "Password needed"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/password_ui.py:63
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:217
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/server_ui.py:125
-#: /home/kovid/work/calibre/src/calibre/gui2/wizard/send_email_ui.py:117
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/password_ui.py:63
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:217
+#: /home/kovid/work/trunk/src/calibre/gui2/preferences/server_ui.py:125
+#: /home/kovid/work/trunk/src/calibre/gui2/wizard/send_email_ui.py:117
msgid "&Username:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/password_ui.py:64
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:218
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/server_ui.py:126
-#: /home/kovid/work/calibre/src/calibre/gui2/wizard/send_email_ui.py:119
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/password_ui.py:64
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:218
+#: /home/kovid/work/trunk/src/calibre/gui2/preferences/server_ui.py:126
+#: /home/kovid/work/trunk/src/calibre/gui2/wizard/send_email_ui.py:119
msgid "&Password:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/password_ui.py:65
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:219
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/server_ui.py:130
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/password_ui.py:65
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:219
+#: /home/kovid/work/trunk/src/calibre/gui2/preferences/server_ui.py:130
msgid "&Show password"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/progress.py:59
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/progress.py:59
msgid "Aborting..."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/progress.py:76
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/progress.py:76
msgid "Working"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/saved_search_editor.py:54
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/saved_search_editor.py:54
msgid "The current saved search will be permanently deleted. Are you sure?"
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/saved_search_editor_ui.py:88
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/saved_search_editor_ui.py:88
msgid "Saved Search Editor"
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/saved_search_editor_ui.py:89
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/saved_search_editor_ui.py:89
msgid "Saved Search: "
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/saved_search_editor_ui.py:90
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/saved_search_editor_ui.py:90
msgid "Select a saved search to edit"
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/saved_search_editor_ui.py:91
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/saved_search_editor_ui.py:91
msgid "Delete this selected saved search"
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/saved_search_editor_ui.py:93
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/saved_search_editor_ui.py:93
msgid "Enter a new saved search name."
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/saved_search_editor_ui.py:94
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/saved_search_editor_ui.py:94
msgid "Add the new saved search"
msgstr ""
#:
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/saved_search_editor_ui.py:96
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/saved_search_editor_ui.py:96
msgid "Change the contents of the saved search"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:120
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler.py:120
msgid "Need username and password"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:121
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler.py:121
msgid "You must provide a username and/or password to use this news source."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:172
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler.py:172
msgid "Created by: "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:179
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler.py:179
msgid "Last downloaded: never"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:194
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler.py:194
msgid "%d days, %d hours and %d minutes ago"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:196
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler.py:196
msgid "Last downloaded"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:220
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:197
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler.py:220
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:197
msgid "Schedule news download"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:223
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler.py:223
msgid "Add a custom news source"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:228
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler.py:228
msgid "Download all scheduled new sources"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:328
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler.py:328
msgid "No internet connection"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:329
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler.py:329
msgid "Cannot download news as no internet connection is active"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:198
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:278
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:198
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:278
msgid "Recipes"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:199
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:199
msgid "Download all scheduled recipes at once"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:200
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:200
msgid "Download &all scheduled"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:201
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:201
msgid "blurb"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:202
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:202
msgid "&Schedule for download:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:203
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:213
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:203
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:213
msgid "Every "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:204
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:204
msgid "day"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:205
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:205
msgid "Monday"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:206
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:206
msgid "Tuesday"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:207
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:207
msgid "Wednesday"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:208
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:208
msgid "Thursday"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:209
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:209
msgid "Friday"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:210
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:210
msgid "Saturday"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:211
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:211
msgid "Sunday"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:212
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:212
msgid "at"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:214
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:214
msgid "Interval at which to download this recipe. A value of zero means that the recipe will be downloaded every hour."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:215
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:227
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles_ui.py:268
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:215
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:227
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles_ui.py:268
msgid " days"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:216
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:216
msgid "&Account"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:220
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:220
msgid "For the scheduling to work, you must leave calibre running."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:221
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:221
msgid "&Schedule"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:222
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:222
msgid "Add &title as tag"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:223
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:223
msgid "&Extra tags:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:224
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:224
msgid "&Advanced"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:225
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:225
msgid "&Download now"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:226
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:226
msgid "Delete downloaded news older than the specified number of days. Set to zero to disable."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:228
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:228
msgid "Delete downloaded news older than "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_item_ui.py:36
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_item_ui.py:36
msgid "contains"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_item_ui.py:37
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_item_ui.py:37
msgid "The text to search for. It is interpreted as a regular expression."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_item_ui.py:38
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_item_ui.py:38
msgid "
%s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:241
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:263
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:290
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:241
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:263
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:290
msgid "Replace recipe?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:242
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:264
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:291
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:242
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:264
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:291
msgid "A custom recipe named %s already exists. Do you want to replace it?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:257
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:257
msgid "Pick recipe"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:257
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:257
msgid "Pick the recipe to customize"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:277
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:277
msgid "Choose a recipe file"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles_ui.py:253
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles_ui.py:253
msgid "Add custom news source"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles_ui.py:254
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles_ui.py:254
msgid "Available user recipes"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles_ui.py:255
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles_ui.py:255
msgid "Add/Update &recipe"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles_ui.py:256
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles_ui.py:256
msgid "&Remove recipe"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles_ui.py:257
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles_ui.py:257
msgid "&Share recipe"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles_ui.py:258
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles_ui.py:258
msgid "Customize &builtin recipe"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles_ui.py:259
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles_ui.py:259
msgid "&Load recipe from file"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles_ui.py:261
+#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles_ui.py:261
msgid ""
"