From e243aeeafff8a3db15b1f53b5baf2d38b6c8a39c Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 11 Aug 2010 21:36:26 -0600 Subject: [PATCH 01/28] Split gui actions into separate files --- src/calibre/gui2/actions/__init__.py | 1361 ------------------- src/calibre/gui2/actions/add.py | 241 ++++ src/calibre/gui2/actions/annotate.py | 235 ++++ src/calibre/gui2/actions/catalog.py | 69 + src/calibre/gui2/actions/convert.py | 148 ++ src/calibre/gui2/actions/delete.py | 165 +++ src/calibre/gui2/actions/edit_metadata.py | 311 +++++ src/calibre/gui2/actions/fetch_news.py | 39 + src/calibre/gui2/actions/save_to_disk.py | 95 ++ src/calibre/gui2/actions/view.py | 159 +++ src/calibre/gui2/add.py | 2 +- src/calibre/gui2/dialogs/metadata_single.py | 5 +- src/calibre/gui2/dialogs/progress.py | 8 +- 13 files changed, 1471 insertions(+), 1367 deletions(-) create mode 100644 src/calibre/gui2/actions/add.py create mode 100644 src/calibre/gui2/actions/annotate.py create mode 100644 src/calibre/gui2/actions/catalog.py create mode 100644 src/calibre/gui2/actions/convert.py create mode 100644 src/calibre/gui2/actions/delete.py create mode 100644 src/calibre/gui2/actions/edit_metadata.py create mode 100644 src/calibre/gui2/actions/fetch_news.py create mode 100644 src/calibre/gui2/actions/save_to_disk.py create mode 100644 src/calibre/gui2/actions/view.py diff --git a/src/calibre/gui2/actions/__init__.py b/src/calibre/gui2/actions/__init__.py index f70332d15a..96aaa843a0 100644 --- a/src/calibre/gui2/actions/__init__.py +++ b/src/calibre/gui2/actions/__init__.py @@ -5,1368 +5,7 @@ __license__ = 'GPL v3' __copyright__ = '2010, Kovid Goyal ' __docformat__ = 'restructuredtext en' -import shutil, os, datetime, time -from functools import partial -from PyQt4.Qt import QInputDialog, pyqtSignal, QModelIndex, QThread, Qt, \ - SIGNAL, QPixmap, QTimer, QDialog -from calibre import strftime -from calibre.ptempfile import PersistentTemporaryFile -from calibre.utils.config import prefs, dynamic -from calibre.gui2 import error_dialog, Dispatcher, gprefs, choose_files, \ - choose_dir, warning_dialog, info_dialog, question_dialog, config, \ - open_local_file -from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag, NavigableString -from calibre.utils.filenames import ascii_filename -from calibre.gui2.widgets import IMAGE_EXTENSIONS -from calibre.gui2.dialogs.metadata_single import MetadataSingleDialog -from calibre.gui2.dialogs.metadata_bulk import MetadataBulkDialog -from calibre.gui2.dialogs.tag_list_editor import TagListEditor -from calibre.gui2.tools import convert_single_ebook, convert_bulk_ebook, \ - fetch_scheduled_recipe, generate_catalog -from calibre.constants import preferred_encoding, filesystem_encoding, \ - isosx -from calibre.gui2.dialogs.choose_format import ChooseFormatDialog -from calibre.ebooks import BOOK_EXTENSIONS -from calibre.gui2.dialogs.confirm_delete import confirm -from calibre.gui2.dialogs.delete_matching_from_device import DeleteMatchingFromDeviceDialog -class AnnotationsAction(object): # {{{ - - def fetch_annotations(self, *args): - # Generate a path_map from selected ids - def get_ids_from_selected_rows(): - rows = self.library_view.selectionModel().selectedRows() - if not rows or len(rows) < 2: - rows = xrange(self.library_view.model().rowCount(QModelIndex())) - ids = map(self.library_view.model().id, rows) - return ids - - def get_formats(id): - formats = db.formats(id, index_is_id=True) - fmts = [] - if formats: - for format in formats.split(','): - fmts.append(format.lower()) - return fmts - - def generate_annotation_paths(ids, db, device): - # Generate path templates - # Individual storage mount points scanned/resolved in driver.get_annotations() - path_map = {} - for id in ids: - mi = db.get_metadata(id, index_is_id=True) - a_path = device.create_upload_path(os.path.abspath('/'), mi, 'x.bookmark', create_dirs=False) - path_map[id] = dict(path=a_path, fmts=get_formats(id)) - return path_map - - device = self.device_manager.device - - if self.current_view() is not self.library_view: - return error_dialog(self, _('Use library only'), - _('User annotations generated from main library only'), - show=True) - db = self.library_view.model().db - - # Get the list of ids - ids = get_ids_from_selected_rows() - if not ids: - return error_dialog(self, _('No books selected'), - _('No books selected to fetch annotations from'), - show=True) - - # Map ids to paths - path_map = generate_annotation_paths(ids, db, device) - - # Dispatch to devices.kindle.driver.get_annotations() - self.device_manager.annotations(Dispatcher(self.annotations_fetched), - path_map) - - def annotations_fetched(self, job): - from calibre.devices.usbms.device import Device - from calibre.ebooks.metadata import MetaInformation - from calibre.gui2.dialogs.progress import ProgressDialog - from calibre.library.cli import do_add_format - - class Updater(QThread): - - update_progress = pyqtSignal(int) - update_done = pyqtSignal() - FINISHED_READING_PCT_THRESHOLD = 96 - - def __init__(self, parent, db, annotation_map, done_callback): - QThread.__init__(self, parent) - self.db = db - self.pd = ProgressDialog(_('Merging user annotations into database'), '', - 0, len(job.result), parent=parent) - - self.am = annotation_map - self.done_callback = done_callback - self.connect(self.pd, SIGNAL('canceled()'), self.canceled) - self.pd.setModal(True) - self.pd.show() - self.update_progress.connect(self.pd.set_value, - type=Qt.QueuedConnection) - self.update_done.connect(self.pd.hide, type=Qt.QueuedConnection) - - def generate_annotation_html(self, bookmark): - # Returns
...
- last_read_location = bookmark.last_read_location - timestamp = datetime.datetime.utcfromtimestamp(bookmark.timestamp) - percent_read = bookmark.percent_read - - ka_soup = BeautifulSoup() - dtc = 0 - divTag = Tag(ka_soup,'div') - divTag['class'] = 'user_annotations' - - # Add the last-read location - spanTag = Tag(ka_soup, 'span') - spanTag['style'] = 'font-weight:bold' - if bookmark.book_format == 'pdf': - spanTag.insert(0,NavigableString( - _("%s
Last Page Read: %d (%d%%)") % \ - (strftime(u'%x', timestamp.timetuple()), - last_read_location, - percent_read))) - else: - spanTag.insert(0,NavigableString( - _("%s
Last Page Read: Location %d (%d%%)") % \ - (strftime(u'%x', timestamp.timetuple()), - last_read_location, - percent_read))) - - divTag.insert(dtc, spanTag) - dtc += 1 - divTag.insert(dtc, Tag(ka_soup,'br')) - dtc += 1 - - if bookmark.user_notes: - user_notes = bookmark.user_notes - annotations = [] - - # Add the annotations sorted by location - # Italicize highlighted text - for location in sorted(user_notes): - if user_notes[location]['text']: - annotations.append( - _('Location %d • %s
%s
') % \ - (user_notes[location]['displayed_location'], - user_notes[location]['type'], - user_notes[location]['text'] if \ - user_notes[location]['type'] == 'Note' else \ - '%s' % user_notes[location]['text'])) - else: - if bookmark.book_format == 'pdf': - annotations.append( - _('Page %d • %s
') % \ - (user_notes[location]['displayed_location'], - user_notes[location]['type'])) - else: - annotations.append( - _('Location %d • %s
') % \ - (user_notes[location]['displayed_location'], - user_notes[location]['type'])) - - for annotation in annotations: - divTag.insert(dtc, annotation) - dtc += 1 - - ka_soup.insert(0,divTag) - return ka_soup - - def mark_book_as_read(self,id): - read_tag = gprefs.get('catalog_epub_mobi_read_tag') - if read_tag: - self.db.set_tags(id, [read_tag], append=True) - - def canceled(self): - self.pd.hide() - - def run(self): - ignore_tags = set(['Catalog','Clippings']) - for (i, id) in enumerate(self.am): - bm = Device.UserAnnotation(self.am[id][0],self.am[id][1]) - if bm.type == 'kindle_bookmark': - mi = self.db.get_metadata(id, index_is_id=True) - user_notes_soup = self.generate_annotation_html(bm.value) - if mi.comments: - a_offset = mi.comments.find('
') - ad_offset = mi.comments.find('
') - - if a_offset >= 0: - mi.comments = mi.comments[:a_offset] - if ad_offset >= 0: - mi.comments = mi.comments[:ad_offset] - if set(mi.tags).intersection(ignore_tags): - continue - if mi.comments: - hrTag = Tag(user_notes_soup,'hr') - hrTag['class'] = 'annotations_divider' - user_notes_soup.insert(0,hrTag) - - mi.comments += user_notes_soup.prettify() - else: - mi.comments = unicode(user_notes_soup.prettify()) - # Update library comments - self.db.set_comment(id, mi.comments) - - # Update 'read' tag except for Catalogs/Clippings - if bm.value.percent_read >= self.FINISHED_READING_PCT_THRESHOLD: - if not set(mi.tags).intersection(ignore_tags): - self.mark_book_as_read(id) - - # Add bookmark file to id - self.db.add_format_with_hooks(id, bm.value.bookmark_extension, - bm.value.path, index_is_id=True) - self.update_progress.emit(i) - elif bm.type == 'kindle_clippings': - # Find 'My Clippings' author=Kindle in database, or add - last_update = 'Last modified %s' % strftime(u'%x %X',bm.value['timestamp'].timetuple()) - mc_id = list(db.data.parse('title:"My Clippings"')) - if mc_id: - do_add_format(self.db, mc_id[0], 'TXT', bm.value['path']) - mi = self.db.get_metadata(mc_id[0], index_is_id=True) - mi.comments = last_update - self.db.set_metadata(mc_id[0], mi) - else: - mi = MetaInformation('My Clippings', authors = ['Kindle']) - mi.tags = ['Clippings'] - mi.comments = last_update - self.db.add_books([bm.value['path']], ['txt'], [mi]) - - self.update_done.emit() - self.done_callback(self.am.keys()) - - if not job.result: return - - if self.current_view() is not self.library_view: - return error_dialog(self, _('Use library only'), - _('User annotations generated from main library only'), - show=True) - db = self.library_view.model().db - - self.__annotation_updater = Updater(self, db, job.result, - Dispatcher(self.library_view.model().refresh_ids)) - self.__annotation_updater.start() - - # }}} - -class AddAction(object): # {{{ - - def __init__(self): - self._add_filesystem_book = Dispatcher(self.__add_filesystem_book) - - def add_recursive(self, single): - root = choose_dir(self, 'recursive book import root dir dialog', - 'Select root folder') - if not root: - return - from calibre.gui2.add import Adder - self._adder = Adder(self, - self.library_view.model().db, - Dispatcher(self._files_added), spare_server=self.spare_server) - self._adder.add_recursive(root, single) - - def add_recursive_single(self, *args): - ''' - Add books from the local filesystem to either the library or the device - recursively assuming one book per folder. - ''' - self.add_recursive(True) - - def add_recursive_multiple(self, *args): - ''' - Add books from the local filesystem to either the library or the device - recursively assuming multiple books per folder. - ''' - self.add_recursive(False) - - def add_empty(self, *args): - ''' - Add an empty book item to the library. This does not import any formats - from a book file. - ''' - num, ok = QInputDialog.getInt(self, _('How many empty books?'), - _('How many empty books should be added?'), 1, 1, 100) - if ok: - from calibre.ebooks.metadata import MetaInformation - for x in xrange(num): - self.library_view.model().db.import_book(MetaInformation(None), []) - self.library_view.model().books_added(num) - - def add_isbns(self, isbns): - from calibre.ebooks.metadata import MetaInformation - ids = set([]) - for x in isbns: - mi = MetaInformation(None) - mi.isbn = x - ids.add(self.library_view.model().db.import_book(mi, [])) - self.library_view.model().books_added(len(isbns)) - self.do_download_metadata(ids) - - - def files_dropped(self, paths): - to_device = self.stack.currentIndex() != 0 - self._add_books(paths, to_device) - - def files_dropped_on_book(self, event, paths): - accept = False - if self.current_view() is not self.library_view: - return - db = self.library_view.model().db - current_idx = self.library_view.currentIndex() - if not current_idx.isValid(): return - cid = db.id(current_idx.row()) - for path in paths: - ext = os.path.splitext(path)[1].lower() - if ext: - ext = ext[1:] - if ext in IMAGE_EXTENSIONS: - pmap = QPixmap() - pmap.load(path) - if not pmap.isNull(): - accept = True - db.set_cover(cid, pmap) - elif ext in BOOK_EXTENSIONS: - db.add_format_with_hooks(cid, ext, path, index_is_id=True) - accept = True - if accept: - event.accept() - self.library_view.model().current_changed(current_idx, current_idx) - - def __add_filesystem_book(self, paths, allow_device=True): - if isinstance(paths, basestring): - paths = [paths] - books = [path for path in map(os.path.abspath, paths) if os.access(path, - os.R_OK)] - - if books: - to_device = allow_device and self.stack.currentIndex() != 0 - self._add_books(books, to_device) - if to_device: - self.status_bar.show_message(\ - _('Uploading books to device.'), 2000) - - - def add_filesystem_book(self, paths, allow_device=True): - self._add_filesystem_book(paths, allow_device=allow_device) - - def add_from_isbn(self, *args): - from calibre.gui2.dialogs.add_from_isbn import AddFromISBN - d = AddFromISBN(self) - if d.exec_() == d.Accepted: - self.add_isbns(d.isbns) - - def add_books(self, *args): - ''' - Add books from the local filesystem to either the library or the device. - ''' - filters = [ - (_('Books'), BOOK_EXTENSIONS), - (_('EPUB Books'), ['epub']), - (_('LRF Books'), ['lrf']), - (_('HTML Books'), ['htm', 'html', 'xhtm', 'xhtml']), - (_('LIT Books'), ['lit']), - (_('MOBI Books'), ['mobi', 'prc', 'azw']), - (_('Topaz books'), ['tpz','azw1']), - (_('Text books'), ['txt', 'rtf']), - (_('PDF Books'), ['pdf']), - (_('Comics'), ['cbz', 'cbr', 'cbc']), - (_('Archives'), ['zip', 'rar']), - ] - to_device = self.stack.currentIndex() != 0 - if to_device: - filters = [(_('Supported books'), self.device_manager.device.FORMATS)] - - books = choose_files(self, 'add books dialog dir', 'Select books', - filters=filters) - if not books: - return - self._add_books(books, to_device) - - def _add_books(self, paths, to_device, on_card=None): - if on_card is None: - on_card = 'carda' if self.stack.currentIndex() == 2 else 'cardb' if self.stack.currentIndex() == 3 else None - if not paths: - return - from calibre.gui2.add import Adder - self.__adder_func = partial(self._files_added, on_card=on_card) - self._adder = Adder(self, - None if to_device else self.library_view.model().db, - Dispatcher(self.__adder_func), spare_server=self.spare_server) - self._adder.add(paths) - - def _files_added(self, paths=[], names=[], infos=[], on_card=None): - if paths: - self.upload_books(paths, - list(map(ascii_filename, names)), - infos, on_card=on_card) - self.status_bar.show_message( - _('Uploading books to device.'), 2000) - if getattr(self._adder, 'number_of_books_added', 0) > 0: - self.library_view.model().books_added(self._adder.number_of_books_added) - if hasattr(self, 'db_images'): - self.db_images.reset() - if getattr(self._adder, 'merged_books', False): - books = u'\n'.join([x if isinstance(x, unicode) else - x.decode(preferred_encoding, 'replace') for x in - self._adder.merged_books]) - info_dialog(self, _('Merged some books'), - _('Some duplicates were found and merged into the ' - 'following existing books:'), det_msg=books, show=True) - if getattr(self._adder, 'critical', None): - det_msg = [] - for name, log in self._adder.critical.items(): - if isinstance(name, str): - name = name.decode(filesystem_encoding, 'replace') - det_msg.append(name+'\n'+log) - - warning_dialog(self, _('Failed to read metadata'), - _('Failed to read metadata from the following')+':', - det_msg='\n\n'.join(det_msg), show=True) - - if hasattr(self._adder, 'cleanup'): - self._adder.cleanup() - self._adder = None - - def _add_from_device_adder(self, paths=[], names=[], infos=[], - on_card=None, model=None): - self._files_added(paths, names, infos, on_card=on_card) - # set the in-library flags, and as a consequence send the library's - # metadata for this book to the device. This sets the uuid to the - # correct value. - self.set_books_in_library(booklists=[model.db], reset=True) - model.reset() - - def add_books_from_device(self, view): - rows = view.selectionModel().selectedRows() - if not rows or len(rows) == 0: - d = error_dialog(self, _('Add to library'), _('No book selected')) - d.exec_() - return - paths = [p for p in view._model.paths(rows) if p is not None] - ve = self.device_manager.device.VIRTUAL_BOOK_EXTENSIONS - def ext(x): - ans = os.path.splitext(x)[1] - ans = ans[1:] if len(ans) > 1 else ans - return ans.lower() - remove = set([p for p in paths if ext(p) in ve]) - if remove: - paths = [p for p in paths if p not in remove] - info_dialog(self, _('Not Implemented'), - _('The following books are virtual and cannot be added' - ' to the calibre library:'), '\n'.join(remove), - show=True) - if not paths: - return - if not paths or len(paths) == 0: - d = error_dialog(self, _('Add to library'), _('No book files found')) - d.exec_() - return - from calibre.gui2.add import Adder - self.__adder_func = partial(self._add_from_device_adder, on_card=None, - model=view._model) - self._adder = Adder(self, self.library_view.model().db, - Dispatcher(self.__adder_func), spare_server=self.spare_server) - self._adder.add(paths) - - # }}} - -class DeleteAction(object): # {{{ - - def _get_selected_formats(self, msg): - from calibre.gui2.dialogs.select_formats import SelectFormats - fmts = self.library_view.model().db.all_formats() - d = SelectFormats([x.lower() for x in fmts], msg, parent=self) - if d.exec_() != d.Accepted: - return None - return d.selected_formats - - def _get_selected_ids(self, err_title=_('Cannot delete')): - rows = self.library_view.selectionModel().selectedRows() - if not rows or len(rows) == 0: - d = error_dialog(self, err_title, _('No book selected')) - d.exec_() - return set([]) - return set(map(self.library_view.model().id, rows)) - - def delete_selected_formats(self, *args): - ids = self._get_selected_ids() - if not ids: - return - fmts = self._get_selected_formats( - _('Choose formats to be deleted')) - if not fmts: - return - for id in ids: - for fmt in fmts: - self.library_view.model().db.remove_format(id, fmt, - index_is_id=True, notify=False) - self.library_view.model().refresh_ids(ids) - self.library_view.model().current_changed(self.library_view.currentIndex(), - self.library_view.currentIndex()) - if ids: - self.tags_view.recount() - - def delete_all_but_selected_formats(self, *args): - ids = self._get_selected_ids() - if not ids: - return - fmts = self._get_selected_formats( - '

'+_('Choose formats not to be deleted')) - if fmts is None: - return - for id in ids: - bfmts = self.library_view.model().db.formats(id, index_is_id=True) - if bfmts is None: - continue - bfmts = set([x.lower() for x in bfmts.split(',')]) - rfmts = bfmts - set(fmts) - for fmt in rfmts: - self.library_view.model().db.remove_format(id, fmt, - index_is_id=True, notify=False) - self.library_view.model().refresh_ids(ids) - self.library_view.model().current_changed(self.library_view.currentIndex(), - self.library_view.currentIndex()) - if ids: - self.tags_view.recount() - - def remove_matching_books_from_device(self, *args): - if not self.device_manager.is_device_connected: - d = error_dialog(self, _('Cannot delete books'), - _('No device is connected')) - d.exec_() - return - ids = self._get_selected_ids() - if not ids: - #_get_selected_ids shows a dialog box if nothing is selected, so we - #do not need to show one here - return - to_delete = {} - some_to_delete = False - for model,name in ((self.memory_view.model(), _('Main memory')), - (self.card_a_view.model(), _('Storage Card A')), - (self.card_b_view.model(), _('Storage Card B'))): - to_delete[name] = (model, model.paths_for_db_ids(ids)) - if len(to_delete[name][1]) > 0: - some_to_delete = True - if not some_to_delete: - d = error_dialog(self, _('No books to delete'), - _('None of the selected books are on the device')) - d.exec_() - return - d = DeleteMatchingFromDeviceDialog(self, to_delete) - if d.exec_(): - paths = {} - ids = {} - for (model, id, path) in d.result: - if model not in paths: - paths[model] = [] - ids[model] = [] - paths[model].append(path) - ids[model].append(id) - for model in paths: - job = self.remove_paths(paths[model]) - self.delete_memory[job] = (paths[model], model) - model.mark_for_deletion(job, ids[model], rows_are_ids=True) - self.status_bar.show_message(_('Deleting books from device.'), 1000) - - def delete_covers(self, *args): - ids = self._get_selected_ids() - if not ids: - return - for id in ids: - self.library_view.model().db.remove_cover(id) - self.library_view.model().refresh_ids(ids) - self.library_view.model().current_changed(self.library_view.currentIndex(), - self.library_view.currentIndex()) - - def delete_books(self, *args): - ''' - Delete selected books from device or library. - ''' - view = self.current_view() - rows = view.selectionModel().selectedRows() - if not rows or len(rows) == 0: - return - if self.stack.currentIndex() == 0: - if not confirm('

'+_('The selected books will be ' - 'permanently deleted and the files ' - 'removed from your computer. Are you sure?') - +'

', 'library_delete_books', self): - return - ci = view.currentIndex() - row = None - if ci.isValid(): - row = ci.row() - ids_deleted = view.model().delete_books(rows) - for v in (self.memory_view, self.card_a_view, self.card_b_view): - if v is None: - continue - v.model().clear_ondevice(ids_deleted) - if row is not None: - ci = view.model().index(row, 0) - if ci.isValid(): - view.set_current_row(row) - else: - if not confirm('

'+_('The selected books will be ' - 'permanently deleted ' - 'from your device. Are you sure?') - +'

', 'device_delete_books', self): - return - if self.stack.currentIndex() == 1: - view = self.memory_view - elif self.stack.currentIndex() == 2: - view = self.card_a_view - else: - view = self.card_b_view - paths = view.model().paths(rows) - job = self.remove_paths(paths) - self.delete_memory[job] = (paths, view.model()) - view.model().mark_for_deletion(job, rows) - self.status_bar.show_message(_('Deleting books from device.'), 1000) - - # }}} - -class EditMetadataAction(object): # {{{ - - def download_metadata(self, checked, covers=True, set_metadata=True, - set_social_metadata=None): - rows = self.library_view.selectionModel().selectedRows() - if not rows or len(rows) == 0: - d = error_dialog(self, _('Cannot download metadata'), - _('No books selected')) - d.exec_() - return - db = self.library_view.model().db - ids = [db.id(row.row()) for row in rows] - self.do_download_metadata(ids, covers=covers, - set_metadata=set_metadata, - set_social_metadata=set_social_metadata) - - def do_download_metadata(self, ids, covers=True, set_metadata=True, - set_social_metadata=None): - db = self.library_view.model().db - if set_social_metadata is None: - get_social_metadata = config['get_social_metadata'] - else: - get_social_metadata = set_social_metadata - from calibre.gui2.metadata import DownloadMetadata - self._download_book_metadata = DownloadMetadata(db, ids, - get_covers=covers, set_metadata=set_metadata, - get_social_metadata=get_social_metadata) - self._download_book_metadata.start() - if set_social_metadata is not None and set_social_metadata: - x = _('social metadata') - else: - x = _('covers') if covers and not set_metadata else _('metadata') - self.progress_indicator.start( - _('Downloading %s for %d book(s)')%(x, len(ids))) - self._book_metadata_download_check = QTimer(self) - self.connect(self._book_metadata_download_check, - SIGNAL('timeout()'), self.book_metadata_download_check, - Qt.QueuedConnection) - self._book_metadata_download_check.start(100) - - def book_metadata_download_check(self): - if self._download_book_metadata.is_alive(): - return - self._book_metadata_download_check.stop() - self.progress_indicator.stop() - cr = self.library_view.currentIndex().row() - x = self._download_book_metadata - self._download_book_metadata = None - if x.exception is None: - self.library_view.model().refresh_ids( - x.updated, cr) - if self.cover_flow: - self.cover_flow.dataChanged() - if x.failures: - details = ['%s: %s'%(title, reason) for title, - reason in x.failures.values()] - details = '%s\n'%('\n'.join(details)) - warning_dialog(self, _('Failed to download some metadata'), - _('Failed to download metadata for the following:'), - det_msg=details).exec_() - else: - err = _('Failed to download metadata:') - error_dialog(self, _('Error'), err, det_msg=x.tb).exec_() - - - def edit_metadata(self, checked, bulk=None): - ''' - Edit metadata of selected books in library. - ''' - rows = self.library_view.selectionModel().selectedRows() - previous = self.library_view.currentIndex() - if not rows or len(rows) == 0: - d = error_dialog(self, _('Cannot edit metadata'), - _('No books selected')) - d.exec_() - return - - if bulk or (bulk is None and len(rows) > 1): - return self.edit_bulk_metadata(checked) - - def accepted(id): - self.library_view.model().refresh_ids([id]) - - for row in rows: - self._metadata_view_id = self.library_view.model().db.id(row.row()) - d = MetadataSingleDialog(self, row.row(), - self.library_view.model().db, - accepted_callback=accepted, - cancel_all=rows.index(row) < len(rows)-1) - self.connect(d, SIGNAL('view_format(PyQt_PyObject)'), - self.metadata_view_format) - d.exec_() - if d.cancel_all: - break - if rows: - current = self.library_view.currentIndex() - m = self.library_view.model() - if self.cover_flow: - self.cover_flow.dataChanged() - m.current_changed(current, previous) - self.tags_view.recount() - - def edit_bulk_metadata(self, checked): - ''' - Edit metadata of selected books in library in bulk. - ''' - rows = [r.row() for r in \ - self.library_view.selectionModel().selectedRows()] - if not rows or len(rows) == 0: - d = error_dialog(self, _('Cannot edit metadata'), - _('No books selected')) - d.exec_() - return - if MetadataBulkDialog(self, rows, - self.library_view.model().db).changed: - self.library_view.model().resort(reset=False) - self.library_view.model().research() - self.tags_view.recount() - if self.cover_flow: - self.cover_flow.dataChanged() - - # Merge books {{{ - def merge_books(self, safe_merge=False): - ''' - Merge selected books in library. - ''' - if self.stack.currentIndex() != 0: - return - rows = self.library_view.selectionModel().selectedRows() - if not rows or len(rows) == 0: - return error_dialog(self, _('Cannot merge books'), - _('No books selected'), show=True) - if len(rows) < 2: - return error_dialog(self, _('Cannot merge books'), - _('At least two books must be selected for merging'), - show=True) - dest_id, src_books, src_ids = self.books_to_merge(rows) - if safe_merge: - if not confirm('

'+_( - 'All book formats and metadata from the selected books ' - 'will be added to the first selected book.

' - 'The second and subsequently selected books will not ' - 'be deleted or changed.

' - 'Please confirm you want to proceed.') - +'

', 'merge_books_safe', self): - return - self.add_formats(dest_id, src_books) - self.merge_metadata(dest_id, src_ids) - else: - if not confirm('

'+_( - 'All book formats and metadata from the selected books will be merged ' - 'into the first selected book.

' - '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?') - +'

', 'merge_books', self): - return - if len(rows)>5: - if not confirm('

'+_('You are about to merge more than 5 books. ' - 'Are you sure you want to proceed?') - +'

', 'merge_too_many_books', self): - return - self.add_formats(dest_id, src_books) - self.merge_metadata(dest_id, src_ids) - self.delete_books_after_merge(src_ids) - # leave the selection highlight on first selected book - dest_row = rows[0].row() - for row in rows: - if row.row() < rows[0].row(): - dest_row -= 1 - ci = self.library_view.model().index(dest_row, 0) - if ci.isValid(): - self.library_view.setCurrentIndex(ci) - - def add_formats(self, dest_id, src_books, replace=False): - for src_book in src_books: - if src_book: - fmt = os.path.splitext(src_book)[-1].replace('.', '').upper() - with open(src_book, 'rb') as f: - self.library_view.model().db.add_format(dest_id, fmt, f, index_is_id=True, - notify=False, replace=replace) - - def books_to_merge(self, rows): - src_books = [] - src_ids = [] - m = self.library_view.model() - for i, row in enumerate(rows): - id_ = m.id(row) - if i == 0: - dest_id = id_ - else: - src_ids.append(id_) - dbfmts = m.db.formats(id_, index_is_id=True) - if dbfmts: - for fmt in dbfmts.split(','): - src_books.append(m.db.format_abspath(id_, fmt, - index_is_id=True)) - return [dest_id, src_books, src_ids] - - def delete_books_after_merge(self, ids_to_delete): - self.library_view.model().delete_books_by_id(ids_to_delete) - - def merge_metadata(self, dest_id, src_ids): - db = self.library_view.model().db - dest_mi = db.get_metadata(dest_id, index_is_id=True, get_cover=True) - orig_dest_comments = dest_mi.comments - for src_id in src_ids: - src_mi = db.get_metadata(src_id, index_is_id=True, get_cover=True) - if src_mi.comments and orig_dest_comments != src_mi.comments: - if not dest_mi.comments: - dest_mi.comments = src_mi.comments - else: - dest_mi.comments = unicode(dest_mi.comments) + u'\n\n' + unicode(src_mi.comments) - if src_mi.title and (not dest_mi.title or - dest_mi.title == _('Unknown')): - dest_mi.title = src_mi.title - if src_mi.title and (not dest_mi.authors or dest_mi.authors[0] == - _('Unknown')): - dest_mi.authors = src_mi.authors - dest_mi.author_sort = src_mi.author_sort - if src_mi.tags: - if not dest_mi.tags: - dest_mi.tags = src_mi.tags - else: - dest_mi.tags.extend(src_mi.tags) - if src_mi.cover and not dest_mi.cover: - dest_mi.cover = src_mi.cover - if not dest_mi.publisher: - dest_mi.publisher = src_mi.publisher - if not dest_mi.rating: - dest_mi.rating = src_mi.rating - if not dest_mi.series: - dest_mi.series = src_mi.series - dest_mi.series_index = src_mi.series_index - db.set_metadata(dest_id, dest_mi, ignore_errors=False) - - for key in db.field_metadata: #loop thru all defined fields - if db.field_metadata[key]['is_custom']: - colnum = db.field_metadata[key]['colnum'] - # Get orig_dest_comments before it gets changed - if db.field_metadata[key]['datatype'] == 'comments': - orig_dest_value = db.get_custom(dest_id, num=colnum, index_is_id=True) - for src_id in src_ids: - dest_value = db.get_custom(dest_id, num=colnum, index_is_id=True) - src_value = db.get_custom(src_id, num=colnum, index_is_id=True) - if db.field_metadata[key]['datatype'] == 'comments': - if src_value and src_value != orig_dest_value: - if not dest_value: - db.set_custom(dest_id, src_value, num=colnum) - else: - dest_value = unicode(dest_value) + u'\n\n' + unicode(src_value) - db.set_custom(dest_id, dest_value, num=colnum) - if db.field_metadata[key]['datatype'] in \ - ('bool', 'int', 'float', 'rating', 'datetime') \ - and not dest_value: - db.set_custom(dest_id, src_value, num=colnum) - if db.field_metadata[key]['datatype'] == 'series' \ - and not dest_value: - if src_value: - src_index = db.get_custom_extra(src_id, num=colnum, index_is_id=True) - db.set_custom(dest_id, src_value, num=colnum, extra=src_index) - if db.field_metadata[key]['datatype'] == 'text' \ - and not db.field_metadata[key]['is_multiple'] \ - and not dest_value: - db.set_custom(dest_id, src_value, num=colnum) - if db.field_metadata[key]['datatype'] == 'text' \ - and db.field_metadata[key]['is_multiple']: - if src_value: - if not dest_value: - dest_value = src_value - else: - dest_value.extend(src_value) - db.set_custom(dest_id, dest_value, num=colnum) - # }}} - - def edit_device_collections(self, view, oncard=None): - model = view.model() - result = model.get_collections_with_ids() - compare = (lambda x,y:cmp(x.lower(), y.lower())) - d = TagListEditor(self, tag_to_match=None, data=result, compare=compare) - d.exec_() - if d.result() == d.Accepted: - to_rename = d.to_rename # dict of new text to old ids - to_delete = d.to_delete # list of ids - for text in to_rename: - for old_id in to_rename[text]: - model.rename_collection(old_id, new_name=unicode(text)) - for item in to_delete: - model.delete_collection_using_id(item) - self.upload_collections(model.db, view=view, oncard=oncard) - view.reset() - - # }}} - -class SaveToDiskAction(object): # {{{ - - def save_single_format_to_disk(self, checked): - self.save_to_disk(checked, False, prefs['output_format']) - - def save_specific_format_disk(self, fmt): - self.save_to_disk(False, False, fmt) - - def save_to_single_dir(self, checked): - self.save_to_disk(checked, True) - - def save_single_fmt_to_single_dir(self, *args): - self.save_to_disk(False, single_dir=True, - single_format=prefs['output_format']) - - def save_to_disk(self, checked, single_dir=False, single_format=None): - rows = self.current_view().selectionModel().selectedRows() - if not rows or len(rows) == 0: - return error_dialog(self, _('Cannot save to disk'), - _('No books selected'), show=True) - path = choose_dir(self, 'save to disk dialog', - _('Choose destination directory')) - if not path: - return - dpath = os.path.abspath(path).replace('/', os.sep) - lpath = self.library_view.model().db.library_path.replace('/', os.sep) - if dpath.startswith(lpath): - return error_dialog(self, _('Not allowed'), - _('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.'), show=True) - - if self.current_view() is self.library_view: - from calibre.gui2.add import Saver - from calibre.library.save_to_disk import config - opts = config().parse() - if single_format is not None: - opts.formats = single_format - # Special case for Kindle annotation files - if single_format.lower() in ['mbp','pdr','tan']: - opts.to_lowercase = False - opts.save_cover = False - opts.write_opf = False - opts.template = opts.send_template - if single_dir: - opts.template = opts.template.split('/')[-1].strip() - if not opts.template: - opts.template = '{title} - {authors}' - self._saver = Saver(self, self.library_view.model().db, - Dispatcher(self._books_saved), rows, path, opts, - spare_server=self.spare_server) - - else: - paths = self.current_view().model().paths(rows) - self.device_manager.save_books( - Dispatcher(self.books_saved), paths, path) - - - def _books_saved(self, path, failures, error): - self._saver = None - if error: - return error_dialog(self, _('Error while saving'), - _('There was an error while saving.'), - error, show=True) - if failures: - failures = [u'%s\n\t%s'% - (title, '\n\t'.join(err.splitlines())) for title, err in - failures] - - warning_dialog(self, _('Could not save some books'), - _('Could not save some books') + ', ' + - _('Click the show details button to see which ones.'), - u'\n\n'.join(failures), show=True) - open_local_file(path) - - def books_saved(self, job): - if job.failed: - return self.device_job_exception(job) - - # }}} - -class GenerateCatalogAction(object): # {{{ - - def generate_catalog(self): - rows = self.library_view.selectionModel().selectedRows() - if not rows or len(rows) < 2: - rows = xrange(self.library_view.model().rowCount(QModelIndex())) - ids = map(self.library_view.model().id, rows) - - dbspec = None - if not ids: - return error_dialog(self, _('No books selected'), - _('No books selected to generate catalog for'), - show=True) - - # Calling gui2.tools:generate_catalog() - ret = generate_catalog(self, dbspec, ids, self.device_manager.device) - if ret is None: - return - - func, args, desc, out, sync, title = ret - - fmt = os.path.splitext(out)[1][1:].upper() - job = self.job_manager.run_job( - Dispatcher(self.catalog_generated), func, args=args, - description=desc) - job.catalog_file_path = out - job.fmt = fmt - job.catalog_sync, job.catalog_title = sync, title - self.status_bar.show_message(_('Generating %s catalog...')%fmt) - - def catalog_generated(self, job): - if job.result: - # Search terms nulled catalog results - return error_dialog(self, _('No books found'), - _("No books to catalog\nCheck exclude tags"), - show=True) - if job.failed: - return self.job_exception(job) - id = self.library_view.model().add_catalog(job.catalog_file_path, job.catalog_title) - self.library_view.model().reset() - if job.catalog_sync: - sync = dynamic.get('catalogs_to_be_synced', set([])) - sync.add(id) - dynamic.set('catalogs_to_be_synced', sync) - self.status_bar.show_message(_('Catalog generated.'), 3000) - self.sync_catalogs() - if job.fmt not in ['EPUB','MOBI']: - export_dir = choose_dir(self, _('Export Catalog Directory'), - _('Select destination for %s.%s') % (job.catalog_title, job.fmt.lower())) - if export_dir: - destination = os.path.join(export_dir, '%s.%s' % (job.catalog_title, job.fmt.lower())) - shutil.copyfile(job.catalog_file_path, destination) - - # }}} - -class FetchNewsAction(object): # {{{ - - def download_scheduled_recipe(self, arg): - func, args, desc, fmt, temp_files = \ - fetch_scheduled_recipe(arg) - job = self.job_manager.run_job( - Dispatcher(self.scheduled_recipe_fetched), func, args=args, - description=desc) - self.conversion_jobs[job] = (temp_files, fmt, arg) - self.status_bar.show_message(_('Fetching news from ')+arg['title'], 2000) - - def scheduled_recipe_fetched(self, job): - temp_files, fmt, arg = self.conversion_jobs.pop(job) - pt = temp_files[0] - if job.failed: - self.scheduler.recipe_download_failed(arg) - return self.job_exception(job) - id = self.library_view.model().add_news(pt.name, arg) - self.library_view.model().reset() - sync = dynamic.get('news_to_be_synced', set([])) - sync.add(id) - dynamic.set('news_to_be_synced', sync) - self.scheduler.recipe_downloaded(arg) - self.status_bar.show_message(arg['title'] + _(' fetched.'), 3000) - self.email_news(id) - self.sync_news() - - # }}} - -class ConvertAction(object): # {{{ - - def auto_convert(self, book_ids, on_card, format): - previous = self.library_view.currentIndex() - rows = [x.row() for x in \ - self.library_view.selectionModel().selectedRows()] - jobs, changed, bad = convert_single_ebook(self, self.library_view.model().db, book_ids, True, format) - if jobs == []: return - self.queue_convert_jobs(jobs, changed, bad, rows, previous, - self.book_auto_converted, extra_job_args=[on_card]) - - def auto_convert_mail(self, to, fmts, delete_from_library, book_ids, format): - previous = self.library_view.currentIndex() - rows = [x.row() for x in \ - self.library_view.selectionModel().selectedRows()] - jobs, changed, bad = convert_single_ebook(self, self.library_view.model().db, book_ids, True, format) - if jobs == []: return - self.queue_convert_jobs(jobs, changed, bad, rows, previous, - self.book_auto_converted_mail, - extra_job_args=[delete_from_library, to, fmts]) - - def auto_convert_news(self, book_ids, format): - previous = self.library_view.currentIndex() - rows = [x.row() for x in \ - self.library_view.selectionModel().selectedRows()] - jobs, changed, bad = convert_single_ebook(self, self.library_view.model().db, book_ids, True, format) - if jobs == []: return - self.queue_convert_jobs(jobs, changed, bad, rows, previous, - self.book_auto_converted_news) - - def auto_convert_catalogs(self, book_ids, format): - previous = self.library_view.currentIndex() - rows = [x.row() for x in \ - self.library_view.selectionModel().selectedRows()] - jobs, changed, bad = convert_single_ebook(self, self.library_view.model().db, book_ids, True, format) - if jobs == []: return - self.queue_convert_jobs(jobs, changed, bad, rows, previous, - self.book_auto_converted_catalogs) - - def get_books_for_conversion(self): - rows = [r.row() for r in \ - self.library_view.selectionModel().selectedRows()] - if not rows or len(rows) == 0: - d = error_dialog(self, _('Cannot convert'), - _('No books selected')) - d.exec_() - return None - return [self.library_view.model().db.id(r) for r in rows] - - def convert_ebook(self, checked, bulk=None): - book_ids = self.get_books_for_conversion() - if book_ids is None: return - previous = self.library_view.currentIndex() - rows = [x.row() for x in \ - self.library_view.selectionModel().selectedRows()] - num = 0 - if bulk or (bulk is None and len(book_ids) > 1): - self.__bulk_queue = convert_bulk_ebook(self, self.queue_convert_jobs, - self.library_view.model().db, book_ids, - out_format=prefs['output_format'], args=(rows, previous, - self.book_converted)) - if self.__bulk_queue is None: - return - num = len(self.__bulk_queue.book_ids) - else: - jobs, changed, bad = convert_single_ebook(self, - self.library_view.model().db, book_ids, out_format=prefs['output_format']) - self.queue_convert_jobs(jobs, changed, bad, rows, previous, - self.book_converted) - num = len(jobs) - - if num > 0: - self.status_bar.show_message(_('Starting conversion of %d book(s)') % - num, 2000) - - def queue_convert_jobs(self, jobs, changed, bad, rows, previous, - converted_func, extra_job_args=[]): - for func, args, desc, fmt, id, temp_files in jobs: - if id not in bad: - job = self.job_manager.run_job(Dispatcher(converted_func), - func, args=args, description=desc) - args = [temp_files, fmt, id]+extra_job_args - self.conversion_jobs[job] = tuple(args) - - if changed: - self.library_view.model().refresh_rows(rows) - current = self.library_view.currentIndex() - self.library_view.model().current_changed(current, previous) - - def book_auto_converted(self, job): - temp_files, fmt, book_id, on_card = self.conversion_jobs[job] - self.book_converted(job) - self.sync_to_device(on_card, False, specific_format=fmt, send_ids=[book_id], do_auto_convert=False) - - def book_auto_converted_mail(self, job): - temp_files, fmt, book_id, delete_from_library, to, fmts = self.conversion_jobs[job] - self.book_converted(job) - self.send_by_mail(to, fmts, delete_from_library, specific_format=fmt, send_ids=[book_id], do_auto_convert=False) - - def book_auto_converted_news(self, job): - temp_files, fmt, book_id = self.conversion_jobs[job] - self.book_converted(job) - self.sync_news(send_ids=[book_id], do_auto_convert=False) - - def book_auto_converted_catalogs(self, job): - temp_files, fmt, book_id = self.conversion_jobs[job] - self.book_converted(job) - self.sync_catalogs(send_ids=[book_id], do_auto_convert=False) - - def book_converted(self, job): - temp_files, fmt, book_id = self.conversion_jobs.pop(job)[:3] - try: - if job.failed: - self.job_exception(job) - return - data = open(temp_files[-1].name, 'rb') - self.library_view.model().db.add_format(book_id, \ - fmt, data, index_is_id=True) - data.close() - self.status_bar.show_message(job.description + \ - (' completed'), 2000) - finally: - for f in temp_files: - try: - if os.path.exists(f.name): - os.remove(f.name) - except: - pass - self.tags_view.recount() - if self.current_view() is self.library_view: - current = self.library_view.currentIndex() - self.library_view.model().current_changed(current, QModelIndex()) - - # }}} - -class ViewAction(object): # {{{ - - def view_format(self, row, format): - fmt_path = self.library_view.model().db.format_abspath(row, format) - if fmt_path: - self._view_file(fmt_path) - - def view_format_by_id(self, id_, format): - fmt_path = self.library_view.model().db.format_abspath(id_, format, - index_is_id=True) - if fmt_path: - self._view_file(fmt_path) - - def metadata_view_format(self, fmt): - fmt_path = self.library_view.model().db.\ - format_abspath(self._metadata_view_id, - fmt, index_is_id=True) - if fmt_path: - self._view_file(fmt_path) - - - def book_downloaded_for_viewing(self, job): - if job.failed: - self.device_job_exception(job) - return - self._view_file(job.result) - - def _launch_viewer(self, name=None, viewer='ebook-viewer', internal=True): - self.setCursor(Qt.BusyCursor) - try: - if internal: - args = [viewer] - if isosx and 'ebook' in viewer: - args.append('--raise-window') - if name is not None: - args.append(name) - self.job_manager.launch_gui_app(viewer, - kwargs=dict(args=args)) - else: - open_local_file(name) - time.sleep(2) # User feedback - finally: - self.unsetCursor() - - def _view_file(self, name): - ext = os.path.splitext(name)[1].upper().replace('.', '') - viewer = 'lrfviewer' if ext == 'LRF' else 'ebook-viewer' - internal = ext in config['internally_viewed_formats'] - self._launch_viewer(name, viewer, internal) - - def view_specific_format(self, triggered): - rows = self.library_view.selectionModel().selectedRows() - if not rows or len(rows) == 0: - d = error_dialog(self, _('Cannot view'), _('No book selected')) - d.exec_() - return - - row = rows[0].row() - formats = self.library_view.model().db.formats(row).upper().split(',') - d = ChooseFormatDialog(self, _('Choose the format to view'), formats) - if d.exec_() == QDialog.Accepted: - format = d.format() - self.view_format(row, format) - - def _view_check(self, num, max_=3): - if num <= max_: - return True - return question_dialog(self, _('Multiple Books Selected'), - _('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?' - ) % num) - - def view_folder(self, *args): - rows = self.current_view().selectionModel().selectedRows() - if not rows or len(rows) == 0: - d = error_dialog(self, _('Cannot open folder'), - _('No book selected')) - d.exec_() - return - if not self._view_check(len(rows)): - return - for row in rows: - path = self.library_view.model().db.abspath(row.row()) - open_local_file(path) - - def view_folder_for_id(self, id_): - path = self.library_view.model().db.abspath(id_, index_is_id=True) - open_local_file(path) - - def view_book(self, triggered): - rows = self.current_view().selectionModel().selectedRows() - self._view_books(rows) - - def view_specific_book(self, index): - self._view_books([index]) - - def _view_books(self, rows): - if not rows or len(rows) == 0: - self._launch_viewer() - return - - if not self._view_check(len(rows)): - return - - if self.current_view() is self.library_view: - for row in rows: - if hasattr(row, 'row'): - row = row.row() - - formats = self.library_view.model().db.formats(row) - title = self.library_view.model().db.title(row) - if not formats: - error_dialog(self, _('Cannot view'), - _('%s has no available formats.')%(title,), show=True) - continue - - formats = formats.upper().split(',') - - - in_prefs = False - for format in prefs['input_format_order']: - if format in formats: - in_prefs = True - self.view_format(row, format) - break - if not in_prefs: - self.view_format(row, formats[0]) - else: - paths = self.current_view().model().paths(rows) - for path in paths: - pt = PersistentTemporaryFile('_viewer_'+\ - os.path.splitext(path)[1]) - self.persistent_files.append(pt) - pt.close() - self.device_manager.view_book(\ - Dispatcher(self.book_downloaded_for_viewing), - path, pt.name) - - # }}} diff --git a/src/calibre/gui2/actions/add.py b/src/calibre/gui2/actions/add.py new file mode 100644 index 0000000000..18a9a4224b --- /dev/null +++ b/src/calibre/gui2/actions/add.py @@ -0,0 +1,241 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai + +__license__ = 'GPL v3' +__copyright__ = '2010, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import os +from functools import partial + +from PyQt4.Qt import QInputDialog, QPixmap + + +from calibre.gui2 import error_dialog, Dispatcher, choose_files, \ + choose_dir, warning_dialog, info_dialog +from calibre.gui2.widgets import IMAGE_EXTENSIONS +from calibre.ebooks import BOOK_EXTENSIONS +from calibre.utils.filenames import ascii_filename +from calibre.constants import preferred_encoding, filesystem_encoding + + +class AddAction(object): + + def __init__(self): + self._add_filesystem_book = Dispatcher(self.__add_filesystem_book) + + def add_recursive(self, single): + root = choose_dir(self, 'recursive book import root dir dialog', + 'Select root folder') + if not root: + return + from calibre.gui2.add import Adder + self._adder = Adder(self, + self.library_view.model().db, + Dispatcher(self._files_added), spare_server=self.spare_server) + self._adder.add_recursive(root, single) + + def add_recursive_single(self, *args): + ''' + Add books from the local filesystem to either the library or the device + recursively assuming one book per folder. + ''' + self.add_recursive(True) + + def add_recursive_multiple(self, *args): + ''' + Add books from the local filesystem to either the library or the device + recursively assuming multiple books per folder. + ''' + self.add_recursive(False) + + def add_empty(self, *args): + ''' + Add an empty book item to the library. This does not import any formats + from a book file. + ''' + num, ok = QInputDialog.getInt(self, _('How many empty books?'), + _('How many empty books should be added?'), 1, 1, 100) + if ok: + from calibre.ebooks.metadata import MetaInformation + for x in xrange(num): + self.library_view.model().db.import_book(MetaInformation(None), []) + self.library_view.model().books_added(num) + + def add_isbns(self, isbns): + from calibre.ebooks.metadata import MetaInformation + ids = set([]) + for x in isbns: + mi = MetaInformation(None) + mi.isbn = x + ids.add(self.library_view.model().db.import_book(mi, [])) + self.library_view.model().books_added(len(isbns)) + self.do_download_metadata(ids) + + + def files_dropped(self, paths): + to_device = self.stack.currentIndex() != 0 + self._add_books(paths, to_device) + + def files_dropped_on_book(self, event, paths): + accept = False + if self.current_view() is not self.library_view: + return + db = self.library_view.model().db + current_idx = self.library_view.currentIndex() + if not current_idx.isValid(): return + cid = db.id(current_idx.row()) + for path in paths: + ext = os.path.splitext(path)[1].lower() + if ext: + ext = ext[1:] + if ext in IMAGE_EXTENSIONS: + pmap = QPixmap() + pmap.load(path) + if not pmap.isNull(): + accept = True + db.set_cover(cid, pmap) + elif ext in BOOK_EXTENSIONS: + db.add_format_with_hooks(cid, ext, path, index_is_id=True) + accept = True + if accept: + event.accept() + self.library_view.model().current_changed(current_idx, current_idx) + + def __add_filesystem_book(self, paths, allow_device=True): + if isinstance(paths, basestring): + paths = [paths] + books = [path for path in map(os.path.abspath, paths) if os.access(path, + os.R_OK)] + + if books: + to_device = allow_device and self.stack.currentIndex() != 0 + self._add_books(books, to_device) + if to_device: + self.status_bar.show_message(\ + _('Uploading books to device.'), 2000) + + + def add_filesystem_book(self, paths, allow_device=True): + self._add_filesystem_book(paths, allow_device=allow_device) + + def add_from_isbn(self, *args): + from calibre.gui2.dialogs.add_from_isbn import AddFromISBN + d = AddFromISBN(self) + if d.exec_() == d.Accepted: + self.add_isbns(d.isbns) + + def add_books(self, *args): + ''' + Add books from the local filesystem to either the library or the device. + ''' + filters = [ + (_('Books'), BOOK_EXTENSIONS), + (_('EPUB Books'), ['epub']), + (_('LRF Books'), ['lrf']), + (_('HTML Books'), ['htm', 'html', 'xhtm', 'xhtml']), + (_('LIT Books'), ['lit']), + (_('MOBI Books'), ['mobi', 'prc', 'azw']), + (_('Topaz books'), ['tpz','azw1']), + (_('Text books'), ['txt', 'rtf']), + (_('PDF Books'), ['pdf']), + (_('Comics'), ['cbz', 'cbr', 'cbc']), + (_('Archives'), ['zip', 'rar']), + ] + to_device = self.stack.currentIndex() != 0 + if to_device: + filters = [(_('Supported books'), self.device_manager.device.FORMATS)] + + books = choose_files(self, 'add books dialog dir', 'Select books', + filters=filters) + if not books: + return + self._add_books(books, to_device) + + def _add_books(self, paths, to_device, on_card=None): + if on_card is None: + on_card = 'carda' if self.stack.currentIndex() == 2 else 'cardb' if self.stack.currentIndex() == 3 else None + if not paths: + return + from calibre.gui2.add import Adder + self.__adder_func = partial(self._files_added, on_card=on_card) + self._adder = Adder(self, + None if to_device else self.library_view.model().db, + Dispatcher(self.__adder_func), spare_server=self.spare_server) + self._adder.add(paths) + + def _files_added(self, paths=[], names=[], infos=[], on_card=None): + if paths: + self.upload_books(paths, + list(map(ascii_filename, names)), + infos, on_card=on_card) + self.status_bar.show_message( + _('Uploading books to device.'), 2000) + if getattr(self._adder, 'number_of_books_added', 0) > 0: + self.library_view.model().books_added(self._adder.number_of_books_added) + if hasattr(self, 'db_images'): + self.db_images.reset() + if getattr(self._adder, 'merged_books', False): + books = u'\n'.join([x if isinstance(x, unicode) else + x.decode(preferred_encoding, 'replace') for x in + self._adder.merged_books]) + info_dialog(self, _('Merged some books'), + _('Some duplicates were found and merged into the ' + 'following existing books:'), det_msg=books, show=True) + if getattr(self._adder, 'critical', None): + det_msg = [] + for name, log in self._adder.critical.items(): + if isinstance(name, str): + name = name.decode(filesystem_encoding, 'replace') + det_msg.append(name+'\n'+log) + + warning_dialog(self, _('Failed to read metadata'), + _('Failed to read metadata from the following')+':', + det_msg='\n\n'.join(det_msg), show=True) + + if hasattr(self._adder, 'cleanup'): + self._adder.cleanup() + self._adder = None + + def _add_from_device_adder(self, paths=[], names=[], infos=[], + on_card=None, model=None): + self._files_added(paths, names, infos, on_card=on_card) + # set the in-library flags, and as a consequence send the library's + # metadata for this book to the device. This sets the uuid to the + # correct value. + self.set_books_in_library(booklists=[model.db], reset=True) + model.reset() + + def add_books_from_device(self, view): + rows = view.selectionModel().selectedRows() + if not rows or len(rows) == 0: + d = error_dialog(self, _('Add to library'), _('No book selected')) + d.exec_() + return + paths = [p for p in view._model.paths(rows) if p is not None] + ve = self.device_manager.device.VIRTUAL_BOOK_EXTENSIONS + def ext(x): + ans = os.path.splitext(x)[1] + ans = ans[1:] if len(ans) > 1 else ans + return ans.lower() + remove = set([p for p in paths if ext(p) in ve]) + if remove: + paths = [p for p in paths if p not in remove] + info_dialog(self, _('Not Implemented'), + _('The following books are virtual and cannot be added' + ' to the calibre library:'), '\n'.join(remove), + show=True) + if not paths: + return + if not paths or len(paths) == 0: + d = error_dialog(self, _('Add to library'), _('No book files found')) + d.exec_() + return + from calibre.gui2.add import Adder + self.__adder_func = partial(self._add_from_device_adder, on_card=None, + model=view._model) + self._adder = Adder(self, self.library_view.model().db, + Dispatcher(self.__adder_func), spare_server=self.spare_server) + self._adder.add(paths) + + diff --git a/src/calibre/gui2/actions/annotate.py b/src/calibre/gui2/actions/annotate.py new file mode 100644 index 0000000000..22f42156dd --- /dev/null +++ b/src/calibre/gui2/actions/annotate.py @@ -0,0 +1,235 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai + +__license__ = 'GPL v3' +__copyright__ = '2010, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import os, datetime + +from PyQt4.Qt import pyqtSignal, QModelIndex, QThread, Qt + +from calibre.gui2 import error_dialog, Dispatcher, gprefs +from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag, NavigableString +from calibre import strftime + +class AnnotationsAction(object): + + def fetch_annotations(self, *args): + # Generate a path_map from selected ids + def get_ids_from_selected_rows(): + rows = self.library_view.selectionModel().selectedRows() + if not rows or len(rows) < 2: + rows = xrange(self.library_view.model().rowCount(QModelIndex())) + ids = map(self.library_view.model().id, rows) + return ids + + def get_formats(id): + formats = db.formats(id, index_is_id=True) + fmts = [] + if formats: + for format in formats.split(','): + fmts.append(format.lower()) + return fmts + + def generate_annotation_paths(ids, db, device): + # Generate path templates + # Individual storage mount points scanned/resolved in driver.get_annotations() + path_map = {} + for id in ids: + mi = db.get_metadata(id, index_is_id=True) + a_path = device.create_upload_path(os.path.abspath('/'), mi, 'x.bookmark', create_dirs=False) + path_map[id] = dict(path=a_path, fmts=get_formats(id)) + return path_map + + device = self.device_manager.device + + if self.current_view() is not self.library_view: + return error_dialog(self, _('Use library only'), + _('User annotations generated from main library only'), + show=True) + db = self.library_view.model().db + + # Get the list of ids + ids = get_ids_from_selected_rows() + if not ids: + return error_dialog(self, _('No books selected'), + _('No books selected to fetch annotations from'), + show=True) + + # Map ids to paths + path_map = generate_annotation_paths(ids, db, device) + + # Dispatch to devices.kindle.driver.get_annotations() + self.device_manager.annotations(Dispatcher(self.annotations_fetched), + path_map) + + def annotations_fetched(self, job): + from calibre.devices.usbms.device import Device + from calibre.ebooks.metadata import MetaInformation + from calibre.gui2.dialogs.progress import ProgressDialog + from calibre.library.cli import do_add_format + + class Updater(QThread): + + update_progress = pyqtSignal(int) + update_done = pyqtSignal() + FINISHED_READING_PCT_THRESHOLD = 96 + + def __init__(self, parent, db, annotation_map, done_callback): + QThread.__init__(self, parent) + self.db = db + self.pd = ProgressDialog(_('Merging user annotations into database'), '', + 0, len(job.result), parent=parent) + + self.am = annotation_map + self.done_callback = done_callback + self.pd.canceled.connect(self.canceled) + self.pd.setModal(True) + self.pd.show() + self.update_progress.connect(self.pd.set_value, + type=Qt.QueuedConnection) + self.update_done.connect(self.pd.hide, type=Qt.QueuedConnection) + + def generate_annotation_html(self, bookmark): + # Returns
...
+ last_read_location = bookmark.last_read_location + timestamp = datetime.datetime.utcfromtimestamp(bookmark.timestamp) + percent_read = bookmark.percent_read + + ka_soup = BeautifulSoup() + dtc = 0 + divTag = Tag(ka_soup,'div') + divTag['class'] = 'user_annotations' + + # Add the last-read location + spanTag = Tag(ka_soup, 'span') + spanTag['style'] = 'font-weight:bold' + if bookmark.book_format == 'pdf': + spanTag.insert(0,NavigableString( + _("%s
Last Page Read: %d (%d%%)") % \ + (strftime(u'%x', timestamp.timetuple()), + last_read_location, + percent_read))) + else: + spanTag.insert(0,NavigableString( + _("%s
Last Page Read: Location %d (%d%%)") % \ + (strftime(u'%x', timestamp.timetuple()), + last_read_location, + percent_read))) + + divTag.insert(dtc, spanTag) + dtc += 1 + divTag.insert(dtc, Tag(ka_soup,'br')) + dtc += 1 + + if bookmark.user_notes: + user_notes = bookmark.user_notes + annotations = [] + + # Add the annotations sorted by location + # Italicize highlighted text + for location in sorted(user_notes): + if user_notes[location]['text']: + annotations.append( + _('Location %d • %s
%s
') % \ + (user_notes[location]['displayed_location'], + user_notes[location]['type'], + user_notes[location]['text'] if \ + user_notes[location]['type'] == 'Note' else \ + '%s' % user_notes[location]['text'])) + else: + if bookmark.book_format == 'pdf': + annotations.append( + _('Page %d • %s
') % \ + (user_notes[location]['displayed_location'], + user_notes[location]['type'])) + else: + annotations.append( + _('Location %d • %s
') % \ + (user_notes[location]['displayed_location'], + user_notes[location]['type'])) + + for annotation in annotations: + divTag.insert(dtc, annotation) + dtc += 1 + + ka_soup.insert(0,divTag) + return ka_soup + + def mark_book_as_read(self,id): + read_tag = gprefs.get('catalog_epub_mobi_read_tag') + if read_tag: + self.db.set_tags(id, [read_tag], append=True) + + def canceled(self): + self.pd.hide() + + def run(self): + ignore_tags = set(['Catalog','Clippings']) + for (i, id) in enumerate(self.am): + bm = Device.UserAnnotation(self.am[id][0],self.am[id][1]) + if bm.type == 'kindle_bookmark': + mi = self.db.get_metadata(id, index_is_id=True) + user_notes_soup = self.generate_annotation_html(bm.value) + if mi.comments: + a_offset = mi.comments.find('
') + ad_offset = mi.comments.find('
') + + if a_offset >= 0: + mi.comments = mi.comments[:a_offset] + if ad_offset >= 0: + mi.comments = mi.comments[:ad_offset] + if set(mi.tags).intersection(ignore_tags): + continue + if mi.comments: + hrTag = Tag(user_notes_soup,'hr') + hrTag['class'] = 'annotations_divider' + user_notes_soup.insert(0,hrTag) + + mi.comments += user_notes_soup.prettify() + else: + mi.comments = unicode(user_notes_soup.prettify()) + # Update library comments + self.db.set_comment(id, mi.comments) + + # Update 'read' tag except for Catalogs/Clippings + if bm.value.percent_read >= self.FINISHED_READING_PCT_THRESHOLD: + if not set(mi.tags).intersection(ignore_tags): + self.mark_book_as_read(id) + + # Add bookmark file to id + self.db.add_format_with_hooks(id, bm.value.bookmark_extension, + bm.value.path, index_is_id=True) + self.update_progress.emit(i) + elif bm.type == 'kindle_clippings': + # Find 'My Clippings' author=Kindle in database, or add + last_update = 'Last modified %s' % strftime(u'%x %X',bm.value['timestamp'].timetuple()) + mc_id = list(db.data.parse('title:"My Clippings"')) + if mc_id: + do_add_format(self.db, mc_id[0], 'TXT', bm.value['path']) + mi = self.db.get_metadata(mc_id[0], index_is_id=True) + mi.comments = last_update + self.db.set_metadata(mc_id[0], mi) + else: + mi = MetaInformation('My Clippings', authors = ['Kindle']) + mi.tags = ['Clippings'] + mi.comments = last_update + self.db.add_books([bm.value['path']], ['txt'], [mi]) + + self.update_done.emit() + self.done_callback(self.am.keys()) + + if not job.result: return + + if self.current_view() is not self.library_view: + return error_dialog(self, _('Use library only'), + _('User annotations generated from main library only'), + show=True) + db = self.library_view.model().db + + self.__annotation_updater = Updater(self, db, job.result, + Dispatcher(self.library_view.model().refresh_ids)) + self.__annotation_updater.start() + + diff --git a/src/calibre/gui2/actions/catalog.py b/src/calibre/gui2/actions/catalog.py new file mode 100644 index 0000000000..f8c9b24b30 --- /dev/null +++ b/src/calibre/gui2/actions/catalog.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai + +__license__ = 'GPL v3' +__copyright__ = '2010, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import os, shutil + +from PyQt4.Qt import QModelIndex + +from calibre.gui2 import error_dialog, Dispatcher, choose_dir +from calibre.gui2.tools import generate_catalog +from calibre.utils.config import dynamic + +class GenerateCatalogAction(object): + + def generate_catalog(self): + rows = self.library_view.selectionModel().selectedRows() + if not rows or len(rows) < 2: + rows = xrange(self.library_view.model().rowCount(QModelIndex())) + ids = map(self.library_view.model().id, rows) + + dbspec = None + if not ids: + return error_dialog(self, _('No books selected'), + _('No books selected to generate catalog for'), + show=True) + + # Calling gui2.tools:generate_catalog() + ret = generate_catalog(self, dbspec, ids, self.device_manager.device) + if ret is None: + return + + func, args, desc, out, sync, title = ret + + fmt = os.path.splitext(out)[1][1:].upper() + job = self.job_manager.run_job( + Dispatcher(self.catalog_generated), func, args=args, + description=desc) + job.catalog_file_path = out + job.fmt = fmt + job.catalog_sync, job.catalog_title = sync, title + self.status_bar.show_message(_('Generating %s catalog...')%fmt) + + def catalog_generated(self, job): + if job.result: + # Search terms nulled catalog results + return error_dialog(self, _('No books found'), + _("No books to catalog\nCheck exclude tags"), + show=True) + if job.failed: + return self.job_exception(job) + id = self.library_view.model().add_catalog(job.catalog_file_path, job.catalog_title) + self.library_view.model().reset() + if job.catalog_sync: + sync = dynamic.get('catalogs_to_be_synced', set([])) + sync.add(id) + dynamic.set('catalogs_to_be_synced', sync) + self.status_bar.show_message(_('Catalog generated.'), 3000) + self.sync_catalogs() + if job.fmt not in ['EPUB','MOBI']: + export_dir = choose_dir(self, _('Export Catalog Directory'), + _('Select destination for %s.%s') % (job.catalog_title, job.fmt.lower())) + if export_dir: + destination = os.path.join(export_dir, '%s.%s' % (job.catalog_title, job.fmt.lower())) + shutil.copyfile(job.catalog_file_path, destination) + + diff --git a/src/calibre/gui2/actions/convert.py b/src/calibre/gui2/actions/convert.py new file mode 100644 index 0000000000..9d5f1da048 --- /dev/null +++ b/src/calibre/gui2/actions/convert.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai + +__license__ = 'GPL v3' +__copyright__ = '2010, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import os + +from PyQt4.Qt import QModelIndex + +from calibre.gui2 import error_dialog, Dispatcher +from calibre.gui2.tools import convert_single_ebook, convert_bulk_ebook +from calibre.utils.config import prefs + +class ConvertAction(object): + + def auto_convert(self, book_ids, on_card, format): + previous = self.library_view.currentIndex() + rows = [x.row() for x in \ + self.library_view.selectionModel().selectedRows()] + jobs, changed, bad = convert_single_ebook(self, self.library_view.model().db, book_ids, True, format) + if jobs == []: return + self.queue_convert_jobs(jobs, changed, bad, rows, previous, + self.book_auto_converted, extra_job_args=[on_card]) + + def auto_convert_mail(self, to, fmts, delete_from_library, book_ids, format): + previous = self.library_view.currentIndex() + rows = [x.row() for x in \ + self.library_view.selectionModel().selectedRows()] + jobs, changed, bad = convert_single_ebook(self, self.library_view.model().db, book_ids, True, format) + if jobs == []: return + self.queue_convert_jobs(jobs, changed, bad, rows, previous, + self.book_auto_converted_mail, + extra_job_args=[delete_from_library, to, fmts]) + + def auto_convert_news(self, book_ids, format): + previous = self.library_view.currentIndex() + rows = [x.row() for x in \ + self.library_view.selectionModel().selectedRows()] + jobs, changed, bad = convert_single_ebook(self, self.library_view.model().db, book_ids, True, format) + if jobs == []: return + self.queue_convert_jobs(jobs, changed, bad, rows, previous, + self.book_auto_converted_news) + + def auto_convert_catalogs(self, book_ids, format): + previous = self.library_view.currentIndex() + rows = [x.row() for x in \ + self.library_view.selectionModel().selectedRows()] + jobs, changed, bad = convert_single_ebook(self, self.library_view.model().db, book_ids, True, format) + if jobs == []: return + self.queue_convert_jobs(jobs, changed, bad, rows, previous, + self.book_auto_converted_catalogs) + + def get_books_for_conversion(self): + rows = [r.row() for r in \ + self.library_view.selectionModel().selectedRows()] + if not rows or len(rows) == 0: + d = error_dialog(self, _('Cannot convert'), + _('No books selected')) + d.exec_() + return None + return [self.library_view.model().db.id(r) for r in rows] + + def convert_ebook(self, checked, bulk=None): + book_ids = self.get_books_for_conversion() + if book_ids is None: return + previous = self.library_view.currentIndex() + rows = [x.row() for x in \ + self.library_view.selectionModel().selectedRows()] + num = 0 + if bulk or (bulk is None and len(book_ids) > 1): + self.__bulk_queue = convert_bulk_ebook(self, self.queue_convert_jobs, + self.library_view.model().db, book_ids, + out_format=prefs['output_format'], args=(rows, previous, + self.book_converted)) + if self.__bulk_queue is None: + return + num = len(self.__bulk_queue.book_ids) + else: + jobs, changed, bad = convert_single_ebook(self, + self.library_view.model().db, book_ids, out_format=prefs['output_format']) + self.queue_convert_jobs(jobs, changed, bad, rows, previous, + self.book_converted) + num = len(jobs) + + if num > 0: + self.status_bar.show_message(_('Starting conversion of %d book(s)') % + num, 2000) + + def queue_convert_jobs(self, jobs, changed, bad, rows, previous, + converted_func, extra_job_args=[]): + for func, args, desc, fmt, id, temp_files in jobs: + if id not in bad: + job = self.job_manager.run_job(Dispatcher(converted_func), + func, args=args, description=desc) + args = [temp_files, fmt, id]+extra_job_args + self.conversion_jobs[job] = tuple(args) + + if changed: + self.library_view.model().refresh_rows(rows) + current = self.library_view.currentIndex() + self.library_view.model().current_changed(current, previous) + + def book_auto_converted(self, job): + temp_files, fmt, book_id, on_card = self.conversion_jobs[job] + self.book_converted(job) + self.sync_to_device(on_card, False, specific_format=fmt, send_ids=[book_id], do_auto_convert=False) + + def book_auto_converted_mail(self, job): + temp_files, fmt, book_id, delete_from_library, to, fmts = self.conversion_jobs[job] + self.book_converted(job) + self.send_by_mail(to, fmts, delete_from_library, specific_format=fmt, send_ids=[book_id], do_auto_convert=False) + + def book_auto_converted_news(self, job): + temp_files, fmt, book_id = self.conversion_jobs[job] + self.book_converted(job) + self.sync_news(send_ids=[book_id], do_auto_convert=False) + + def book_auto_converted_catalogs(self, job): + temp_files, fmt, book_id = self.conversion_jobs[job] + self.book_converted(job) + self.sync_catalogs(send_ids=[book_id], do_auto_convert=False) + + def book_converted(self, job): + temp_files, fmt, book_id = self.conversion_jobs.pop(job)[:3] + try: + if job.failed: + self.job_exception(job) + return + data = open(temp_files[-1].name, 'rb') + self.library_view.model().db.add_format(book_id, \ + fmt, data, index_is_id=True) + data.close() + self.status_bar.show_message(job.description + \ + (' completed'), 2000) + finally: + for f in temp_files: + try: + if os.path.exists(f.name): + os.remove(f.name) + except: + pass + self.tags_view.recount() + if self.current_view() is self.library_view: + current = self.library_view.currentIndex() + self.library_view.model().current_changed(current, QModelIndex()) + diff --git a/src/calibre/gui2/actions/delete.py b/src/calibre/gui2/actions/delete.py new file mode 100644 index 0000000000..e5c6000863 --- /dev/null +++ b/src/calibre/gui2/actions/delete.py @@ -0,0 +1,165 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai + +__license__ = 'GPL v3' +__copyright__ = '2010, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +from calibre.gui2 import error_dialog +from calibre.gui2.dialogs.delete_matching_from_device import DeleteMatchingFromDeviceDialog +from calibre.gui2.dialogs.confirm_delete import confirm + +class DeleteAction(object): + + def _get_selected_formats(self, msg): + from calibre.gui2.dialogs.select_formats import SelectFormats + fmts = self.library_view.model().db.all_formats() + d = SelectFormats([x.lower() for x in fmts], msg, parent=self) + if d.exec_() != d.Accepted: + return None + return d.selected_formats + + def _get_selected_ids(self, err_title=_('Cannot delete')): + rows = self.library_view.selectionModel().selectedRows() + if not rows or len(rows) == 0: + d = error_dialog(self, err_title, _('No book selected')) + d.exec_() + return set([]) + return set(map(self.library_view.model().id, rows)) + + def delete_selected_formats(self, *args): + ids = self._get_selected_ids() + if not ids: + return + fmts = self._get_selected_formats( + _('Choose formats to be deleted')) + if not fmts: + return + for id in ids: + for fmt in fmts: + self.library_view.model().db.remove_format(id, fmt, + index_is_id=True, notify=False) + self.library_view.model().refresh_ids(ids) + self.library_view.model().current_changed(self.library_view.currentIndex(), + self.library_view.currentIndex()) + if ids: + self.tags_view.recount() + + def delete_all_but_selected_formats(self, *args): + ids = self._get_selected_ids() + if not ids: + return + fmts = self._get_selected_formats( + '

'+_('Choose formats not to be deleted')) + if fmts is None: + return + for id in ids: + bfmts = self.library_view.model().db.formats(id, index_is_id=True) + if bfmts is None: + continue + bfmts = set([x.lower() for x in bfmts.split(',')]) + rfmts = bfmts - set(fmts) + for fmt in rfmts: + self.library_view.model().db.remove_format(id, fmt, + index_is_id=True, notify=False) + self.library_view.model().refresh_ids(ids) + self.library_view.model().current_changed(self.library_view.currentIndex(), + self.library_view.currentIndex()) + if ids: + self.tags_view.recount() + + def remove_matching_books_from_device(self, *args): + if not self.device_manager.is_device_connected: + d = error_dialog(self, _('Cannot delete books'), + _('No device is connected')) + d.exec_() + return + ids = self._get_selected_ids() + if not ids: + #_get_selected_ids shows a dialog box if nothing is selected, so we + #do not need to show one here + return + to_delete = {} + some_to_delete = False + for model,name in ((self.memory_view.model(), _('Main memory')), + (self.card_a_view.model(), _('Storage Card A')), + (self.card_b_view.model(), _('Storage Card B'))): + to_delete[name] = (model, model.paths_for_db_ids(ids)) + if len(to_delete[name][1]) > 0: + some_to_delete = True + if not some_to_delete: + d = error_dialog(self, _('No books to delete'), + _('None of the selected books are on the device')) + d.exec_() + return + d = DeleteMatchingFromDeviceDialog(self, to_delete) + if d.exec_(): + paths = {} + ids = {} + for (model, id, path) in d.result: + if model not in paths: + paths[model] = [] + ids[model] = [] + paths[model].append(path) + ids[model].append(id) + for model in paths: + job = self.remove_paths(paths[model]) + self.delete_memory[job] = (paths[model], model) + model.mark_for_deletion(job, ids[model], rows_are_ids=True) + self.status_bar.show_message(_('Deleting books from device.'), 1000) + + def delete_covers(self, *args): + ids = self._get_selected_ids() + if not ids: + return + for id in ids: + self.library_view.model().db.remove_cover(id) + self.library_view.model().refresh_ids(ids) + self.library_view.model().current_changed(self.library_view.currentIndex(), + self.library_view.currentIndex()) + + def delete_books(self, *args): + ''' + Delete selected books from device or library. + ''' + view = self.current_view() + rows = view.selectionModel().selectedRows() + if not rows or len(rows) == 0: + return + if self.stack.currentIndex() == 0: + if not confirm('

'+_('The selected books will be ' + 'permanently deleted and the files ' + 'removed from your computer. Are you sure?') + +'

', 'library_delete_books', self): + return + ci = view.currentIndex() + row = None + if ci.isValid(): + row = ci.row() + ids_deleted = view.model().delete_books(rows) + for v in (self.memory_view, self.card_a_view, self.card_b_view): + if v is None: + continue + v.model().clear_ondevice(ids_deleted) + if row is not None: + ci = view.model().index(row, 0) + if ci.isValid(): + view.set_current_row(row) + else: + if not confirm('

'+_('The selected books will be ' + 'permanently deleted ' + 'from your device. Are you sure?') + +'

', 'device_delete_books', self): + return + if self.stack.currentIndex() == 1: + view = self.memory_view + elif self.stack.currentIndex() == 2: + view = self.card_a_view + else: + view = self.card_b_view + paths = view.model().paths(rows) + job = self.remove_paths(paths) + self.delete_memory[job] = (paths, view.model()) + view.model().mark_for_deletion(job, rows) + self.status_bar.show_message(_('Deleting books from device.'), 1000) + diff --git a/src/calibre/gui2/actions/edit_metadata.py b/src/calibre/gui2/actions/edit_metadata.py new file mode 100644 index 0000000000..b4f299f54c --- /dev/null +++ b/src/calibre/gui2/actions/edit_metadata.py @@ -0,0 +1,311 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai + +__license__ = 'GPL v3' +__copyright__ = '2010, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import os + +from PyQt4.Qt import Qt, QTimer + +from calibre.gui2 import error_dialog, config, warning_dialog +from calibre.gui2.dialogs.metadata_single import MetadataSingleDialog +from calibre.gui2.dialogs.metadata_bulk import MetadataBulkDialog +from calibre.gui2.dialogs.confirm_delete import confirm +from calibre.gui2.dialogs.tag_list_editor import TagListEditor + +class EditMetadataAction(object): + + def download_metadata(self, checked, covers=True, set_metadata=True, + set_social_metadata=None): + rows = self.library_view.selectionModel().selectedRows() + if not rows or len(rows) == 0: + d = error_dialog(self, _('Cannot download metadata'), + _('No books selected')) + d.exec_() + return + db = self.library_view.model().db + ids = [db.id(row.row()) for row in rows] + self.do_download_metadata(ids, covers=covers, + set_metadata=set_metadata, + set_social_metadata=set_social_metadata) + + def do_download_metadata(self, ids, covers=True, set_metadata=True, + set_social_metadata=None): + db = self.library_view.model().db + if set_social_metadata is None: + get_social_metadata = config['get_social_metadata'] + else: + get_social_metadata = set_social_metadata + from calibre.gui2.metadata import DownloadMetadata + self._download_book_metadata = DownloadMetadata(db, ids, + get_covers=covers, set_metadata=set_metadata, + get_social_metadata=get_social_metadata) + self._download_book_metadata.start() + if set_social_metadata is not None and set_social_metadata: + x = _('social metadata') + else: + x = _('covers') if covers and not set_metadata else _('metadata') + self.progress_indicator.start( + _('Downloading %s for %d book(s)')%(x, len(ids))) + self._book_metadata_download_check = QTimer(self) + self._book_metadata_download_check.timeout.connect(self.book_metadata_download_check, + type=Qt.QueuedConnection) + self._book_metadata_download_check.start(100) + + def book_metadata_download_check(self): + if self._download_book_metadata.is_alive(): + return + self._book_metadata_download_check.stop() + self.progress_indicator.stop() + cr = self.library_view.currentIndex().row() + x = self._download_book_metadata + self._download_book_metadata = None + if x.exception is None: + self.library_view.model().refresh_ids( + x.updated, cr) + if self.cover_flow: + self.cover_flow.dataChanged() + if x.failures: + details = ['%s: %s'%(title, reason) for title, + reason in x.failures.values()] + details = '%s\n'%('\n'.join(details)) + warning_dialog(self, _('Failed to download some metadata'), + _('Failed to download metadata for the following:'), + det_msg=details).exec_() + else: + err = _('Failed to download metadata:') + error_dialog(self, _('Error'), err, det_msg=x.tb).exec_() + + + def edit_metadata(self, checked, bulk=None): + ''' + Edit metadata of selected books in library. + ''' + rows = self.library_view.selectionModel().selectedRows() + previous = self.library_view.currentIndex() + if not rows or len(rows) == 0: + d = error_dialog(self, _('Cannot edit metadata'), + _('No books selected')) + d.exec_() + return + + if bulk or (bulk is None and len(rows) > 1): + return self.edit_bulk_metadata(checked) + + def accepted(id): + self.library_view.model().refresh_ids([id]) + + for row in rows: + self._metadata_view_id = self.library_view.model().db.id(row.row()) + d = MetadataSingleDialog(self, row.row(), + self.library_view.model().db, + accepted_callback=accepted, + cancel_all=rows.index(row) < len(rows)-1) + d.view_format.connect(self.metadata_view_format) + d.exec_() + if d.cancel_all: + break + if rows: + current = self.library_view.currentIndex() + m = self.library_view.model() + if self.cover_flow: + self.cover_flow.dataChanged() + m.current_changed(current, previous) + self.tags_view.recount() + + def edit_bulk_metadata(self, checked): + ''' + Edit metadata of selected books in library in bulk. + ''' + rows = [r.row() for r in \ + self.library_view.selectionModel().selectedRows()] + if not rows or len(rows) == 0: + d = error_dialog(self, _('Cannot edit metadata'), + _('No books selected')) + d.exec_() + return + if MetadataBulkDialog(self, rows, + self.library_view.model().db).changed: + self.library_view.model().resort(reset=False) + self.library_view.model().research() + self.tags_view.recount() + if self.cover_flow: + self.cover_flow.dataChanged() + + # Merge books {{{ + def merge_books(self, safe_merge=False): + ''' + Merge selected books in library. + ''' + if self.stack.currentIndex() != 0: + return + rows = self.library_view.selectionModel().selectedRows() + if not rows or len(rows) == 0: + return error_dialog(self, _('Cannot merge books'), + _('No books selected'), show=True) + if len(rows) < 2: + return error_dialog(self, _('Cannot merge books'), + _('At least two books must be selected for merging'), + show=True) + dest_id, src_books, src_ids = self.books_to_merge(rows) + if safe_merge: + if not confirm('

'+_( + 'All book formats and metadata from the selected books ' + 'will be added to the first selected book.

' + 'The second and subsequently selected books will not ' + 'be deleted or changed.

' + 'Please confirm you want to proceed.') + +'

', 'merge_books_safe', self): + return + self.add_formats(dest_id, src_books) + self.merge_metadata(dest_id, src_ids) + else: + if not confirm('

'+_( + 'All book formats and metadata from the selected books will be merged ' + 'into the first selected book.

' + '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?') + +'

', 'merge_books', self): + return + if len(rows)>5: + if not confirm('

'+_('You are about to merge more than 5 books. ' + 'Are you sure you want to proceed?') + +'

', 'merge_too_many_books', self): + return + self.add_formats(dest_id, src_books) + self.merge_metadata(dest_id, src_ids) + self.delete_books_after_merge(src_ids) + # leave the selection highlight on first selected book + dest_row = rows[0].row() + for row in rows: + if row.row() < rows[0].row(): + dest_row -= 1 + ci = self.library_view.model().index(dest_row, 0) + if ci.isValid(): + self.library_view.setCurrentIndex(ci) + + def add_formats(self, dest_id, src_books, replace=False): + for src_book in src_books: + if src_book: + fmt = os.path.splitext(src_book)[-1].replace('.', '').upper() + with open(src_book, 'rb') as f: + self.library_view.model().db.add_format(dest_id, fmt, f, index_is_id=True, + notify=False, replace=replace) + + def books_to_merge(self, rows): + src_books = [] + src_ids = [] + m = self.library_view.model() + for i, row in enumerate(rows): + id_ = m.id(row) + if i == 0: + dest_id = id_ + else: + src_ids.append(id_) + dbfmts = m.db.formats(id_, index_is_id=True) + if dbfmts: + for fmt in dbfmts.split(','): + src_books.append(m.db.format_abspath(id_, fmt, + index_is_id=True)) + return [dest_id, src_books, src_ids] + + def delete_books_after_merge(self, ids_to_delete): + self.library_view.model().delete_books_by_id(ids_to_delete) + + def merge_metadata(self, dest_id, src_ids): + db = self.library_view.model().db + dest_mi = db.get_metadata(dest_id, index_is_id=True, get_cover=True) + orig_dest_comments = dest_mi.comments + for src_id in src_ids: + src_mi = db.get_metadata(src_id, index_is_id=True, get_cover=True) + if src_mi.comments and orig_dest_comments != src_mi.comments: + if not dest_mi.comments: + dest_mi.comments = src_mi.comments + else: + dest_mi.comments = unicode(dest_mi.comments) + u'\n\n' + unicode(src_mi.comments) + if src_mi.title and (not dest_mi.title or + dest_mi.title == _('Unknown')): + dest_mi.title = src_mi.title + if src_mi.title and (not dest_mi.authors or dest_mi.authors[0] == + _('Unknown')): + dest_mi.authors = src_mi.authors + dest_mi.author_sort = src_mi.author_sort + if src_mi.tags: + if not dest_mi.tags: + dest_mi.tags = src_mi.tags + else: + dest_mi.tags.extend(src_mi.tags) + if src_mi.cover and not dest_mi.cover: + dest_mi.cover = src_mi.cover + if not dest_mi.publisher: + dest_mi.publisher = src_mi.publisher + if not dest_mi.rating: + dest_mi.rating = src_mi.rating + if not dest_mi.series: + dest_mi.series = src_mi.series + dest_mi.series_index = src_mi.series_index + db.set_metadata(dest_id, dest_mi, ignore_errors=False) + + for key in db.field_metadata: #loop thru all defined fields + if db.field_metadata[key]['is_custom']: + colnum = db.field_metadata[key]['colnum'] + # Get orig_dest_comments before it gets changed + if db.field_metadata[key]['datatype'] == 'comments': + orig_dest_value = db.get_custom(dest_id, num=colnum, index_is_id=True) + for src_id in src_ids: + dest_value = db.get_custom(dest_id, num=colnum, index_is_id=True) + src_value = db.get_custom(src_id, num=colnum, index_is_id=True) + if db.field_metadata[key]['datatype'] == 'comments': + if src_value and src_value != orig_dest_value: + if not dest_value: + db.set_custom(dest_id, src_value, num=colnum) + else: + dest_value = unicode(dest_value) + u'\n\n' + unicode(src_value) + db.set_custom(dest_id, dest_value, num=colnum) + if db.field_metadata[key]['datatype'] in \ + ('bool', 'int', 'float', 'rating', 'datetime') \ + and not dest_value: + db.set_custom(dest_id, src_value, num=colnum) + if db.field_metadata[key]['datatype'] == 'series' \ + and not dest_value: + if src_value: + src_index = db.get_custom_extra(src_id, num=colnum, index_is_id=True) + db.set_custom(dest_id, src_value, num=colnum, extra=src_index) + if db.field_metadata[key]['datatype'] == 'text' \ + and not db.field_metadata[key]['is_multiple'] \ + and not dest_value: + db.set_custom(dest_id, src_value, num=colnum) + if db.field_metadata[key]['datatype'] == 'text' \ + and db.field_metadata[key]['is_multiple']: + if src_value: + if not dest_value: + dest_value = src_value + else: + dest_value.extend(src_value) + db.set_custom(dest_id, dest_value, num=colnum) + # }}} + + def edit_device_collections(self, view, oncard=None): + model = view.model() + result = model.get_collections_with_ids() + compare = (lambda x,y:cmp(x.lower(), y.lower())) + d = TagListEditor(self, tag_to_match=None, data=result, compare=compare) + d.exec_() + if d.result() == d.Accepted: + to_rename = d.to_rename # dict of new text to old ids + to_delete = d.to_delete # list of ids + for text in to_rename: + for old_id in to_rename[text]: + model.rename_collection(old_id, new_name=unicode(text)) + for item in to_delete: + model.delete_collection_using_id(item) + self.upload_collections(model.db, view=view, oncard=oncard) + view.reset() + + diff --git a/src/calibre/gui2/actions/fetch_news.py b/src/calibre/gui2/actions/fetch_news.py new file mode 100644 index 0000000000..c051f362f1 --- /dev/null +++ b/src/calibre/gui2/actions/fetch_news.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai + +__license__ = 'GPL v3' +__copyright__ = '2010, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +from calibre.gui2 import Dispatcher +from calibre.gui2.tools import fetch_scheduled_recipe +from calibre.utils.config import dynamic + +class FetchNewsAction(object): + + def download_scheduled_recipe(self, arg): + func, args, desc, fmt, temp_files = \ + fetch_scheduled_recipe(arg) + job = self.job_manager.run_job( + Dispatcher(self.scheduled_recipe_fetched), func, args=args, + description=desc) + self.conversion_jobs[job] = (temp_files, fmt, arg) + self.status_bar.show_message(_('Fetching news from ')+arg['title'], 2000) + + def scheduled_recipe_fetched(self, job): + temp_files, fmt, arg = self.conversion_jobs.pop(job) + pt = temp_files[0] + if job.failed: + self.scheduler.recipe_download_failed(arg) + return self.job_exception(job) + id = self.library_view.model().add_news(pt.name, arg) + self.library_view.model().reset() + sync = dynamic.get('news_to_be_synced', set([])) + sync.add(id) + dynamic.set('news_to_be_synced', sync) + self.scheduler.recipe_downloaded(arg) + self.status_bar.show_message(arg['title'] + _(' fetched.'), 3000) + self.email_news(id) + self.sync_news() + + diff --git a/src/calibre/gui2/actions/save_to_disk.py b/src/calibre/gui2/actions/save_to_disk.py new file mode 100644 index 0000000000..fb1ca58a3c --- /dev/null +++ b/src/calibre/gui2/actions/save_to_disk.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai + +__license__ = 'GPL v3' +__copyright__ = '2010, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import os + +from calibre.utils.config import prefs +from calibre.gui2 import error_dialog, Dispatcher, \ + choose_dir, warning_dialog, open_local_file + + +class SaveToDiskAction(object): + + def save_single_format_to_disk(self, checked): + self.save_to_disk(checked, False, prefs['output_format']) + + def save_specific_format_disk(self, fmt): + self.save_to_disk(False, False, fmt) + + def save_to_single_dir(self, checked): + self.save_to_disk(checked, True) + + def save_single_fmt_to_single_dir(self, *args): + self.save_to_disk(False, single_dir=True, + single_format=prefs['output_format']) + + def save_to_disk(self, checked, single_dir=False, single_format=None): + rows = self.current_view().selectionModel().selectedRows() + if not rows or len(rows) == 0: + return error_dialog(self, _('Cannot save to disk'), + _('No books selected'), show=True) + path = choose_dir(self, 'save to disk dialog', + _('Choose destination directory')) + if not path: + return + dpath = os.path.abspath(path).replace('/', os.sep) + lpath = self.library_view.model().db.library_path.replace('/', os.sep) + if dpath.startswith(lpath): + return error_dialog(self, _('Not allowed'), + _('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.'), show=True) + + if self.current_view() is self.library_view: + from calibre.gui2.add import Saver + from calibre.library.save_to_disk import config + opts = config().parse() + if single_format is not None: + opts.formats = single_format + # Special case for Kindle annotation files + if single_format.lower() in ['mbp','pdr','tan']: + opts.to_lowercase = False + opts.save_cover = False + opts.write_opf = False + opts.template = opts.send_template + if single_dir: + opts.template = opts.template.split('/')[-1].strip() + if not opts.template: + opts.template = '{title} - {authors}' + self._saver = Saver(self, self.library_view.model().db, + Dispatcher(self._books_saved), rows, path, opts, + spare_server=self.spare_server) + + else: + paths = self.current_view().model().paths(rows) + self.device_manager.save_books( + Dispatcher(self.books_saved), paths, path) + + + def _books_saved(self, path, failures, error): + self._saver = None + if error: + return error_dialog(self, _('Error while saving'), + _('There was an error while saving.'), + error, show=True) + if failures: + failures = [u'%s\n\t%s'% + (title, '\n\t'.join(err.splitlines())) for title, err in + failures] + + warning_dialog(self, _('Could not save some books'), + _('Could not save some books') + ', ' + + _('Click the show details button to see which ones.'), + u'\n\n'.join(failures), show=True) + open_local_file(path) + + def books_saved(self, job): + if job.failed: + return self.device_job_exception(job) + + diff --git a/src/calibre/gui2/actions/view.py b/src/calibre/gui2/actions/view.py new file mode 100644 index 0000000000..3ca7a807d7 --- /dev/null +++ b/src/calibre/gui2/actions/view.py @@ -0,0 +1,159 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai + +__license__ = 'GPL v3' +__copyright__ = '2010, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import os, time + +from PyQt4.Qt import Qt + +from calibre.constants import isosx +from calibre.gui2 import error_dialog, Dispatcher, question_dialog, config, \ + open_local_file +from calibre.gui2.dialogs.choose_format import ChooseFormatDialog +from calibre.utils.config import prefs +from calibre.ptempfile import PersistentTemporaryFile + +class ViewAction(object): + + def view_format(self, row, format): + fmt_path = self.library_view.model().db.format_abspath(row, format) + if fmt_path: + self._view_file(fmt_path) + + def view_format_by_id(self, id_, format): + fmt_path = self.library_view.model().db.format_abspath(id_, format, + index_is_id=True) + if fmt_path: + self._view_file(fmt_path) + + def metadata_view_format(self, fmt): + fmt_path = self.library_view.model().db.\ + format_abspath(self._metadata_view_id, + fmt, index_is_id=True) + if fmt_path: + self._view_file(fmt_path) + + + def book_downloaded_for_viewing(self, job): + if job.failed: + self.device_job_exception(job) + return + self._view_file(job.result) + + def _launch_viewer(self, name=None, viewer='ebook-viewer', internal=True): + self.setCursor(Qt.BusyCursor) + try: + if internal: + args = [viewer] + if isosx and 'ebook' in viewer: + args.append('--raise-window') + if name is not None: + args.append(name) + self.job_manager.launch_gui_app(viewer, + kwargs=dict(args=args)) + else: + open_local_file(name) + time.sleep(2) # User feedback + finally: + self.unsetCursor() + + def _view_file(self, name): + ext = os.path.splitext(name)[1].upper().replace('.', '') + viewer = 'lrfviewer' if ext == 'LRF' else 'ebook-viewer' + internal = ext in config['internally_viewed_formats'] + self._launch_viewer(name, viewer, internal) + + def view_specific_format(self, triggered): + rows = self.library_view.selectionModel().selectedRows() + if not rows or len(rows) == 0: + d = error_dialog(self, _('Cannot view'), _('No book selected')) + d.exec_() + return + + row = rows[0].row() + formats = self.library_view.model().db.formats(row).upper().split(',') + d = ChooseFormatDialog(self, _('Choose the format to view'), formats) + if d.exec_() == d.Accepted: + format = d.format() + self.view_format(row, format) + + def _view_check(self, num, max_=3): + if num <= max_: + return True + return question_dialog(self, _('Multiple Books Selected'), + _('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?' + ) % num) + + def view_folder(self, *args): + rows = self.current_view().selectionModel().selectedRows() + if not rows or len(rows) == 0: + d = error_dialog(self, _('Cannot open folder'), + _('No book selected')) + d.exec_() + return + if not self._view_check(len(rows)): + return + for row in rows: + path = self.library_view.model().db.abspath(row.row()) + open_local_file(path) + + def view_folder_for_id(self, id_): + path = self.library_view.model().db.abspath(id_, index_is_id=True) + open_local_file(path) + + def view_book(self, triggered): + rows = self.current_view().selectionModel().selectedRows() + self._view_books(rows) + + def view_specific_book(self, index): + self._view_books([index]) + + def _view_books(self, rows): + if not rows or len(rows) == 0: + self._launch_viewer() + return + + if not self._view_check(len(rows)): + return + + if self.current_view() is self.library_view: + for row in rows: + if hasattr(row, 'row'): + row = row.row() + + formats = self.library_view.model().db.formats(row) + title = self.library_view.model().db.title(row) + if not formats: + error_dialog(self, _('Cannot view'), + _('%s has no available formats.')%(title,), show=True) + continue + + formats = formats.upper().split(',') + + + in_prefs = False + for format in prefs['input_format_order']: + if format in formats: + in_prefs = True + self.view_format(row, format) + break + if not in_prefs: + self.view_format(row, formats[0]) + else: + paths = self.current_view().model().paths(rows) + for path in paths: + pt = PersistentTemporaryFile('_viewer_'+\ + os.path.splitext(path)[1]) + self.persistent_files.append(pt) + pt.close() + self.device_manager.view_book(\ + Dispatcher(self.book_downloaded_for_viewing), + path, pt.name) + + diff --git a/src/calibre/gui2/add.py b/src/calibre/gui2/add.py index 74f5a2148e..b646d4ac79 100644 --- a/src/calibre/gui2/add.py +++ b/src/calibre/gui2/add.py @@ -443,7 +443,7 @@ class Saver(QObject): from calibre.ebooks.metadata.worker import SaveWorker self.worker = SaveWorker(self.rq, db, self.ids, path, self.opts, spare_server=self.spare_server) - self.connect(self.pd, SIGNAL('canceled()'), self.canceled) + self.pd.canceled.connect(self.canceled) self.timer = QTimer(self) self.connect(self.timer, SIGNAL('timeout()'), self.update) self.timer.start(200) diff --git a/src/calibre/gui2/dialogs/metadata_single.py b/src/calibre/gui2/dialogs/metadata_single.py index 6cb351898b..50223923c1 100644 --- a/src/calibre/gui2/dialogs/metadata_single.py +++ b/src/calibre/gui2/dialogs/metadata_single.py @@ -12,7 +12,7 @@ import time import traceback from PyQt4.Qt import SIGNAL, QObject, Qt, QTimer, QThread, QDate, \ - QPixmap, QListWidgetItem, QDialog + QPixmap, QListWidgetItem, QDialog, pyqtSignal from calibre.gui2 import error_dialog, file_icon_provider, dynamic, \ choose_files, choose_images, ResizableDialog, \ @@ -99,6 +99,7 @@ class Format(QListWidgetItem): class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog): COVER_FETCH_TIMEOUT = 240 # seconds + view_format = pyqtSignal(object) def do_reset_cover(self, *args): pix = QPixmap(I('default_cover.svg')) @@ -474,7 +475,7 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog): def show_format(self, item, *args): fmt = item.ext - self.emit(SIGNAL('view_format(PyQt_PyObject)'), fmt) + self.view_format.emit(fmt) def deduce_author_sort(self): au = unicode(self.authors.text()) diff --git a/src/calibre/gui2/dialogs/progress.py b/src/calibre/gui2/dialogs/progress.py index 91f6edd252..2369575e90 100644 --- a/src/calibre/gui2/dialogs/progress.py +++ b/src/calibre/gui2/dialogs/progress.py @@ -5,12 +5,14 @@ __docformat__ = 'restructuredtext en' '''''' -from PyQt4.Qt import QDialog, SIGNAL, Qt +from PyQt4.Qt import QDialog, pyqtSignal, Qt from calibre.gui2.dialogs.progress_ui import Ui_Dialog class ProgressDialog(QDialog, Ui_Dialog): + canceled = pyqtSignal() + def __init__(self, title, msg='', min=0, max=99, parent=None): QDialog.__init__(self, parent) self.setupUi(self) @@ -23,7 +25,7 @@ class ProgressDialog(QDialog, Ui_Dialog): self.bar.setValue(min) self.canceled = False - self.connect(self.button_box, SIGNAL('rejected()'), self._canceled) + self.button_box.rejected.connect(self._canceled) def set_msg(self, msg=''): self.message.setText(msg) @@ -50,7 +52,7 @@ class ProgressDialog(QDialog, Ui_Dialog): self.canceled = True self.button_box.setDisabled(True) self.title.setText(_('Aborting...')) - self.emit(SIGNAL('canceled()')) + self.canceled.emit() def keyPressEvent(self, ev): if ev.key() == Qt.Key_Escape: From 5d96982933205dff5859c8274b2a25dfe0d4c164 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 11 Aug 2010 22:38:32 -0600 Subject: [PATCH 02/28] Plumbing for InterfaceAction plugins --- src/calibre/customize/__init__.py | 3 +++ src/calibre/customize/ui.py | 15 +++++++++++++-- src/calibre/gui2/__init__.py | 16 +++++++++++----- src/calibre/gui2/actions/__init__.py | 17 +++++++++++++++++ src/calibre/gui2/actions/add.py | 8 +++++--- src/calibre/manual/plugins.rst | 7 +++++++ 6 files changed, 56 insertions(+), 10 deletions(-) diff --git a/src/calibre/customize/__init__.py b/src/calibre/customize/__init__.py index 1348da5e5a..ea11259da2 100644 --- a/src/calibre/customize/__init__.py +++ b/src/calibre/customize/__init__.py @@ -351,3 +351,6 @@ class CatalogPlugin(Plugin): # Default implementation does nothing raise NotImplementedError('CatalogPlugin.generate_catalog() default ' 'method, should be overridden in subclass') + +class InterfaceActionBase(Plugin): + pass diff --git a/src/calibre/customize/ui.py b/src/calibre/customize/ui.py index 7b70bfbb4b..b720964c92 100644 --- a/src/calibre/customize/ui.py +++ b/src/calibre/customize/ui.py @@ -6,7 +6,8 @@ import os, shutil, traceback, functools, sys, re from contextlib import closing from calibre.customize import Plugin, CatalogPlugin, FileTypePlugin, \ - MetadataReaderPlugin, MetadataWriterPlugin + MetadataReaderPlugin, MetadataWriterPlugin, \ + InterfaceActionBase as InterfaceAction from calibre.customize.conversion import InputFormatPlugin, OutputFormatPlugin from calibre.customize.profiles import InputProfile, OutputProfile from calibre.customize.builtins import plugins as builtin_plugins @@ -19,7 +20,6 @@ from calibre.utils.config import make_config_dir, Config, ConfigProxy, \ plugin_dir, OptionParser, prefs from calibre.ebooks.epub.fix import ePubFixer - platform = 'linux' if iswindows: platform = 'windows' @@ -246,6 +246,17 @@ def cover_sources(): # }}} +# Interface Actions # {{{ + +def interface_actions(): + customization = config['plugin_customization'] + for plugin in _initialized_plugins: + if isinstance(plugin, InterfaceAction): + if not is_disabled(plugin): + plugin.site_customization = customization.get(plugin.name, '') + yield plugin +# }}} + # Metadata read/write {{{ _metadata_readers = {} _metadata_writers = {} diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index 686d705abb..062e4eeab9 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -244,14 +244,20 @@ def info_dialog(parent, title, msg, det_msg='', show=False): class Dispatcher(QObject): - '''Convenience class to ensure that a function call always happens in the - thread the receiver was created in.''' + ''' + Convenience class to use Qt signals with arbitrary python callables. + By default, ensures that a function call always happens in the + thread this Dispatcher was created in. + ''' dispatch_signal = pyqtSignal(object, object) - def __init__(self, func): - QObject.__init__(self) + def __init__(self, func, queued=True, parent=None): + QObject.__init__(self, parent) self.func = func - self.dispatch_signal.connect(self.dispatch, type=Qt.QueuedConnection) + typ = Qt.QueuedConnection + if not queued: + typ = Qt.AutoConnection if queued is None else Qt.DirectConnection + self.dispatch_signal.connect(self.dispatch, type=typ) def __call__(self, *args, **kwargs): self.dispatch_signal.emit(args, kwargs) diff --git a/src/calibre/gui2/actions/__init__.py b/src/calibre/gui2/actions/__init__.py index 96aaa843a0..5c1f2d1535 100644 --- a/src/calibre/gui2/actions/__init__.py +++ b/src/calibre/gui2/actions/__init__.py @@ -6,6 +6,23 @@ __copyright__ = '2010, Kovid Goyal ' __docformat__ = 'restructuredtext en' +from calibre.customize import InterfaceActionBase +class InterfaceAction(InterfaceActionBase): + supported_platforms = ['windows', 'osx', 'linux'] + author = 'Kovid Goyal' + type = _('User Interface Action') + + positions = frozenset([]) + separators = frozenset([]) + + def do_genesis(self, gui): + self.gui = gui + self.genesis() + + # Subclassable methods {{{ + def genesis(self): + raise NotImplementedError() + # }}} diff --git a/src/calibre/gui2/actions/add.py b/src/calibre/gui2/actions/add.py index 18a9a4224b..b7be89360f 100644 --- a/src/calibre/gui2/actions/add.py +++ b/src/calibre/gui2/actions/add.py @@ -17,12 +17,14 @@ from calibre.gui2.widgets import IMAGE_EXTENSIONS from calibre.ebooks import BOOK_EXTENSIONS from calibre.utils.filenames import ascii_filename from calibre.constants import preferred_encoding, filesystem_encoding +from calibre.gui2.actions import InterfaceAction +class AddAction(InterfaceAction): -class AddAction(object): + def genesis(self): + self._add_filesystem_book = Dispatcher(self.__add_filesystem_book, + parent=self.gui) - def __init__(self): - self._add_filesystem_book = Dispatcher(self.__add_filesystem_book) def add_recursive(self, single): root = choose_dir(self, 'recursive book import root dir dialog', diff --git a/src/calibre/manual/plugins.rst b/src/calibre/manual/plugins.rst index 26e544d766..8b6919db90 100644 --- a/src/calibre/manual/plugins.rst +++ b/src/calibre/manual/plugins.rst @@ -157,4 +157,11 @@ The base class for such devices is :class:`calibre.devices.usbms.driver.USBMS`. :members: :member-order: bysource +User Interface Actions +-------------------------- + +.. autoclass:: calibre.gui2.actions.InterfaceAction + :show-inheritance: + :members: + :member-order: bysource From 82dc900a11bc9c6de9c7966deb41964ac6a01971 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 12 Aug 2010 11:09:47 -0600 Subject: [PATCH 03/28] Migrated Add Books action --- src/calibre/gui2/actions/__init__.py | 31 +++++++- src/calibre/gui2/actions/add.py | 108 ++++++++++++++++----------- src/calibre/gui2/init.py | 7 +- src/calibre/gui2/layout.py | 16 ---- src/calibre/gui2/main.py | 2 +- src/calibre/gui2/ui.py | 2 +- 6 files changed, 98 insertions(+), 68 deletions(-) diff --git a/src/calibre/gui2/actions/__init__.py b/src/calibre/gui2/actions/__init__.py index 5c1f2d1535..fc5f3bd9b8 100644 --- a/src/calibre/gui2/actions/__init__.py +++ b/src/calibre/gui2/actions/__init__.py @@ -5,8 +5,12 @@ __license__ = 'GPL v3' __copyright__ = '2010, Kovid Goyal ' __docformat__ = 'restructuredtext en' +from functools import partial + +from PyQt4.Qt import QToolButton, QAction, QIcon from calibre.customize import InterfaceActionBase +from calibre.gui2 import Dispatcher class InterfaceAction(InterfaceActionBase): @@ -17,12 +21,31 @@ class InterfaceAction(InterfaceActionBase): positions = frozenset([]) separators = frozenset([]) + popup_type = QToolButton.MenuPopup + + #: Of the form: (text, icon_path, tooltip, keyboard shortcut) + #: tooltip and keybard shortcut can be None + #: shortcut must be a translated string if not None + action_spec = ('text', 'icon', None, None) + def do_genesis(self, gui): self.gui = gui + self.Dispatcher = partial(Dispatcher, parent=gui) + self.create_action() self.genesis() - # Subclassable methods {{{ - def genesis(self): - raise NotImplementedError() - # }}} + def create_action(self): + text, icon, tooltip, shortcut = self.action_spec + action = QAction(QIcon(I(icon)), text, self) + text = tooltip if tooltip else text + action.setToolTip(text) + action.setStatusTip(text) + action.setWhatsThis(text) + action.setAutoRepeat(False) + if shortcut: + action.setShortcut(shortcut) + self.qaction = action + + def genesis(self): + pass diff --git a/src/calibre/gui2/actions/add.py b/src/calibre/gui2/actions/add.py index b7be89360f..8c6b627d5c 100644 --- a/src/calibre/gui2/actions/add.py +++ b/src/calibre/gui2/actions/add.py @@ -8,10 +8,10 @@ __docformat__ = 'restructuredtext en' import os from functools import partial -from PyQt4.Qt import QInputDialog, QPixmap +from PyQt4.Qt import QInputDialog, QPixmap, QMenu -from calibre.gui2 import error_dialog, Dispatcher, choose_files, \ +from calibre.gui2 import error_dialog, choose_files, \ choose_dir, warning_dialog, info_dialog from calibre.gui2.widgets import IMAGE_EXTENSIONS from calibre.ebooks import BOOK_EXTENSIONS @@ -21,20 +21,41 @@ from calibre.gui2.actions import InterfaceAction class AddAction(InterfaceAction): + name = 'Add Books' + action_spec = (_('Add books'), 'add_book.svg', None, _('A')) + positions = frozenset([ + ('toolbar', 'all', 0), + ]) + def genesis(self): - self._add_filesystem_book = Dispatcher(self.__add_filesystem_book, - parent=self.gui) + self._add_filesystem_book = self.Dispatcher(self.__add_filesystem_book) + self.add_menu = QMenu() + self.add_menu.addAction(_('Add books from a single directory'), + self.add_books) + self.add_menu.addAction(_('Add books from directories, including ' + 'sub-directories (One book per directory, assumes every ebook ' + 'file is the same book in a different format)'), + self.add_recursive_single) + self.add_menu.addAction(_('Add books from directories, including ' + 'sub directories (Multiple books per directory, assumes every ' + 'ebook file is a different book)'), self.add_recursive_multiple) + self.add_menu.addSeparator() + self.add_menu.addAction(_('Add Empty book. (Book entry with no ' + 'formats)'), self.add_empty) + self.add_menu.addAction(_('Add from ISBN'), self.add_from_isbn) + self.qaction.setMenu(self.add_menu) + self.qaction.triggered.connect(self.add_books) def add_recursive(self, single): - root = choose_dir(self, 'recursive book import root dir dialog', + root = choose_dir(self.gui, 'recursive book import root dir dialog', 'Select root folder') if not root: return from calibre.gui2.add import Adder - self._adder = Adder(self, - self.library_view.model().db, - Dispatcher(self._files_added), spare_server=self.spare_server) + self._adder = Adder(self.gui, + self.gui.library_view.model().db, + self.Dispatcher(self._files_added), spare_server=self.gui.spare_server) self._adder.add_recursive(root, single) def add_recursive_single(self, *args): @@ -56,13 +77,13 @@ class AddAction(InterfaceAction): Add an empty book item to the library. This does not import any formats from a book file. ''' - num, ok = QInputDialog.getInt(self, _('How many empty books?'), + num, ok = QInputDialog.getInt(self.gui, _('How many empty books?'), _('How many empty books should be added?'), 1, 1, 100) if ok: from calibre.ebooks.metadata import MetaInformation for x in xrange(num): - self.library_view.model().db.import_book(MetaInformation(None), []) - self.library_view.model().books_added(num) + self.gui.library_view.model().db.import_book(MetaInformation(None), []) + self.gui.library_view.model().books_added(num) def add_isbns(self, isbns): from calibre.ebooks.metadata import MetaInformation @@ -70,21 +91,21 @@ class AddAction(InterfaceAction): for x in isbns: mi = MetaInformation(None) mi.isbn = x - ids.add(self.library_view.model().db.import_book(mi, [])) - self.library_view.model().books_added(len(isbns)) - self.do_download_metadata(ids) + ids.add(self.gui.library_view.model().db.import_book(mi, [])) + self.gui.library_view.model().books_added(len(isbns)) + self.gui.do_download_metadata(ids) def files_dropped(self, paths): - to_device = self.stack.currentIndex() != 0 + to_device = self.gui.stack.currentIndex() != 0 self._add_books(paths, to_device) def files_dropped_on_book(self, event, paths): accept = False - if self.current_view() is not self.library_view: + if self.gui.current_view() is not self.gui.library_view: return - db = self.library_view.model().db - current_idx = self.library_view.currentIndex() + db = self.gui.library_view.model().db + current_idx = self.gui.library_view.currentIndex() if not current_idx.isValid(): return cid = db.id(current_idx.row()) for path in paths: @@ -102,7 +123,7 @@ class AddAction(InterfaceAction): accept = True if accept: event.accept() - self.library_view.model().current_changed(current_idx, current_idx) + self.gui.library_view.model().current_changed(current_idx, current_idx) def __add_filesystem_book(self, paths, allow_device=True): if isinstance(paths, basestring): @@ -111,10 +132,10 @@ class AddAction(InterfaceAction): os.R_OK)] if books: - to_device = allow_device and self.stack.currentIndex() != 0 + to_device = allow_device and self.gui.stack.currentIndex() != 0 self._add_books(books, to_device) if to_device: - self.status_bar.show_message(\ + self.gui.status_bar.show_message(\ _('Uploading books to device.'), 2000) @@ -123,7 +144,7 @@ class AddAction(InterfaceAction): def add_from_isbn(self, *args): from calibre.gui2.dialogs.add_from_isbn import AddFromISBN - d = AddFromISBN(self) + d = AddFromISBN(self.gui) if d.exec_() == d.Accepted: self.add_isbns(d.isbns) @@ -144,11 +165,11 @@ class AddAction(InterfaceAction): (_('Comics'), ['cbz', 'cbr', 'cbc']), (_('Archives'), ['zip', 'rar']), ] - to_device = self.stack.currentIndex() != 0 + to_device = self.gui.stack.currentIndex() != 0 if to_device: - filters = [(_('Supported books'), self.device_manager.device.FORMATS)] + filters = [(_('Supported books'), self.gui.device_manager.device.FORMATS)] - books = choose_files(self, 'add books dialog dir', 'Select books', + books = choose_files(self.gui, 'add books dialog dir', 'Select books', filters=filters) if not books: return @@ -156,32 +177,33 @@ class AddAction(InterfaceAction): def _add_books(self, paths, to_device, on_card=None): if on_card is None: - on_card = 'carda' if self.stack.currentIndex() == 2 else 'cardb' if self.stack.currentIndex() == 3 else None + on_card = 'carda' if self.gui.stack.currentIndex() == 2 else \ + 'cardb' if self.gui.stack.currentIndex() == 3 else None if not paths: return from calibre.gui2.add import Adder self.__adder_func = partial(self._files_added, on_card=on_card) - self._adder = Adder(self, - None if to_device else self.library_view.model().db, - Dispatcher(self.__adder_func), spare_server=self.spare_server) + self._adder = Adder(self.gui, + None if to_device else self.gui.library_view.model().db, + self.Dispatcher(self.__adder_func), spare_server=self.gui.spare_server) self._adder.add(paths) def _files_added(self, paths=[], names=[], infos=[], on_card=None): if paths: - self.upload_books(paths, + self.gui.upload_books(paths, list(map(ascii_filename, names)), infos, on_card=on_card) - self.status_bar.show_message( + self.gui.status_bar.show_message( _('Uploading books to device.'), 2000) if getattr(self._adder, 'number_of_books_added', 0) > 0: - self.library_view.model().books_added(self._adder.number_of_books_added) - if hasattr(self, 'db_images'): - self.db_images.reset() + self.gui.library_view.model().books_added(self._adder.number_of_books_added) + if hasattr(self.gui, 'db_images'): + self.gui.db_images.reset() if getattr(self._adder, 'merged_books', False): books = u'\n'.join([x if isinstance(x, unicode) else x.decode(preferred_encoding, 'replace') for x in self._adder.merged_books]) - info_dialog(self, _('Merged some books'), + info_dialog(self.gui, _('Merged some books'), _('Some duplicates were found and merged into the ' 'following existing books:'), det_msg=books, show=True) if getattr(self._adder, 'critical', None): @@ -191,7 +213,7 @@ class AddAction(InterfaceAction): name = name.decode(filesystem_encoding, 'replace') det_msg.append(name+'\n'+log) - warning_dialog(self, _('Failed to read metadata'), + warning_dialog(self.gui, _('Failed to read metadata'), _('Failed to read metadata from the following')+':', det_msg='\n\n'.join(det_msg), show=True) @@ -205,17 +227,17 @@ class AddAction(InterfaceAction): # set the in-library flags, and as a consequence send the library's # metadata for this book to the device. This sets the uuid to the # correct value. - self.set_books_in_library(booklists=[model.db], reset=True) + self.gui.set_books_in_library(booklists=[model.db], reset=True) model.reset() def add_books_from_device(self, view): rows = view.selectionModel().selectedRows() if not rows or len(rows) == 0: - d = error_dialog(self, _('Add to library'), _('No book selected')) + d = error_dialog(self.gui, _('Add to library'), _('No book selected')) d.exec_() return paths = [p for p in view._model.paths(rows) if p is not None] - ve = self.device_manager.device.VIRTUAL_BOOK_EXTENSIONS + ve = self.gui.device_manager.device.VIRTUAL_BOOK_EXTENSIONS def ext(x): ans = os.path.splitext(x)[1] ans = ans[1:] if len(ans) > 1 else ans @@ -223,21 +245,21 @@ class AddAction(InterfaceAction): remove = set([p for p in paths if ext(p) in ve]) if remove: paths = [p for p in paths if p not in remove] - info_dialog(self, _('Not Implemented'), + info_dialog(self.gui, _('Not Implemented'), _('The following books are virtual and cannot be added' ' to the calibre library:'), '\n'.join(remove), show=True) if not paths: return if not paths or len(paths) == 0: - d = error_dialog(self, _('Add to library'), _('No book files found')) + d = error_dialog(self.gui, _('Add to library'), _('No book files found')) d.exec_() return from calibre.gui2.add import Adder self.__adder_func = partial(self._add_from_device_adder, on_card=None, model=view._model) - self._adder = Adder(self, self.library_view.model().db, - Dispatcher(self.__adder_func), spare_server=self.spare_server) + self._adder = Adder(self.gui, self.gui.library_view.model().db, + self.Dispatcher(self.__adder_func), spare_server=self.gui.spare_server) self._adder.add(paths) diff --git a/src/calibre/gui2/init.py b/src/calibre/gui2/init.py index a3ae5b77aa..7f8ad2d23c 100644 --- a/src/calibre/gui2/init.py +++ b/src/calibre/gui2/init.py @@ -63,7 +63,8 @@ class LibraryViewMixin(object): # {{{ add_to_library = None, edit_device_collections=None, similar_menu=similar_menu) - add_to_library = (_('Add books to library'), self.add_books_from_device) + add_to_library = (_('Add books to library'), + self.iactions['Add Books'].add_books_from_device) edit_device_collections = (_('Manage collections'), partial(self.edit_device_collections, oncard=None)) @@ -89,7 +90,7 @@ class LibraryViewMixin(object): # {{{ add_to_library=add_to_library, edit_device_collections=edit_device_collections) - self.library_view.files_dropped.connect(self.files_dropped, type=Qt.QueuedConnection) + self.library_view.files_dropped.connect(self.iactions['Add Books'].files_dropped, type=Qt.QueuedConnection) for func, args in [ ('connect_to_search_box', (self.search, self.search_done)), @@ -305,7 +306,7 @@ class LayoutMixin(object): # {{{ def finalize_layout(self): self.status_bar.initialize(self.system_tray_icon) self.book_details.show_book_info.connect(self.show_book_info) - self.book_details.files_dropped.connect(self.files_dropped_on_book) + self.book_details.files_dropped.connect(self.iactions['Add Books'].files_dropped_on_book) self.book_details.open_containing_folder.connect(self.view_folder_for_id) self.book_details.view_specific_format.connect(self.view_format_by_id) diff --git a/src/calibre/gui2/layout.py b/src/calibre/gui2/layout.py index 8a919c59f5..05763db658 100644 --- a/src/calibre/gui2/layout.py +++ b/src/calibre/gui2/layout.py @@ -528,22 +528,6 @@ class MainWindowMixin(object): md.addSeparator() md.addAction(self.action_merge) - self.add_menu = QMenu() - self.add_menu.addAction(_('Add books from a single directory'), - self.add_books) - self.add_menu.addAction(_('Add books from directories, including ' - 'sub-directories (One book per directory, assumes every ebook ' - 'file is the same book in a different format)'), - self.add_recursive_single) - self.add_menu.addAction(_('Add books from directories, including ' - 'sub directories (Multiple books per directory, assumes every ' - 'ebook file is a different book)'), self.add_recursive_multiple) - self.add_menu.addSeparator() - self.add_menu.addAction(_('Add Empty book. (Book entry with no ' - 'formats)'), self.add_empty) - self.add_menu.addAction(_('Add from ISBN'), self.add_from_isbn) - self.action_add.setMenu(self.add_menu) - self.action_add.triggered.connect(self.add_books) self.action_del.triggered.connect(self.delete_books) self.action_edit.triggered.connect(self.edit_metadata) self.action_merge.triggered.connect(self.merge_books) diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py index ca896fc014..f9d7d80b24 100644 --- a/src/calibre/gui2/main.py +++ b/src/calibre/gui2/main.py @@ -155,7 +155,7 @@ class GuiRunner(QObject): main.initialize(self.library_path, self.db, self.listener, self.actions) if DEBUG: prints('Started up in', time.time() - self.startup_time) - add_filesystem_book = partial(main.add_filesystem_book, allow_device=False) + add_filesystem_book = partial(main.iactions['Add Books'].add_filesystem_book, allow_device=False) sys.excepthook = main.unhandled_exception if len(self.args) > 1: p = os.path.abspath(self.args[1]) diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index 0b1091f848..cca6a378d1 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -329,7 +329,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ if len(argv) > 1: path = os.path.abspath(argv[1]) if os.access(path, os.R_OK): - self.add_filesystem_book(path) + self.iactions['Add Books'].add_filesystem_book(path) self.setWindowState(self.windowState() & \ ~Qt.WindowMinimized|Qt.WindowActive) self.show_windows() From 206547021d8f1bf69b67a78d1111023f2fdfb861 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 12 Aug 2010 12:12:16 -0600 Subject: [PATCH 04/28] Migrate Fetch Annotations action and refactor plugins so as to delay load the gui components --- src/calibre/customize/__init__.py | 8 +++++- src/calibre/customize/builtins.py | 12 ++++++++ src/calibre/gui2/actions/__init__.py | 26 ++++++++++------- src/calibre/gui2/actions/annotate.py | 43 +++++++++++++++++----------- src/calibre/gui2/device.py | 3 +- src/calibre/gui2/ui.py | 28 +++++++++++------- 6 files changed, 80 insertions(+), 40 deletions(-) diff --git a/src/calibre/customize/__init__.py b/src/calibre/customize/__init__.py index ea11259da2..88c9324239 100644 --- a/src/calibre/customize/__init__.py +++ b/src/calibre/customize/__init__.py @@ -353,4 +353,10 @@ class CatalogPlugin(Plugin): 'method, should be overridden in subclass') class InterfaceActionBase(Plugin): - pass + + supported_platforms = ['windows', 'osx', 'linux'] + author = 'Kovid Goyal' + type = _('User Interface Action') + can_be_disabled = False + + actual_plugin = None diff --git a/src/calibre/customize/builtins.py b/src/calibre/customize/builtins.py index 998bfa7b1e..d71d934e2c 100644 --- a/src/calibre/customize/builtins.py +++ b/src/calibre/customize/builtins.py @@ -574,3 +574,15 @@ plugins += [x for x in list(locals().values()) if isinstance(x, type) and \ plugins += [x for x in list(locals().values()) if isinstance(x, type) and \ x.__name__.endswith('MetadataWriter')] plugins += input_profiles + output_profiles + +from calibre.customize import InterfaceActionBase + +class ActionAdd(InterfaceActionBase): + name = 'action_add' + actual_plugin = 'calibre.gui2.actions.add:AddAction' + +class ActionFetchAnnotations(InterfaceActionBase): + name = 'action_fetch_annotations' + actual_plugin = 'calibre.gui2.actions.annotate:FetchAnnotationsAction' + +plugins += [ActionAdd, ActionFetchAnnotations] diff --git a/src/calibre/gui2/actions/__init__.py b/src/calibre/gui2/actions/__init__.py index fc5f3bd9b8..74a8cbe5f5 100644 --- a/src/calibre/gui2/actions/__init__.py +++ b/src/calibre/gui2/actions/__init__.py @@ -7,17 +7,14 @@ __docformat__ = 'restructuredtext en' from functools import partial -from PyQt4.Qt import QToolButton, QAction, QIcon +from PyQt4.Qt import QToolButton, QAction, QIcon, QObject -from calibre.customize import InterfaceActionBase from calibre.gui2 import Dispatcher -class InterfaceAction(InterfaceActionBase): - - supported_platforms = ['windows', 'osx', 'linux'] - author = 'Kovid Goyal' - type = _('User Interface Action') +class InterfaceAction(QObject): + name = 'Implement me' + priority = 1 positions = frozenset([]) separators = frozenset([]) @@ -28,15 +25,22 @@ class InterfaceAction(InterfaceActionBase): #: shortcut must be a translated string if not None action_spec = ('text', 'icon', None, None) - def do_genesis(self, gui): - self.gui = gui - self.Dispatcher = partial(Dispatcher, parent=gui) + def __init__(self, parent, site_customization): + QObject.__init__(self, parent) + self.gui = parent + self.site_customization = site_customization + + def do_genesis(self): + self.Dispatcher = partial(Dispatcher, parent=self) self.create_action() self.genesis() def create_action(self): text, icon, tooltip, shortcut = self.action_spec - action = QAction(QIcon(I(icon)), text, self) + if icon is not None: + action = QAction(QIcon(I(icon)), text, self.gui) + else: + action = QAction(text, self.gui) text = tooltip if tooltip else text action.setToolTip(text) action.setStatusTip(text) diff --git a/src/calibre/gui2/actions/annotate.py b/src/calibre/gui2/actions/annotate.py index 22f42156dd..e4c45742c2 100644 --- a/src/calibre/gui2/actions/annotate.py +++ b/src/calibre/gui2/actions/annotate.py @@ -9,19 +9,26 @@ import os, datetime from PyQt4.Qt import pyqtSignal, QModelIndex, QThread, Qt -from calibre.gui2 import error_dialog, Dispatcher, gprefs +from calibre.gui2 import error_dialog, gprefs from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag, NavigableString from calibre import strftime +from calibre.gui2.actions import InterfaceAction -class AnnotationsAction(object): +class FetchAnnotationsAction(InterfaceAction): + + name = 'Fetch Annotations' + action_spec = (_('Fetch Annotations'), None, None, None) + + def genesis(self): + pass def fetch_annotations(self, *args): # Generate a path_map from selected ids def get_ids_from_selected_rows(): - rows = self.library_view.selectionModel().selectedRows() + rows = self.gui.library_view.selectionModel().selectedRows() if not rows or len(rows) < 2: - rows = xrange(self.library_view.model().rowCount(QModelIndex())) - ids = map(self.library_view.model().id, rows) + rows = xrange(self.gui.library_view.model().rowCount(QModelIndex())) + ids = map(self.gui.library_view.model().id, rows) return ids def get_formats(id): @@ -42,18 +49,18 @@ class AnnotationsAction(object): path_map[id] = dict(path=a_path, fmts=get_formats(id)) return path_map - device = self.device_manager.device + device = self.gui.device_manager.device - if self.current_view() is not self.library_view: - return error_dialog(self, _('Use library only'), + if self.gui.current_view() is not self.gui.library_view: + return error_dialog(self.gui, _('Use library only'), _('User annotations generated from main library only'), show=True) - db = self.library_view.model().db + db = self.gui.library_view.model().db # Get the list of ids ids = get_ids_from_selected_rows() if not ids: - return error_dialog(self, _('No books selected'), + return error_dialog(self.gui, _('No books selected'), _('No books selected to fetch annotations from'), show=True) @@ -61,7 +68,7 @@ class AnnotationsAction(object): path_map = generate_annotation_paths(ids, db, device) # Dispatch to devices.kindle.driver.get_annotations() - self.device_manager.annotations(Dispatcher(self.annotations_fetched), + self.gui.device_manager.annotations(self.Dispatcher(self.annotations_fetched), path_map) def annotations_fetched(self, job): @@ -70,7 +77,7 @@ class AnnotationsAction(object): from calibre.gui2.dialogs.progress import ProgressDialog from calibre.library.cli import do_add_format - class Updater(QThread): + class Updater(QThread): # {{{ update_progress = pyqtSignal(int) update_done = pyqtSignal() @@ -220,16 +227,18 @@ class AnnotationsAction(object): self.update_done.emit() self.done_callback(self.am.keys()) + # }}} + if not job.result: return - if self.current_view() is not self.library_view: - return error_dialog(self, _('Use library only'), + if self.gui.current_view() is not self.gui.library_view: + return error_dialog(self.gui, _('Use library only'), _('User annotations generated from main library only'), show=True) - db = self.library_view.model().db + db = self.gui.library_view.model().db - self.__annotation_updater = Updater(self, db, job.result, - Dispatcher(self.library_view.model().refresh_ids)) + self.__annotation_updater = Updater(self.gui, db, job.result, + self.Dispatcher(self.gui.library_view.model().refresh_ids)) self.__annotation_updater.start() diff --git a/src/calibre/gui2/device.py b/src/calibre/gui2/device.py index 789ae68723..0f83afa6dd 100644 --- a/src/calibre/gui2/device.py +++ b/src/calibre/gui2/device.py @@ -652,7 +652,8 @@ class DeviceMixin(object): # {{{ self.connect(self._sync_menu, SIGNAL('sync(PyQt_PyObject, PyQt_PyObject, PyQt_PyObject)'), self.dispatch_sync_event) - self._sync_menu.fetch_annotations.connect(self.fetch_annotations) + self._sync_menu.fetch_annotations.connect( + self.iactions['Fetch Annotations'].fetch_annotations) self._sync_menu.disconnect_mounted_device.connect(self.disconnect_mounted_device) if self.device_connected: self.share_conn_menu.connect_to_folder_action.setEnabled(False) diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index cca6a378d1..63b1e72de4 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -23,6 +23,8 @@ from calibre.constants import __appname__, isosx from calibre.ptempfile import PersistentTemporaryFile from calibre.utils.config import prefs, dynamic from calibre.utils.ipc.server import Server +from calibre.library.database2 import LibraryDatabase2 +from calibre.customize import interface_actions from calibre.gui2 import error_dialog, GetMetadata, open_local_file, \ gprefs, max_available_height, config, info_dialog, Dispatcher from calibre.gui2.cover_flow import CoverFlowMixin @@ -33,16 +35,11 @@ from calibre.gui2.layout import MainWindowMixin from calibre.gui2.device import DeviceMixin from calibre.gui2.jobs import JobManager, JobsDialog, JobsButton from calibre.gui2.dialogs.config import ConfigDialog - from calibre.gui2.dialogs.book_info import BookInfo -from calibre.library.database2 import LibraryDatabase2 from calibre.gui2.init import LibraryViewMixin, LayoutMixin from calibre.gui2.search_box import SearchBoxMixin, SavedSearchBoxMixin from calibre.gui2.search_restriction_mixin import SearchRestrictionMixin from calibre.gui2.tag_view import TagBrowserMixin -from calibre.gui2.actions import AnnotationsAction, AddAction, DeleteAction, \ - EditMetadataAction, SaveToDiskAction, GenerateCatalogAction, FetchNewsAction, \ - ConvertAction, ViewAction class Listener(Thread): # {{{ @@ -91,16 +88,26 @@ class SystemTrayIcon(QSystemTrayIcon): # {{{ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ TagBrowserMixin, CoverFlowMixin, LibraryViewMixin, SearchBoxMixin, - SavedSearchBoxMixin, SearchRestrictionMixin, LayoutMixin, UpdateMixin, - AnnotationsAction, AddAction, DeleteAction, - EditMetadataAction, SaveToDiskAction, GenerateCatalogAction, FetchNewsAction, - ConvertAction, ViewAction): + SavedSearchBoxMixin, SearchRestrictionMixin, LayoutMixin, UpdateMixin + ): 'The main GUI' def __init__(self, opts, parent=None): MainWindow.__init__(self, opts, parent) self.opts = opts + acmap = {} + for action in interface_actions(): + mod, cls = action.actual_plugin.split(':') + ac = getattr(__import__(mod, fromlist=['1'], level=0), cls)(self, + action.site_customization) + if ac.name in acmap: + if ac.priority >= acmap[ac.name].priority: + acmap[ac.name] = ac + else: + acmap[ac.name] = ac + + self.iactions = acmap def initialize(self, library_path, db, listener, actions): opts = self.opts @@ -120,6 +127,8 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ self.check_messages_timer.start(1000) MainWindowMixin.__init__(self, db) + for ac in self.iactions.values(): + ac.do_genesis() # Jobs Button {{{ self.job_manager = JobManager() @@ -249,7 +258,6 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ self.start_content_server() self.keyboard_interrupt.connect(self.quit, type=Qt.QueuedConnection) - AddAction.__init__(self) self.read_settings() self.finalize_layout() From cb07d093e25fddef5f569577c920a1cd33788740 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 12 Aug 2010 17:59:51 -0600 Subject: [PATCH 05/28] Migrate catalog and convert actions. And remove layout spec from plugins --- src/calibre/customize/builtins.py | 15 +++- src/calibre/gui2/actions/__init__.py | 5 +- src/calibre/gui2/actions/add.py | 3 - src/calibre/gui2/actions/annotate.py | 2 +- src/calibre/gui2/actions/catalog.py | 38 +++++----- src/calibre/gui2/actions/convert.py | 99 ++++++++++++++++---------- src/calibre/gui2/actions/fetch_news.py | 3 + src/calibre/gui2/device.py | 8 +-- src/calibre/gui2/layout.py | 12 ---- src/calibre/gui2/ui.py | 1 - 10 files changed, 103 insertions(+), 83 deletions(-) diff --git a/src/calibre/customize/builtins.py b/src/calibre/customize/builtins.py index d71d934e2c..8462ae5d38 100644 --- a/src/calibre/customize/builtins.py +++ b/src/calibre/customize/builtins.py @@ -578,11 +578,20 @@ plugins += input_profiles + output_profiles from calibre.customize import InterfaceActionBase class ActionAdd(InterfaceActionBase): - name = 'action_add' + name = 'Add Books' actual_plugin = 'calibre.gui2.actions.add:AddAction' class ActionFetchAnnotations(InterfaceActionBase): - name = 'action_fetch_annotations' + name = 'Fetch Annotations' actual_plugin = 'calibre.gui2.actions.annotate:FetchAnnotationsAction' -plugins += [ActionAdd, ActionFetchAnnotations] +class ActionGenerateCatalog(InterfaceActionBase): + name = 'Generate Catalog' + actual_plugin = 'calibre.gui2.actions.catalog:GenerateCatalogAction' + +class ActionConvert(InterfaceActionBase): + name = 'Convert Books' + actual_plugin = 'calibre.gui2.actions.convert:ConvertAction' + +plugins += [ActionAdd, ActionFetchAnnotations, ActionGenerateCatalog, + ActionConvert] diff --git a/src/calibre/gui2/actions/__init__.py b/src/calibre/gui2/actions/__init__.py index 74a8cbe5f5..65d0078c50 100644 --- a/src/calibre/gui2/actions/__init__.py +++ b/src/calibre/gui2/actions/__init__.py @@ -16,17 +16,16 @@ class InterfaceAction(QObject): name = 'Implement me' priority = 1 positions = frozenset([]) - separators = frozenset([]) - popup_type = QToolButton.MenuPopup #: Of the form: (text, icon_path, tooltip, keyboard shortcut) - #: tooltip and keybard shortcut can be None + #: icon, tooltip and keybard shortcut can be None #: shortcut must be a translated string if not None action_spec = ('text', 'icon', None, None) def __init__(self, parent, site_customization): QObject.__init__(self, parent) + self.setObjectName(self.name) self.gui = parent self.site_customization = site_customization diff --git a/src/calibre/gui2/actions/add.py b/src/calibre/gui2/actions/add.py index 8c6b627d5c..668af0957e 100644 --- a/src/calibre/gui2/actions/add.py +++ b/src/calibre/gui2/actions/add.py @@ -23,9 +23,6 @@ class AddAction(InterfaceAction): name = 'Add Books' action_spec = (_('Add books'), 'add_book.svg', None, _('A')) - positions = frozenset([ - ('toolbar', 'all', 0), - ]) def genesis(self): self._add_filesystem_book = self.Dispatcher(self.__add_filesystem_book) diff --git a/src/calibre/gui2/actions/annotate.py b/src/calibre/gui2/actions/annotate.py index e4c45742c2..d8b7b829b2 100644 --- a/src/calibre/gui2/actions/annotate.py +++ b/src/calibre/gui2/actions/annotate.py @@ -17,7 +17,7 @@ from calibre.gui2.actions import InterfaceAction class FetchAnnotationsAction(InterfaceAction): name = 'Fetch Annotations' - action_spec = (_('Fetch Annotations'), None, None, None) + action_spec = (_('Fetch annotations (experimental)'), None, None, None) def genesis(self): pass diff --git a/src/calibre/gui2/actions/catalog.py b/src/calibre/gui2/actions/catalog.py index f8c9b24b30..6807d7717e 100644 --- a/src/calibre/gui2/actions/catalog.py +++ b/src/calibre/gui2/actions/catalog.py @@ -9,58 +9,62 @@ import os, shutil from PyQt4.Qt import QModelIndex -from calibre.gui2 import error_dialog, Dispatcher, choose_dir +from calibre.gui2 import error_dialog, choose_dir from calibre.gui2.tools import generate_catalog from calibre.utils.config import dynamic +from calibre.gui2.actions import InterfaceAction -class GenerateCatalogAction(object): +class GenerateCatalogAction(InterfaceAction): + + name = 'Generate Catalog' + action_spec = (_('Create catalog of books in your calibre library'), None, None, None) def generate_catalog(self): - rows = self.library_view.selectionModel().selectedRows() + rows = self.gui.library_view.selectionModel().selectedRows() if not rows or len(rows) < 2: - rows = xrange(self.library_view.model().rowCount(QModelIndex())) - ids = map(self.library_view.model().id, rows) + rows = xrange(self.gui.library_view.model().rowCount(QModelIndex())) + ids = map(self.gui.library_view.model().id, rows) dbspec = None if not ids: - return error_dialog(self, _('No books selected'), + return error_dialog(self.gui, _('No books selected'), _('No books selected to generate catalog for'), show=True) # Calling gui2.tools:generate_catalog() - ret = generate_catalog(self, dbspec, ids, self.device_manager.device) + ret = generate_catalog(self.gui, dbspec, ids, self.gui.device_manager.device) if ret is None: return func, args, desc, out, sync, title = ret fmt = os.path.splitext(out)[1][1:].upper() - job = self.job_manager.run_job( - Dispatcher(self.catalog_generated), func, args=args, + job = self.gui.job_manager.run_job( + self.Dispatcher(self.catalog_generated), func, args=args, description=desc) job.catalog_file_path = out job.fmt = fmt job.catalog_sync, job.catalog_title = sync, title - self.status_bar.show_message(_('Generating %s catalog...')%fmt) + self.gui.status_bar.show_message(_('Generating %s catalog...')%fmt) def catalog_generated(self, job): if job.result: # Search terms nulled catalog results - return error_dialog(self, _('No books found'), + return error_dialog(self.gui, _('No books found'), _("No books to catalog\nCheck exclude tags"), show=True) if job.failed: - return self.job_exception(job) - id = self.library_view.model().add_catalog(job.catalog_file_path, job.catalog_title) - self.library_view.model().reset() + return self.gui.job_exception(job) + id = self.gui.library_view.model().add_catalog(job.catalog_file_path, job.catalog_title) + self.gui.library_view.model().reset() if job.catalog_sync: sync = dynamic.get('catalogs_to_be_synced', set([])) sync.add(id) dynamic.set('catalogs_to_be_synced', sync) - self.status_bar.show_message(_('Catalog generated.'), 3000) - self.sync_catalogs() + self.gui.status_bar.show_message(_('Catalog generated.'), 3000) + self.gui.sync_catalogs() if job.fmt not in ['EPUB','MOBI']: - export_dir = choose_dir(self, _('Export Catalog Directory'), + export_dir = choose_dir(self.gui, _('Export Catalog Directory'), _('Select destination for %s.%s') % (job.catalog_title, job.fmt.lower())) if export_dir: destination = os.path.join(export_dir, '%s.%s' % (job.catalog_title, job.fmt.lower())) diff --git a/src/calibre/gui2/actions/convert.py b/src/calibre/gui2/actions/convert.py index 9d5f1da048..ace877b315 100644 --- a/src/calibre/gui2/actions/convert.py +++ b/src/calibre/gui2/actions/convert.py @@ -6,133 +6,154 @@ __copyright__ = '2010, Kovid Goyal ' __docformat__ = 'restructuredtext en' import os +from functools import partial -from PyQt4.Qt import QModelIndex +from PyQt4.Qt import QModelIndex, QMenu from calibre.gui2 import error_dialog, Dispatcher from calibre.gui2.tools import convert_single_ebook, convert_bulk_ebook from calibre.utils.config import prefs +from calibre.gui2.actions import InterfaceAction + +class ConvertAction(InterfaceAction): + + name = 'Convert Books' + action_spec = (_('Convert books'), 'convert.svg', None, _('C')) + + def genesis(self): + cm = QMenu() + cm.addAction(_('Convert individually'), partial(self.convert_ebook, + False, bulk=False)) + cm.addAction(_('Bulk convert'), + partial(self.convert_ebook, False, bulk=True)) + cm.addSeparator() + ac = cm.addAction( + _('Create catalog of books in your calibre library')) + ac.triggered.connect(self.gui.iactions['Generate Catalog'].generate_catalog) + self.qaction.setMenu(cm) + self.qaction.triggered.connect(self.convert_ebook) + self.convert_menu = cm + self.conversion_jobs = {} -class ConvertAction(object): def auto_convert(self, book_ids, on_card, format): - previous = self.library_view.currentIndex() + previous = self.gui.library_view.currentIndex() rows = [x.row() for x in \ - self.library_view.selectionModel().selectedRows()] - jobs, changed, bad = convert_single_ebook(self, self.library_view.model().db, book_ids, True, format) + self.gui.library_view.selectionModel().selectedRows()] + jobs, changed, bad = convert_single_ebook(self.gui, self.gui.library_view.model().db, book_ids, True, format) if jobs == []: return self.queue_convert_jobs(jobs, changed, bad, rows, previous, self.book_auto_converted, extra_job_args=[on_card]) def auto_convert_mail(self, to, fmts, delete_from_library, book_ids, format): - previous = self.library_view.currentIndex() + previous = self.gui.library_view.currentIndex() rows = [x.row() for x in \ - self.library_view.selectionModel().selectedRows()] - jobs, changed, bad = convert_single_ebook(self, self.library_view.model().db, book_ids, True, format) + self.gui.library_view.selectionModel().selectedRows()] + jobs, changed, bad = convert_single_ebook(self.gui, self.gui.library_view.model().db, book_ids, True, format) if jobs == []: return self.queue_convert_jobs(jobs, changed, bad, rows, previous, self.book_auto_converted_mail, extra_job_args=[delete_from_library, to, fmts]) def auto_convert_news(self, book_ids, format): - previous = self.library_view.currentIndex() + previous = self.gui.library_view.currentIndex() rows = [x.row() for x in \ - self.library_view.selectionModel().selectedRows()] - jobs, changed, bad = convert_single_ebook(self, self.library_view.model().db, book_ids, True, format) + self.gui.library_view.selectionModel().selectedRows()] + jobs, changed, bad = convert_single_ebook(self.gui, self.gui.library_view.model().db, book_ids, True, format) if jobs == []: return self.queue_convert_jobs(jobs, changed, bad, rows, previous, self.book_auto_converted_news) def auto_convert_catalogs(self, book_ids, format): - previous = self.library_view.currentIndex() + previous = self.gui.library_view.currentIndex() rows = [x.row() for x in \ - self.library_view.selectionModel().selectedRows()] - jobs, changed, bad = convert_single_ebook(self, self.library_view.model().db, book_ids, True, format) + self.gui.library_view.selectionModel().selectedRows()] + jobs, changed, bad = convert_single_ebook(self.gui, self.gui.library_view.model().db, book_ids, True, format) if jobs == []: return self.queue_convert_jobs(jobs, changed, bad, rows, previous, self.book_auto_converted_catalogs) def get_books_for_conversion(self): rows = [r.row() for r in \ - self.library_view.selectionModel().selectedRows()] + self.gui.library_view.selectionModel().selectedRows()] if not rows or len(rows) == 0: - d = error_dialog(self, _('Cannot convert'), + d = error_dialog(self.gui, _('Cannot convert'), _('No books selected')) d.exec_() return None - return [self.library_view.model().db.id(r) for r in rows] + return [self.gui.library_view.model().db.id(r) for r in rows] def convert_ebook(self, checked, bulk=None): book_ids = self.get_books_for_conversion() if book_ids is None: return - previous = self.library_view.currentIndex() + previous = self.gui.library_view.currentIndex() rows = [x.row() for x in \ - self.library_view.selectionModel().selectedRows()] + self.gui.library_view.selectionModel().selectedRows()] num = 0 if bulk or (bulk is None and len(book_ids) > 1): - self.__bulk_queue = convert_bulk_ebook(self, self.queue_convert_jobs, - self.library_view.model().db, book_ids, + self.__bulk_queue = convert_bulk_ebook(self.gui, self.queue_convert_jobs, + self.gui.library_view.model().db, book_ids, out_format=prefs['output_format'], args=(rows, previous, self.book_converted)) if self.__bulk_queue is None: return num = len(self.__bulk_queue.book_ids) else: - jobs, changed, bad = convert_single_ebook(self, - self.library_view.model().db, book_ids, out_format=prefs['output_format']) + jobs, changed, bad = convert_single_ebook(self.gui, + self.gui.library_view.model().db, book_ids, out_format=prefs['output_format']) self.queue_convert_jobs(jobs, changed, bad, rows, previous, self.book_converted) num = len(jobs) if num > 0: - self.status_bar.show_message(_('Starting conversion of %d book(s)') % + self.gui.status_bar.show_message(_('Starting conversion of %d book(s)') % num, 2000) def queue_convert_jobs(self, jobs, changed, bad, rows, previous, converted_func, extra_job_args=[]): for func, args, desc, fmt, id, temp_files in jobs: if id not in bad: - job = self.job_manager.run_job(Dispatcher(converted_func), + job = self.gui.job_manager.run_job(Dispatcher(converted_func), func, args=args, description=desc) args = [temp_files, fmt, id]+extra_job_args self.conversion_jobs[job] = tuple(args) if changed: - self.library_view.model().refresh_rows(rows) - current = self.library_view.currentIndex() - self.library_view.model().current_changed(current, previous) + self.gui.library_view.model().refresh_rows(rows) + current = self.gui.library_view.currentIndex() + self.gui.library_view.model().current_changed(current, previous) def book_auto_converted(self, job): temp_files, fmt, book_id, on_card = self.conversion_jobs[job] self.book_converted(job) - self.sync_to_device(on_card, False, specific_format=fmt, send_ids=[book_id], do_auto_convert=False) + self.gui.sync_to_device(on_card, False, specific_format=fmt, send_ids=[book_id], do_auto_convert=False) def book_auto_converted_mail(self, job): temp_files, fmt, book_id, delete_from_library, to, fmts = self.conversion_jobs[job] self.book_converted(job) - self.send_by_mail(to, fmts, delete_from_library, specific_format=fmt, send_ids=[book_id], do_auto_convert=False) + self.gui.send_by_mail(to, fmts, delete_from_library, specific_format=fmt, send_ids=[book_id], do_auto_convert=False) def book_auto_converted_news(self, job): temp_files, fmt, book_id = self.conversion_jobs[job] self.book_converted(job) - self.sync_news(send_ids=[book_id], do_auto_convert=False) + self.gui.sync_news(send_ids=[book_id], do_auto_convert=False) def book_auto_converted_catalogs(self, job): temp_files, fmt, book_id = self.conversion_jobs[job] self.book_converted(job) - self.sync_catalogs(send_ids=[book_id], do_auto_convert=False) + self.gui.sync_catalogs(send_ids=[book_id], do_auto_convert=False) def book_converted(self, job): temp_files, fmt, book_id = self.conversion_jobs.pop(job)[:3] try: if job.failed: - self.job_exception(job) + self.gui.job_exception(job) return data = open(temp_files[-1].name, 'rb') - self.library_view.model().db.add_format(book_id, \ + self.gui.library_view.model().db.add_format(book_id, \ fmt, data, index_is_id=True) data.close() - self.status_bar.show_message(job.description + \ + self.gui.status_bar.show_message(job.description + \ (' completed'), 2000) finally: for f in temp_files: @@ -141,8 +162,8 @@ class ConvertAction(object): os.remove(f.name) except: pass - self.tags_view.recount() - if self.current_view() is self.library_view: - current = self.library_view.currentIndex() - self.library_view.model().current_changed(current, QModelIndex()) + self.gui.tags_view.recount() + if self.gui.current_view() is self.gui.library_view: + current = self.gui.library_view.currentIndex() + self.gui.library_view.model().current_changed(current, QModelIndex()) diff --git a/src/calibre/gui2/actions/fetch_news.py b/src/calibre/gui2/actions/fetch_news.py index c051f362f1..72c93937dc 100644 --- a/src/calibre/gui2/actions/fetch_news.py +++ b/src/calibre/gui2/actions/fetch_news.py @@ -11,6 +11,9 @@ from calibre.utils.config import dynamic class FetchNewsAction(object): + def genesis(self): + self.conversion_jobs = {} + def download_scheduled_recipe(self, arg): func, args, desc, fmt, temp_files = \ fetch_scheduled_recipe(arg) diff --git a/src/calibre/gui2/device.py b/src/calibre/gui2/device.py index 0f83afa6dd..6cc8e47aa5 100644 --- a/src/calibre/gui2/device.py +++ b/src/calibre/gui2/device.py @@ -925,7 +925,7 @@ class DeviceMixin(object): # {{{ _('Auto convert the following books before sending via ' 'email?'), det_msg=autos, buttons=QMessageBox.Yes|QMessageBox.Cancel): - self.auto_convert_mail(to, fmts, delete_from_library, auto, format) + self.iactions['Convert Books'].auto_convert_mail(to, fmts, delete_from_library, auto, format) if bad: bad = '\n'.join('%s'%(i,) for i in bad) @@ -1027,7 +1027,7 @@ class DeviceMixin(object): # {{{ _('Auto convert the following books before uploading to ' 'the device?'), det_msg=autos, buttons=QMessageBox.Yes|QMessageBox.Cancel): - self.auto_convert_catalogs(auto, format) + self.iactions['Convert Books'].auto_convert_catalogs(auto, format) files = [f for f in files if f is not None] if not files: dynamic.set('catalogs_to_be_synced', set([])) @@ -1089,7 +1089,7 @@ class DeviceMixin(object): # {{{ _('Auto convert the following books before uploading to ' 'the device?'), det_msg=autos, buttons=QMessageBox.Yes|QMessageBox.Cancel): - self.auto_convert_news(auto, format) + self.iactions['Convert Books'].auto_convert_news(auto, format) files = [f for f in files if f is not None] for f in files: f.deleted_after_upload = del_on_upload @@ -1208,7 +1208,7 @@ class DeviceMixin(object): # {{{ _('Auto convert the following books before uploading to ' 'the device?'), det_msg=autos, buttons=QMessageBox.Yes|QMessageBox.Cancel): - self.auto_convert(auto, on_card, format) + self.iactions['Convert Books'].auto_convert(auto, on_card, format) if bad: bad = '\n'.join('%s'%(i,) for i in bad) diff --git a/src/calibre/gui2/layout.py b/src/calibre/gui2/layout.py index 05763db658..b0851c0b25 100644 --- a/src/calibre/gui2/layout.py +++ b/src/calibre/gui2/layout.py @@ -585,18 +585,6 @@ class MainWindowMixin(object): self.action_edit.setMenu(md) self.action_save.setMenu(self.save_menu) - cm = QMenu() - cm.addAction(_('Convert individually'), partial(self.convert_ebook, - False, bulk=False)) - cm.addAction(_('Bulk convert'), - partial(self.convert_ebook, False, bulk=True)) - cm.addSeparator() - ac = cm.addAction( - _('Create catalog of books in your calibre library')) - ac.triggered.connect(self.generate_catalog) - self.action_convert.setMenu(cm) - self.action_convert.triggered.connect(self.convert_ebook) - self.convert_menu = cm pm = QMenu() pm.addAction(QIcon(I('config.svg')), _('Preferences'), self.do_config) diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index 63b1e72de4..79d16eeb5a 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -150,7 +150,6 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ self.get_metadata = GetMetadata() self.upload_memory = {} self.delete_memory = {} - self.conversion_jobs = {} self.persistent_files = [] self.metadata_dialogs = [] self.default_thumbnail = None From e09ecee42108652b745326dac30ce07a1d33c579 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 12 Aug 2010 18:07:45 -0600 Subject: [PATCH 06/28] Automatic fixes --- src/calibre/gui2/actions/delete.py | 34 ++++++++--------- src/calibre/gui2/actions/edit_metadata.py | 46 +++++++++++------------ src/calibre/gui2/actions/fetch_news.py | 4 +- src/calibre/gui2/actions/save_to_disk.py | 10 ++--- src/calibre/gui2/actions/view.py | 26 ++++++------- 5 files changed, 60 insertions(+), 60 deletions(-) diff --git a/src/calibre/gui2/actions/delete.py b/src/calibre/gui2/actions/delete.py index e5c6000863..de3c4d8868 100644 --- a/src/calibre/gui2/actions/delete.py +++ b/src/calibre/gui2/actions/delete.py @@ -13,19 +13,19 @@ class DeleteAction(object): def _get_selected_formats(self, msg): from calibre.gui2.dialogs.select_formats import SelectFormats - fmts = self.library_view.model().db.all_formats() + fmts = self.gui.library_view.model().db.all_formats() d = SelectFormats([x.lower() for x in fmts], msg, parent=self) if d.exec_() != d.Accepted: return None return d.selected_formats def _get_selected_ids(self, err_title=_('Cannot delete')): - rows = self.library_view.selectionModel().selectedRows() + rows = self.gui.library_view.selectionModel().selectedRows() if not rows or len(rows) == 0: d = error_dialog(self, err_title, _('No book selected')) d.exec_() return set([]) - return set(map(self.library_view.model().id, rows)) + return set(map(self.gui.library_view.model().id, rows)) def delete_selected_formats(self, *args): ids = self._get_selected_ids() @@ -37,11 +37,11 @@ class DeleteAction(object): return for id in ids: for fmt in fmts: - self.library_view.model().db.remove_format(id, fmt, + self.gui.library_view.model().db.remove_format(id, fmt, index_is_id=True, notify=False) - self.library_view.model().refresh_ids(ids) - self.library_view.model().current_changed(self.library_view.currentIndex(), - self.library_view.currentIndex()) + self.gui.library_view.model().refresh_ids(ids) + self.gui.library_view.model().current_changed(self.gui.library_view.currentIndex(), + self.gui.library_view.currentIndex()) if ids: self.tags_view.recount() @@ -54,17 +54,17 @@ class DeleteAction(object): if fmts is None: return for id in ids: - bfmts = self.library_view.model().db.formats(id, index_is_id=True) + bfmts = self.gui.library_view.model().db.formats(id, index_is_id=True) if bfmts is None: continue bfmts = set([x.lower() for x in bfmts.split(',')]) rfmts = bfmts - set(fmts) for fmt in rfmts: - self.library_view.model().db.remove_format(id, fmt, + self.gui.library_view.model().db.remove_format(id, fmt, index_is_id=True, notify=False) - self.library_view.model().refresh_ids(ids) - self.library_view.model().current_changed(self.library_view.currentIndex(), - self.library_view.currentIndex()) + self.gui.library_view.model().refresh_ids(ids) + self.gui.library_view.model().current_changed(self.gui.library_view.currentIndex(), + self.gui.library_view.currentIndex()) if ids: self.tags_view.recount() @@ -113,16 +113,16 @@ class DeleteAction(object): if not ids: return for id in ids: - self.library_view.model().db.remove_cover(id) - self.library_view.model().refresh_ids(ids) - self.library_view.model().current_changed(self.library_view.currentIndex(), - self.library_view.currentIndex()) + self.gui.library_view.model().db.remove_cover(id) + self.gui.library_view.model().refresh_ids(ids) + self.gui.library_view.model().current_changed(self.gui.library_view.currentIndex(), + self.gui.library_view.currentIndex()) def delete_books(self, *args): ''' Delete selected books from device or library. ''' - view = self.current_view() + view = self.gui.current_view() rows = view.selectionModel().selectedRows() if not rows or len(rows) == 0: return diff --git a/src/calibre/gui2/actions/edit_metadata.py b/src/calibre/gui2/actions/edit_metadata.py index b4f299f54c..ad77a4e197 100644 --- a/src/calibre/gui2/actions/edit_metadata.py +++ b/src/calibre/gui2/actions/edit_metadata.py @@ -19,13 +19,13 @@ class EditMetadataAction(object): def download_metadata(self, checked, covers=True, set_metadata=True, set_social_metadata=None): - rows = self.library_view.selectionModel().selectedRows() + rows = self.gui.library_view.selectionModel().selectedRows() if not rows or len(rows) == 0: d = error_dialog(self, _('Cannot download metadata'), _('No books selected')) d.exec_() return - db = self.library_view.model().db + db = self.gui.library_view.model().db ids = [db.id(row.row()) for row in rows] self.do_download_metadata(ids, covers=covers, set_metadata=set_metadata, @@ -33,7 +33,7 @@ class EditMetadataAction(object): def do_download_metadata(self, ids, covers=True, set_metadata=True, set_social_metadata=None): - db = self.library_view.model().db + db = self.gui.library_view.model().db if set_social_metadata is None: get_social_metadata = config['get_social_metadata'] else: @@ -59,11 +59,11 @@ class EditMetadataAction(object): return self._book_metadata_download_check.stop() self.progress_indicator.stop() - cr = self.library_view.currentIndex().row() + cr = self.gui.library_view.currentIndex().row() x = self._download_book_metadata self._download_book_metadata = None if x.exception is None: - self.library_view.model().refresh_ids( + self.gui.library_view.model().refresh_ids( x.updated, cr) if self.cover_flow: self.cover_flow.dataChanged() @@ -83,8 +83,8 @@ class EditMetadataAction(object): ''' Edit metadata of selected books in library. ''' - rows = self.library_view.selectionModel().selectedRows() - previous = self.library_view.currentIndex() + rows = self.gui.library_view.selectionModel().selectedRows() + previous = self.gui.library_view.currentIndex() if not rows or len(rows) == 0: d = error_dialog(self, _('Cannot edit metadata'), _('No books selected')) @@ -95,12 +95,12 @@ class EditMetadataAction(object): return self.edit_bulk_metadata(checked) def accepted(id): - self.library_view.model().refresh_ids([id]) + self.gui.library_view.model().refresh_ids([id]) for row in rows: - self._metadata_view_id = self.library_view.model().db.id(row.row()) + self._metadata_view_id = self.gui.library_view.model().db.id(row.row()) d = MetadataSingleDialog(self, row.row(), - self.library_view.model().db, + self.gui.library_view.model().db, accepted_callback=accepted, cancel_all=rows.index(row) < len(rows)-1) d.view_format.connect(self.metadata_view_format) @@ -108,8 +108,8 @@ class EditMetadataAction(object): if d.cancel_all: break if rows: - current = self.library_view.currentIndex() - m = self.library_view.model() + current = self.gui.library_view.currentIndex() + m = self.gui.library_view.model() if self.cover_flow: self.cover_flow.dataChanged() m.current_changed(current, previous) @@ -120,16 +120,16 @@ class EditMetadataAction(object): Edit metadata of selected books in library in bulk. ''' rows = [r.row() for r in \ - self.library_view.selectionModel().selectedRows()] + self.gui.library_view.selectionModel().selectedRows()] if not rows or len(rows) == 0: d = error_dialog(self, _('Cannot edit metadata'), _('No books selected')) d.exec_() return if MetadataBulkDialog(self, rows, - self.library_view.model().db).changed: - self.library_view.model().resort(reset=False) - self.library_view.model().research() + self.gui.library_view.model().db).changed: + self.gui.library_view.model().resort(reset=False) + self.gui.library_view.model().research() self.tags_view.recount() if self.cover_flow: self.cover_flow.dataChanged() @@ -141,7 +141,7 @@ class EditMetadataAction(object): ''' if self.stack.currentIndex() != 0: return - rows = self.library_view.selectionModel().selectedRows() + rows = self.gui.library_view.selectionModel().selectedRows() if not rows or len(rows) == 0: return error_dialog(self, _('Cannot merge books'), _('No books selected'), show=True) @@ -186,22 +186,22 @@ class EditMetadataAction(object): for row in rows: if row.row() < rows[0].row(): dest_row -= 1 - ci = self.library_view.model().index(dest_row, 0) + ci = self.gui.library_view.model().index(dest_row, 0) if ci.isValid(): - self.library_view.setCurrentIndex(ci) + self.gui.library_view.setCurrentIndex(ci) def add_formats(self, dest_id, src_books, replace=False): for src_book in src_books: if src_book: fmt = os.path.splitext(src_book)[-1].replace('.', '').upper() with open(src_book, 'rb') as f: - self.library_view.model().db.add_format(dest_id, fmt, f, index_is_id=True, + self.gui.library_view.model().db.add_format(dest_id, fmt, f, index_is_id=True, notify=False, replace=replace) def books_to_merge(self, rows): src_books = [] src_ids = [] - m = self.library_view.model() + m = self.gui.library_view.model() for i, row in enumerate(rows): id_ = m.id(row) if i == 0: @@ -216,10 +216,10 @@ class EditMetadataAction(object): return [dest_id, src_books, src_ids] def delete_books_after_merge(self, ids_to_delete): - self.library_view.model().delete_books_by_id(ids_to_delete) + self.gui.library_view.model().delete_books_by_id(ids_to_delete) def merge_metadata(self, dest_id, src_ids): - db = self.library_view.model().db + db = self.gui.library_view.model().db dest_mi = db.get_metadata(dest_id, index_is_id=True, get_cover=True) orig_dest_comments = dest_mi.comments for src_id in src_ids: diff --git a/src/calibre/gui2/actions/fetch_news.py b/src/calibre/gui2/actions/fetch_news.py index 72c93937dc..7e318fc2f1 100644 --- a/src/calibre/gui2/actions/fetch_news.py +++ b/src/calibre/gui2/actions/fetch_news.py @@ -29,8 +29,8 @@ class FetchNewsAction(object): if job.failed: self.scheduler.recipe_download_failed(arg) return self.job_exception(job) - id = self.library_view.model().add_news(pt.name, arg) - self.library_view.model().reset() + id = self.gui.library_view.model().add_news(pt.name, arg) + self.gui.library_view.model().reset() sync = dynamic.get('news_to_be_synced', set([])) sync.add(id) dynamic.set('news_to_be_synced', sync) diff --git a/src/calibre/gui2/actions/save_to_disk.py b/src/calibre/gui2/actions/save_to_disk.py index fb1ca58a3c..5ce6addb1c 100644 --- a/src/calibre/gui2/actions/save_to_disk.py +++ b/src/calibre/gui2/actions/save_to_disk.py @@ -28,7 +28,7 @@ class SaveToDiskAction(object): single_format=prefs['output_format']) def save_to_disk(self, checked, single_dir=False, single_format=None): - rows = self.current_view().selectionModel().selectedRows() + rows = self.gui.current_view().selectionModel().selectedRows() if not rows or len(rows) == 0: return error_dialog(self, _('Cannot save to disk'), _('No books selected'), show=True) @@ -37,7 +37,7 @@ class SaveToDiskAction(object): if not path: return dpath = os.path.abspath(path).replace('/', os.sep) - lpath = self.library_view.model().db.library_path.replace('/', os.sep) + lpath = self.gui.library_view.model().db.library_path.replace('/', os.sep) if dpath.startswith(lpath): return error_dialog(self, _('Not allowed'), _('You are trying to save files into the calibre ' @@ -45,7 +45,7 @@ class SaveToDiskAction(object): 'library. Save to disk is meant to export ' 'files from your calibre library elsewhere.'), show=True) - if self.current_view() is self.library_view: + if self.gui.current_view() is self.gui.library_view: from calibre.gui2.add import Saver from calibre.library.save_to_disk import config opts = config().parse() @@ -61,12 +61,12 @@ class SaveToDiskAction(object): opts.template = opts.template.split('/')[-1].strip() if not opts.template: opts.template = '{title} - {authors}' - self._saver = Saver(self, self.library_view.model().db, + self._saver = Saver(self, self.gui.library_view.model().db, Dispatcher(self._books_saved), rows, path, opts, spare_server=self.spare_server) else: - paths = self.current_view().model().paths(rows) + paths = self.gui.current_view().model().paths(rows) self.device_manager.save_books( Dispatcher(self.books_saved), paths, path) diff --git a/src/calibre/gui2/actions/view.py b/src/calibre/gui2/actions/view.py index 3ca7a807d7..56eccf64b7 100644 --- a/src/calibre/gui2/actions/view.py +++ b/src/calibre/gui2/actions/view.py @@ -19,18 +19,18 @@ from calibre.ptempfile import PersistentTemporaryFile class ViewAction(object): def view_format(self, row, format): - fmt_path = self.library_view.model().db.format_abspath(row, format) + fmt_path = self.gui.library_view.model().db.format_abspath(row, format) if fmt_path: self._view_file(fmt_path) def view_format_by_id(self, id_, format): - fmt_path = self.library_view.model().db.format_abspath(id_, format, + fmt_path = self.gui.library_view.model().db.format_abspath(id_, format, index_is_id=True) if fmt_path: self._view_file(fmt_path) def metadata_view_format(self, fmt): - fmt_path = self.library_view.model().db.\ + fmt_path = self.gui.library_view.model().db.\ format_abspath(self._metadata_view_id, fmt, index_is_id=True) if fmt_path: @@ -67,14 +67,14 @@ class ViewAction(object): self._launch_viewer(name, viewer, internal) def view_specific_format(self, triggered): - rows = self.library_view.selectionModel().selectedRows() + rows = self.gui.library_view.selectionModel().selectedRows() if not rows or len(rows) == 0: d = error_dialog(self, _('Cannot view'), _('No book selected')) d.exec_() return row = rows[0].row() - formats = self.library_view.model().db.formats(row).upper().split(',') + formats = self.gui.library_view.model().db.formats(row).upper().split(',') d = ChooseFormatDialog(self, _('Choose the format to view'), formats) if d.exec_() == d.Accepted: format = d.format() @@ -91,7 +91,7 @@ class ViewAction(object): ) % num) def view_folder(self, *args): - rows = self.current_view().selectionModel().selectedRows() + rows = self.gui.current_view().selectionModel().selectedRows() if not rows or len(rows) == 0: d = error_dialog(self, _('Cannot open folder'), _('No book selected')) @@ -100,15 +100,15 @@ class ViewAction(object): if not self._view_check(len(rows)): return for row in rows: - path = self.library_view.model().db.abspath(row.row()) + path = self.gui.library_view.model().db.abspath(row.row()) open_local_file(path) def view_folder_for_id(self, id_): - path = self.library_view.model().db.abspath(id_, index_is_id=True) + path = self.gui.library_view.model().db.abspath(id_, index_is_id=True) open_local_file(path) def view_book(self, triggered): - rows = self.current_view().selectionModel().selectedRows() + rows = self.gui.current_view().selectionModel().selectedRows() self._view_books(rows) def view_specific_book(self, index): @@ -122,13 +122,13 @@ class ViewAction(object): if not self._view_check(len(rows)): return - if self.current_view() is self.library_view: + if self.gui.current_view() is self.gui.library_view: for row in rows: if hasattr(row, 'row'): row = row.row() - formats = self.library_view.model().db.formats(row) - title = self.library_view.model().db.title(row) + formats = self.gui.library_view.model().db.formats(row) + title = self.gui.library_view.model().db.title(row) if not formats: error_dialog(self, _('Cannot view'), _('%s has no available formats.')%(title,), show=True) @@ -146,7 +146,7 @@ class ViewAction(object): if not in_prefs: self.view_format(row, formats[0]) else: - paths = self.current_view().model().paths(rows) + paths = self.gui.current_view().model().paths(rows) for path in paths: pt = PersistentTemporaryFile('_viewer_'+\ os.path.splitext(path)[1]) From 673dee204d0690e4b992b270752d9760b4cb6cc8 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 12 Aug 2010 18:22:01 -0600 Subject: [PATCH 07/28] More automatic migration --- src/calibre/gui2/actions/edit_metadata.py | 14 +++++++------- src/calibre/gui2/actions/fetch_news.py | 4 ++-- src/calibre/gui2/actions/save_to_disk.py | 8 ++++---- src/calibre/gui2/actions/view.py | 8 ++++---- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/calibre/gui2/actions/edit_metadata.py b/src/calibre/gui2/actions/edit_metadata.py index ad77a4e197..5c323e609d 100644 --- a/src/calibre/gui2/actions/edit_metadata.py +++ b/src/calibre/gui2/actions/edit_metadata.py @@ -21,7 +21,7 @@ class EditMetadataAction(object): set_social_metadata=None): rows = self.gui.library_view.selectionModel().selectedRows() if not rows or len(rows) == 0: - d = error_dialog(self, _('Cannot download metadata'), + d = error_dialog(self.gui, _('Cannot download metadata'), _('No books selected')) d.exec_() return @@ -71,12 +71,12 @@ class EditMetadataAction(object): details = ['%s: %s'%(title, reason) for title, reason in x.failures.values()] details = '%s\n'%('\n'.join(details)) - warning_dialog(self, _('Failed to download some metadata'), + warning_dialog(self.gui, _('Failed to download some metadata'), _('Failed to download metadata for the following:'), det_msg=details).exec_() else: err = _('Failed to download metadata:') - error_dialog(self, _('Error'), err, det_msg=x.tb).exec_() + error_dialog(self.gui, _('Error'), err, det_msg=x.tb).exec_() def edit_metadata(self, checked, bulk=None): @@ -86,7 +86,7 @@ class EditMetadataAction(object): rows = self.gui.library_view.selectionModel().selectedRows() previous = self.gui.library_view.currentIndex() if not rows or len(rows) == 0: - d = error_dialog(self, _('Cannot edit metadata'), + d = error_dialog(self.gui, _('Cannot edit metadata'), _('No books selected')) d.exec_() return @@ -122,7 +122,7 @@ class EditMetadataAction(object): rows = [r.row() for r in \ self.gui.library_view.selectionModel().selectedRows()] if not rows or len(rows) == 0: - d = error_dialog(self, _('Cannot edit metadata'), + d = error_dialog(self.gui, _('Cannot edit metadata'), _('No books selected')) d.exec_() return @@ -143,10 +143,10 @@ class EditMetadataAction(object): return rows = self.gui.library_view.selectionModel().selectedRows() if not rows or len(rows) == 0: - return error_dialog(self, _('Cannot merge books'), + return error_dialog(self.gui, _('Cannot merge books'), _('No books selected'), show=True) if len(rows) < 2: - return error_dialog(self, _('Cannot merge books'), + return error_dialog(self.gui, _('Cannot merge books'), _('At least two books must be selected for merging'), show=True) dest_id, src_books, src_ids = self.books_to_merge(rows) diff --git a/src/calibre/gui2/actions/fetch_news.py b/src/calibre/gui2/actions/fetch_news.py index 7e318fc2f1..361e3d63bd 100644 --- a/src/calibre/gui2/actions/fetch_news.py +++ b/src/calibre/gui2/actions/fetch_news.py @@ -21,7 +21,7 @@ class FetchNewsAction(object): Dispatcher(self.scheduled_recipe_fetched), func, args=args, description=desc) self.conversion_jobs[job] = (temp_files, fmt, arg) - self.status_bar.show_message(_('Fetching news from ')+arg['title'], 2000) + self.gui.status_bar.show_message(_('Fetching news from ')+arg['title'], 2000) def scheduled_recipe_fetched(self, job): temp_files, fmt, arg = self.conversion_jobs.pop(job) @@ -35,7 +35,7 @@ class FetchNewsAction(object): sync.add(id) dynamic.set('news_to_be_synced', sync) self.scheduler.recipe_downloaded(arg) - self.status_bar.show_message(arg['title'] + _(' fetched.'), 3000) + self.gui.status_bar.show_message(arg['title'] + _(' fetched.'), 3000) self.email_news(id) self.sync_news() diff --git a/src/calibre/gui2/actions/save_to_disk.py b/src/calibre/gui2/actions/save_to_disk.py index 5ce6addb1c..39df0948d2 100644 --- a/src/calibre/gui2/actions/save_to_disk.py +++ b/src/calibre/gui2/actions/save_to_disk.py @@ -30,7 +30,7 @@ class SaveToDiskAction(object): def save_to_disk(self, checked, single_dir=False, single_format=None): rows = self.gui.current_view().selectionModel().selectedRows() if not rows or len(rows) == 0: - return error_dialog(self, _('Cannot save to disk'), + return error_dialog(self.gui, _('Cannot save to disk'), _('No books selected'), show=True) path = choose_dir(self, 'save to disk dialog', _('Choose destination directory')) @@ -39,7 +39,7 @@ class SaveToDiskAction(object): dpath = os.path.abspath(path).replace('/', os.sep) lpath = self.gui.library_view.model().db.library_path.replace('/', os.sep) if dpath.startswith(lpath): - return error_dialog(self, _('Not allowed'), + return error_dialog(self.gui, _('Not allowed'), _('You are trying to save files into the calibre ' 'library. This can cause corruption of your ' 'library. Save to disk is meant to export ' @@ -74,7 +74,7 @@ class SaveToDiskAction(object): def _books_saved(self, path, failures, error): self._saver = None if error: - return error_dialog(self, _('Error while saving'), + return error_dialog(self.gui, _('Error while saving'), _('There was an error while saving.'), error, show=True) if failures: @@ -82,7 +82,7 @@ class SaveToDiskAction(object): (title, '\n\t'.join(err.splitlines())) for title, err in failures] - warning_dialog(self, _('Could not save some books'), + warning_dialog(self.gui, _('Could not save some books'), _('Could not save some books') + ', ' + _('Click the show details button to see which ones.'), u'\n\n'.join(failures), show=True) diff --git a/src/calibre/gui2/actions/view.py b/src/calibre/gui2/actions/view.py index 56eccf64b7..bf445b40b2 100644 --- a/src/calibre/gui2/actions/view.py +++ b/src/calibre/gui2/actions/view.py @@ -69,7 +69,7 @@ class ViewAction(object): def view_specific_format(self, triggered): rows = self.gui.library_view.selectionModel().selectedRows() if not rows or len(rows) == 0: - d = error_dialog(self, _('Cannot view'), _('No book selected')) + d = error_dialog(self.gui, _('Cannot view'), _('No book selected')) d.exec_() return @@ -83,7 +83,7 @@ class ViewAction(object): def _view_check(self, num, max_=3): if num <= max_: return True - return question_dialog(self, _('Multiple Books Selected'), + return question_dialog(self.gui, _('Multiple Books Selected'), _('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 ' @@ -93,7 +93,7 @@ class ViewAction(object): def view_folder(self, *args): rows = self.gui.current_view().selectionModel().selectedRows() if not rows or len(rows) == 0: - d = error_dialog(self, _('Cannot open folder'), + d = error_dialog(self.gui, _('Cannot open folder'), _('No book selected')) d.exec_() return @@ -130,7 +130,7 @@ class ViewAction(object): formats = self.gui.library_view.model().db.formats(row) title = self.gui.library_view.model().db.title(row) if not formats: - error_dialog(self, _('Cannot view'), + error_dialog(self.gui, _('Cannot view'), _('%s has no available formats.')%(title,), show=True) continue From 020286b746241b54a09f9078203b6bab2560d30e Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 12 Aug 2010 18:50:57 -0600 Subject: [PATCH 08/28] Migrate delete action and location_selected code --- src/calibre/customize/builtins.py | 6 +- src/calibre/gui2/actions/__init__.py | 3 + src/calibre/gui2/actions/convert.py | 3 + src/calibre/gui2/actions/delete.py | 80 ++++++++++++++++------- src/calibre/gui2/actions/edit_metadata.py | 4 ++ src/calibre/gui2/actions/fetch_news.py | 4 ++ src/calibre/gui2/actions/view.py | 5 ++ src/calibre/gui2/device.py | 5 +- src/calibre/gui2/layout.py | 16 ----- src/calibre/gui2/ui.py | 13 +--- 10 files changed, 84 insertions(+), 55 deletions(-) diff --git a/src/calibre/customize/builtins.py b/src/calibre/customize/builtins.py index 8462ae5d38..8232a163e7 100644 --- a/src/calibre/customize/builtins.py +++ b/src/calibre/customize/builtins.py @@ -593,5 +593,9 @@ class ActionConvert(InterfaceActionBase): name = 'Convert Books' actual_plugin = 'calibre.gui2.actions.convert:ConvertAction' +class ActionDelete(InterfaceActionBase): + name = 'Remove Books' + actual_plugin = 'calibre.gui2.actions.delete:DeleteAction' + plugins += [ActionAdd, ActionFetchAnnotations, ActionGenerateCatalog, - ActionConvert] + ActionConvert, ActionDelete] diff --git a/src/calibre/gui2/actions/__init__.py b/src/calibre/gui2/actions/__init__.py index 65d0078c50..b198a69214 100644 --- a/src/calibre/gui2/actions/__init__.py +++ b/src/calibre/gui2/actions/__init__.py @@ -52,3 +52,6 @@ class InterfaceAction(QObject): def genesis(self): pass + def location_selected(self, loc): + pass + diff --git a/src/calibre/gui2/actions/convert.py b/src/calibre/gui2/actions/convert.py index ace877b315..0641cc6a97 100644 --- a/src/calibre/gui2/actions/convert.py +++ b/src/calibre/gui2/actions/convert.py @@ -35,6 +35,9 @@ class ConvertAction(InterfaceAction): self.convert_menu = cm self.conversion_jobs = {} + def location_selected(self, loc): + enabled = loc == 'library' + self.qaction.setEnabled(enabled) def auto_convert(self, book_ids, on_card, format): previous = self.gui.library_view.currentIndex() diff --git a/src/calibre/gui2/actions/delete.py b/src/calibre/gui2/actions/delete.py index de3c4d8868..e0f3ae4d65 100644 --- a/src/calibre/gui2/actions/delete.py +++ b/src/calibre/gui2/actions/delete.py @@ -5,16 +5,46 @@ __license__ = 'GPL v3' __copyright__ = '2010, Kovid Goyal ' __docformat__ = 'restructuredtext en' +from PyQt4.Qt import QMenu + from calibre.gui2 import error_dialog from calibre.gui2.dialogs.delete_matching_from_device import DeleteMatchingFromDeviceDialog from calibre.gui2.dialogs.confirm_delete import confirm +from calibre.gui2.actions import InterfaceAction -class DeleteAction(object): +class DeleteAction(InterfaceAction): + + name = 'Remove Books' + action_spec = (_('Remove books'), 'trash.svg', None, _('Del')) + + def genesis(self): + self.qaction.triggered.connect(self.delete_books) + self.delete_menu = QMenu() + self.delete_menu.addAction(_('Remove selected books'), self.delete_books) + self.delete_menu.addAction( + _('Remove files of a specific format from selected books..'), + self.delete_selected_formats) + self.delete_menu.addAction( + _('Remove all formats from selected books, except...'), + self.delete_all_but_selected_formats) + self.delete_menu.addAction( + _('Remove covers from selected books'), self.delete_covers) + self.delete_menu.addSeparator() + self.delete_menu.addAction( + _('Remove matching books from device'), + self.remove_matching_books_from_device) + self.qaction.setMenu(self.delete_menu) + self.delete_memory = {} + + def location_selected(self, loc): + enabled = loc == 'library' + for action in list(self.delete_menu.actions())[1:]: + action.setEnabled(enabled) def _get_selected_formats(self, msg): from calibre.gui2.dialogs.select_formats import SelectFormats fmts = self.gui.library_view.model().db.all_formats() - d = SelectFormats([x.lower() for x in fmts], msg, parent=self) + d = SelectFormats([x.lower() for x in fmts], msg, parent=self.gui) if d.exec_() != d.Accepted: return None return d.selected_formats @@ -22,7 +52,7 @@ class DeleteAction(object): def _get_selected_ids(self, err_title=_('Cannot delete')): rows = self.gui.library_view.selectionModel().selectedRows() if not rows or len(rows) == 0: - d = error_dialog(self, err_title, _('No book selected')) + d = error_dialog(self.gui, err_title, _('No book selected')) d.exec_() return set([]) return set(map(self.gui.library_view.model().id, rows)) @@ -43,7 +73,7 @@ class DeleteAction(object): self.gui.library_view.model().current_changed(self.gui.library_view.currentIndex(), self.gui.library_view.currentIndex()) if ids: - self.tags_view.recount() + self.gui.tags_view.recount() def delete_all_but_selected_formats(self, *args): ids = self._get_selected_ids() @@ -66,11 +96,11 @@ class DeleteAction(object): self.gui.library_view.model().current_changed(self.gui.library_view.currentIndex(), self.gui.library_view.currentIndex()) if ids: - self.tags_view.recount() + self.gui.tags_view.recount() def remove_matching_books_from_device(self, *args): - if not self.device_manager.is_device_connected: - d = error_dialog(self, _('Cannot delete books'), + if not self.gui.device_manager.is_device_connected: + d = error_dialog(self.gui, _('Cannot delete books'), _('No device is connected')) d.exec_() return @@ -81,18 +111,18 @@ class DeleteAction(object): return to_delete = {} some_to_delete = False - for model,name in ((self.memory_view.model(), _('Main memory')), - (self.card_a_view.model(), _('Storage Card A')), - (self.card_b_view.model(), _('Storage Card B'))): + for model,name in ((self.gui.memory_view.model(), _('Main memory')), + (self.gui.card_a_view.model(), _('Storage Card A')), + (self.gui.card_b_view.model(), _('Storage Card B'))): to_delete[name] = (model, model.paths_for_db_ids(ids)) if len(to_delete[name][1]) > 0: some_to_delete = True if not some_to_delete: - d = error_dialog(self, _('No books to delete'), + d = error_dialog(self.gui, _('No books to delete'), _('None of the selected books are on the device')) d.exec_() return - d = DeleteMatchingFromDeviceDialog(self, to_delete) + d = DeleteMatchingFromDeviceDialog(self.gui, to_delete) if d.exec_(): paths = {} ids = {} @@ -103,10 +133,10 @@ class DeleteAction(object): paths[model].append(path) ids[model].append(id) for model in paths: - job = self.remove_paths(paths[model]) + job = self.gui.remove_paths(paths[model]) self.delete_memory[job] = (paths[model], model) model.mark_for_deletion(job, ids[model], rows_are_ids=True) - self.status_bar.show_message(_('Deleting books from device.'), 1000) + self.gui.status_bar.show_message(_('Deleting books from device.'), 1000) def delete_covers(self, *args): ids = self._get_selected_ids() @@ -126,18 +156,18 @@ class DeleteAction(object): rows = view.selectionModel().selectedRows() if not rows or len(rows) == 0: return - if self.stack.currentIndex() == 0: + if self.gui.stack.currentIndex() == 0: if not confirm('

'+_('The selected books will be ' 'permanently deleted and the files ' 'removed from your computer. Are you sure?') - +'

', 'library_delete_books', self): + +'

', 'library_delete_books', self.gui): return ci = view.currentIndex() row = None if ci.isValid(): row = ci.row() ids_deleted = view.model().delete_books(rows) - for v in (self.memory_view, self.card_a_view, self.card_b_view): + for v in (self.gui.memory_view, self.gui.card_a_view, self.gui.card_b_view): if v is None: continue v.model().clear_ondevice(ids_deleted) @@ -149,17 +179,17 @@ class DeleteAction(object): if not confirm('

'+_('The selected books will be ' 'permanently deleted ' 'from your device. Are you sure?') - +'

', 'device_delete_books', self): + +'

', 'device_delete_books', self.gui): return - if self.stack.currentIndex() == 1: - view = self.memory_view - elif self.stack.currentIndex() == 2: - view = self.card_a_view + if self.gui.stack.currentIndex() == 1: + view = self.gui.memory_view + elif self.gui.stack.currentIndex() == 2: + view = self.gui.card_a_view else: - view = self.card_b_view + view = self.gui.card_b_view paths = view.model().paths(rows) - job = self.remove_paths(paths) + job = self.gui.remove_paths(paths) self.delete_memory[job] = (paths, view.model()) view.model().mark_for_deletion(job, rows) - self.status_bar.show_message(_('Deleting books from device.'), 1000) + self.gui.status_bar.show_message(_('Deleting books from device.'), 1000) diff --git a/src/calibre/gui2/actions/edit_metadata.py b/src/calibre/gui2/actions/edit_metadata.py index 5c323e609d..e4b2145da0 100644 --- a/src/calibre/gui2/actions/edit_metadata.py +++ b/src/calibre/gui2/actions/edit_metadata.py @@ -17,6 +17,10 @@ from calibre.gui2.dialogs.tag_list_editor import TagListEditor class EditMetadataAction(object): + def location_selected(self, loc): + enabled = loc == 'library' + self.qaction.setEnabled(enabled) + def download_metadata(self, checked, covers=True, set_metadata=True, set_social_metadata=None): rows = self.gui.library_view.selectionModel().selectedRows() diff --git a/src/calibre/gui2/actions/fetch_news.py b/src/calibre/gui2/actions/fetch_news.py index 361e3d63bd..d161877cea 100644 --- a/src/calibre/gui2/actions/fetch_news.py +++ b/src/calibre/gui2/actions/fetch_news.py @@ -11,6 +11,10 @@ from calibre.utils.config import dynamic class FetchNewsAction(object): + def location_selected(self, loc): + enabled = loc == 'library' + self.qaction.setEnabled(enabled) + def genesis(self): self.conversion_jobs = {} diff --git a/src/calibre/gui2/actions/view.py b/src/calibre/gui2/actions/view.py index bf445b40b2..bdad55d142 100644 --- a/src/calibre/gui2/actions/view.py +++ b/src/calibre/gui2/actions/view.py @@ -18,6 +18,11 @@ from calibre.ptempfile import PersistentTemporaryFile class ViewAction(object): + def location_selected(self, loc): + enabled = loc == 'library' + for action in list(self.view_menu.actions())[1:]: + action.setEnabled(enabled) + def view_format(self, row, format): fmt_path = self.gui.library_view.model().db.format_abspath(row, format) if fmt_path: diff --git a/src/calibre/gui2/device.py b/src/calibre/gui2/device.py index 6cc8e47aa5..1e716a85fe 100644 --- a/src/calibre/gui2/device.py +++ b/src/calibre/gui2/device.py @@ -792,8 +792,9 @@ class DeviceMixin(object): # {{{ self.device_job_exception(job) return - if self.delete_memory.has_key(job): - paths, model = self.delete_memory.pop(job) + dm = self.iactions['Remove Books'].delete_memory + if dm.has_key(job): + paths, model = dm.pop(job) self.device_manager.remove_books_from_metadata(paths, self.booklists()) model.paths_deleted(paths) diff --git a/src/calibre/gui2/layout.py b/src/calibre/gui2/layout.py index b0851c0b25..74da5f53d3 100644 --- a/src/calibre/gui2/layout.py +++ b/src/calibre/gui2/layout.py @@ -528,7 +528,6 @@ class MainWindowMixin(object): md.addSeparator() md.addAction(self.action_merge) - self.action_del.triggered.connect(self.delete_books) self.action_edit.triggered.connect(self.edit_metadata) self.action_merge.triggered.connect(self.merge_books) @@ -557,21 +556,6 @@ class MainWindowMixin(object): self.action_view.setMenu(self.view_menu) ac.triggered.connect(self.view_specific_format, type=Qt.QueuedConnection) - self.delete_menu = QMenu() - self.delete_menu.addAction(_('Remove selected books'), self.delete_books) - self.delete_menu.addAction( - _('Remove files of a specific format from selected books..'), - self.delete_selected_formats) - self.delete_menu.addAction( - _('Remove all formats from selected books, except...'), - self.delete_all_but_selected_formats) - self.delete_menu.addAction( - _('Remove covers from selected books'), self.delete_covers) - self.delete_menu.addSeparator() - self.delete_menu.addAction( - _('Remove matching books from device'), - self.remove_matching_books_from_device) - self.action_del.setMenu(self.delete_menu) self.action_open_containing_folder.setShortcut(Qt.Key_O) self.addAction(self.action_open_containing_folder) diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index 79d16eeb5a..df0c9091b5 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -149,7 +149,6 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ self.verbose = opts.verbose self.get_metadata = GetMetadata() self.upload_memory = {} - self.delete_memory = {} self.persistent_files = [] self.metadata_dialogs = [] self.default_thumbnail = None @@ -437,26 +436,18 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ for x in ('tb', 'cb'): splitter = getattr(self, x+'_splitter') splitter.button.setEnabled(location == 'library') + for action in self.iactions.values(): + action.location_selected(location) if location == 'library': - self.action_edit.setEnabled(True) self.action_merge.setEnabled(True) - self.action_convert.setEnabled(True) - self.view_menu.actions()[1].setEnabled(True) self.action_open_containing_folder.setEnabled(True) self.action_sync.setEnabled(True) self.search_restriction.setEnabled(True) - for action in list(self.delete_menu.actions())[1:]: - action.setEnabled(True) else: - self.action_edit.setEnabled(False) self.action_merge.setEnabled(False) - self.action_convert.setEnabled(False) - self.view_menu.actions()[1].setEnabled(False) self.action_open_containing_folder.setEnabled(False) self.action_sync.setEnabled(False) self.search_restriction.setEnabled(False) - for action in list(self.delete_menu.actions())[1:]: - action.setEnabled(False) # Reset the view in case something changed while it was invisible self.current_view().reset() self.set_number_of_books_shown() From e4b2729e78112945d4ebcdc08ad8080d86035a54 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 12 Aug 2010 19:39:49 -0600 Subject: [PATCH 09/28] Edit metadata migrated --- src/calibre/customize/builtins.py | 6 +- src/calibre/gui2/actions/__init__.py | 8 +- src/calibre/gui2/actions/add.py | 2 +- src/calibre/gui2/actions/edit_metadata.py | 90 +++++++++++++++++------ src/calibre/gui2/actions/view.py | 7 +- src/calibre/gui2/init.py | 7 +- src/calibre/gui2/layout.py | 39 ---------- src/calibre/gui2/ui.py | 2 - 8 files changed, 88 insertions(+), 73 deletions(-) diff --git a/src/calibre/customize/builtins.py b/src/calibre/customize/builtins.py index 8232a163e7..bdb76a6066 100644 --- a/src/calibre/customize/builtins.py +++ b/src/calibre/customize/builtins.py @@ -597,5 +597,9 @@ class ActionDelete(InterfaceActionBase): name = 'Remove Books' actual_plugin = 'calibre.gui2.actions.delete:DeleteAction' +class ActionEditMetadata(InterfaceActionBase): + name = 'Edit Metadata' + actual_plugin = 'calibre.gui2.actions.delete:EditMetadataAction' + plugins += [ActionAdd, ActionFetchAnnotations, ActionGenerateCatalog, - ActionConvert, ActionDelete] + ActionConvert, ActionDelete, ActionEditMetadata] diff --git a/src/calibre/gui2/actions/__init__.py b/src/calibre/gui2/actions/__init__.py index b198a69214..4798828074 100644 --- a/src/calibre/gui2/actions/__init__.py +++ b/src/calibre/gui2/actions/__init__.py @@ -34,8 +34,10 @@ class InterfaceAction(QObject): self.create_action() self.genesis() - def create_action(self): - text, icon, tooltip, shortcut = self.action_spec + def create_action(self, spec=None, attr='qaction'): + if spec is None: + spec = self.action_spec + text, icon, tooltip, shortcut = spec if icon is not None: action = QAction(QIcon(I(icon)), text, self.gui) else: @@ -47,7 +49,7 @@ class InterfaceAction(QObject): action.setAutoRepeat(False) if shortcut: action.setShortcut(shortcut) - self.qaction = action + setattr(self, attr, action) def genesis(self): pass diff --git a/src/calibre/gui2/actions/add.py b/src/calibre/gui2/actions/add.py index 668af0957e..9aa78298dc 100644 --- a/src/calibre/gui2/actions/add.py +++ b/src/calibre/gui2/actions/add.py @@ -90,7 +90,7 @@ class AddAction(InterfaceAction): mi.isbn = x ids.add(self.gui.library_view.model().db.import_book(mi, [])) self.gui.library_view.model().books_added(len(isbns)) - self.gui.do_download_metadata(ids) + self.gui.iactions['Edit Metadata'].do_download_metadata(ids) def files_dropped(self, paths): diff --git a/src/calibre/gui2/actions/edit_metadata.py b/src/calibre/gui2/actions/edit_metadata.py index e4b2145da0..05b4bdf7fc 100644 --- a/src/calibre/gui2/actions/edit_metadata.py +++ b/src/calibre/gui2/actions/edit_metadata.py @@ -6,20 +6,64 @@ __copyright__ = '2010, Kovid Goyal ' __docformat__ = 'restructuredtext en' import os +from functools import partial -from PyQt4.Qt import Qt, QTimer +from PyQt4.Qt import Qt, QTimer, QMenu from calibre.gui2 import error_dialog, config, warning_dialog from calibre.gui2.dialogs.metadata_single import MetadataSingleDialog from calibre.gui2.dialogs.metadata_bulk import MetadataBulkDialog from calibre.gui2.dialogs.confirm_delete import confirm from calibre.gui2.dialogs.tag_list_editor import TagListEditor +from calibre.gui2.actions import InterfaceAction -class EditMetadataAction(object): +class EditMetadataAction(InterfaceAction): + + name = 'Edit Metadata' + action_spec = (_('Edit metadata'), 'edit_input.svg', None, _('E')) + + def genesis(self): + self.create_action(spec=(_('Merge book records'), 'merge_books.svg', + None, _('M')), attr='action_merge') + md = QMenu() + md.addAction(_('Edit metadata individually'), + partial(self.edit_metadata, False, bulk=False)) + md.addSeparator() + md.addAction(_('Edit metadata in bulk'), + partial(self.edit_metadata, False, bulk=True)) + md.addSeparator() + md.addAction(_('Download metadata and covers'), + partial(self.download_metadata, False, covers=True), + Qt.ControlModifier+Qt.Key_D) + md.addAction(_('Download only metadata'), + partial(self.download_metadata, False, covers=False)) + md.addAction(_('Download only covers'), + partial(self.download_metadata, False, covers=True, + set_metadata=False, set_social_metadata=False)) + md.addAction(_('Download only social metadata'), + partial(self.download_metadata, False, covers=False, + set_metadata=False, set_social_metadata=True)) + self.metadata_menu = md + + mb = QMenu() + mb.addAction(_('Merge into first selected book - delete others'), + self.merge_books) + mb.addSeparator() + mb.addAction(_('Merge into first selected book - keep others'), + partial(self.merge_books, safe_merge=True)) + self.merge_menu = mb + self.action_merge.setMenu(mb) + md.addSeparator() + md.addAction(self.action_merge) + + self.qaction.triggered.connect(self.edit_metadata) + self.qaction.setMenu(md) + self.action_merge.triggered.connect(self.merge_books) def location_selected(self, loc): enabled = loc == 'library' self.qaction.setEnabled(enabled) + self.action_merge.setEnabled(enabled) def download_metadata(self, checked, covers=True, set_metadata=True, set_social_metadata=None): @@ -51,9 +95,9 @@ class EditMetadataAction(object): x = _('social metadata') else: x = _('covers') if covers and not set_metadata else _('metadata') - self.progress_indicator.start( + self.gui.progress_indicator.start( _('Downloading %s for %d book(s)')%(x, len(ids))) - self._book_metadata_download_check = QTimer(self) + self._book_metadata_download_check = QTimer(self.gui) self._book_metadata_download_check.timeout.connect(self.book_metadata_download_check, type=Qt.QueuedConnection) self._book_metadata_download_check.start(100) @@ -62,15 +106,15 @@ class EditMetadataAction(object): if self._download_book_metadata.is_alive(): return self._book_metadata_download_check.stop() - self.progress_indicator.stop() + self.gui.progress_indicator.stop() cr = self.gui.library_view.currentIndex().row() x = self._download_book_metadata self._download_book_metadata = None if x.exception is None: self.gui.library_view.model().refresh_ids( x.updated, cr) - if self.cover_flow: - self.cover_flow.dataChanged() + if self.gui.cover_flow: + self.gui.cover_flow.dataChanged() if x.failures: details = ['%s: %s'%(title, reason) for title, reason in x.failures.values()] @@ -102,22 +146,22 @@ class EditMetadataAction(object): self.gui.library_view.model().refresh_ids([id]) for row in rows: - self._metadata_view_id = self.gui.library_view.model().db.id(row.row()) - d = MetadataSingleDialog(self, row.row(), + self.gui.iactions['View'].metadata_view_id = self.gui.library_view.model().db.id(row.row()) + d = MetadataSingleDialog(self.gui, row.row(), self.gui.library_view.model().db, accepted_callback=accepted, cancel_all=rows.index(row) < len(rows)-1) - d.view_format.connect(self.metadata_view_format) + d.view_format.connect(self.gui.iactions['View'].metadata_view_format) d.exec_() if d.cancel_all: break if rows: current = self.gui.library_view.currentIndex() m = self.gui.library_view.model() - if self.cover_flow: - self.cover_flow.dataChanged() + if self.gui.cover_flow: + self.gui.cover_flow.dataChanged() m.current_changed(current, previous) - self.tags_view.recount() + self.gui.tags_view.recount() def edit_bulk_metadata(self, checked): ''' @@ -130,20 +174,20 @@ class EditMetadataAction(object): _('No books selected')) d.exec_() return - if MetadataBulkDialog(self, rows, + if MetadataBulkDialog(self.gui, rows, self.gui.library_view.model().db).changed: self.gui.library_view.model().resort(reset=False) self.gui.library_view.model().research() - self.tags_view.recount() - if self.cover_flow: - self.cover_flow.dataChanged() + self.gui.tags_view.recount() + if self.gui.cover_flow: + self.gui.cover_flow.dataChanged() # Merge books {{{ def merge_books(self, safe_merge=False): ''' Merge selected books in library. ''' - if self.stack.currentIndex() != 0: + if self.gui.stack.currentIndex() != 0: return rows = self.gui.library_view.selectionModel().selectedRows() if not rows or len(rows) == 0: @@ -161,7 +205,7 @@ class EditMetadataAction(object): 'The second and subsequently selected books will not ' 'be deleted or changed.

' 'Please confirm you want to proceed.') - +'

', 'merge_books_safe', self): + +'

', 'merge_books_safe', self.gui): return self.add_formats(dest_id, src_books) self.merge_metadata(dest_id, src_ids) @@ -175,12 +219,12 @@ class EditMetadataAction(object): '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?') - +'

', 'merge_books', self): + +'

', 'merge_books', self.gui): return if len(rows)>5: if not confirm('

'+_('You are about to merge more than 5 books. ' 'Are you sure you want to proceed?') - +'

', 'merge_too_many_books', self): + +'

', 'merge_too_many_books', self.gui): return self.add_formats(dest_id, src_books) self.merge_metadata(dest_id, src_ids) @@ -299,7 +343,7 @@ class EditMetadataAction(object): model = view.model() result = model.get_collections_with_ids() compare = (lambda x,y:cmp(x.lower(), y.lower())) - d = TagListEditor(self, tag_to_match=None, data=result, compare=compare) + d = TagListEditor(self.gui, tag_to_match=None, data=result, compare=compare) d.exec_() if d.result() == d.Accepted: to_rename = d.to_rename # dict of new text to old ids @@ -309,7 +353,7 @@ class EditMetadataAction(object): model.rename_collection(old_id, new_name=unicode(text)) for item in to_delete: model.delete_collection_using_id(item) - self.upload_collections(model.db, view=view, oncard=oncard) + self.gui.upload_collections(model.db, view=view, oncard=oncard) view.reset() diff --git a/src/calibre/gui2/actions/view.py b/src/calibre/gui2/actions/view.py index bdad55d142..4a6e545da6 100644 --- a/src/calibre/gui2/actions/view.py +++ b/src/calibre/gui2/actions/view.py @@ -18,6 +18,11 @@ from calibre.ptempfile import PersistentTemporaryFile class ViewAction(object): + name = 'View' + + def genesis(self): + self.metadata_view_id = None + def location_selected(self, loc): enabled = loc == 'library' for action in list(self.view_menu.actions())[1:]: @@ -36,7 +41,7 @@ class ViewAction(object): def metadata_view_format(self, fmt): fmt_path = self.gui.library_view.model().db.\ - format_abspath(self._metadata_view_id, + format_abspath(self.metadata_view_id, fmt, index_is_id=True) if fmt_path: self._view_file(fmt_path) diff --git a/src/calibre/gui2/init.py b/src/calibre/gui2/init.py index 7f8ad2d23c..359ea7465c 100644 --- a/src/calibre/gui2/init.py +++ b/src/calibre/gui2/init.py @@ -66,8 +66,9 @@ class LibraryViewMixin(object): # {{{ add_to_library = (_('Add books to library'), self.iactions['Add Books'].add_books_from_device) + edc = self.iactions['Edit Metadata'].edit_device_collections edit_device_collections = (_('Manage collections'), - partial(self.edit_device_collections, oncard=None)) + partial(edc, oncard=None)) self.memory_view.set_context_menu(None, None, None, self.action_view, self.action_save, None, None, self.action_del, None, @@ -75,7 +76,7 @@ class LibraryViewMixin(object): # {{{ edit_device_collections=edit_device_collections) edit_device_collections = (_('Manage collections'), - partial(self.edit_device_collections, oncard='carda')) + partial(edc, oncard='carda')) self.card_a_view.set_context_menu(None, None, None, self.action_view, self.action_save, None, None, self.action_del, None, @@ -83,7 +84,7 @@ class LibraryViewMixin(object): # {{{ edit_device_collections=edit_device_collections) edit_device_collections = (_('Manage collections'), - partial(self.edit_device_collections, oncard='cardb')) + partial(edc, oncard='cardb')) self.card_b_view.set_context_menu(None, None, None, self.action_view, self.action_save, None, None, self.action_del, None, diff --git a/src/calibre/gui2/layout.py b/src/calibre/gui2/layout.py index 74da5f53d3..582818a593 100644 --- a/src/calibre/gui2/layout.py +++ b/src/calibre/gui2/layout.py @@ -459,10 +459,6 @@ class MainWindowMixin(object): setattr(self, 'action_'+name, action) all_actions.append(action) - ac(0, 0, 0, 'add', _('Add books'), 'add_book.svg', _('A')) - ac(1, 1, 0, 'edit', _('Edit metadata'), 'edit_input.svg', _('E')) - ac(2, 2, 3, 'convert', _('Convert books'), 'convert.svg', _('C')) - ac(3, 3, 0, 'view', _('View'), 'view.svg', _('V')) ac(-1, 4, 0, 'sync', _('Send to device'), 'sync.svg') ac(5, 5, 3, 'choose_library', _('%d books')%0, 'lt.png', tooltip=_('Choose calibre library to work with')) @@ -473,7 +469,6 @@ class MainWindowMixin(object): ac(10, 10, 3, 'help', _('Help'), 'help.svg', _('F1'), _("Browse the calibre User Manual")) ac(11, 11, 0, 'preferences', _('Preferences'), 'config.svg', _('Ctrl+P')) - ac(-1, -1, 0, 'merge', _('Merge book records'), 'merge_books.svg', _('M')) ac(-1, -1, 0, 'open_containing_folder', _('Open containing folder'), 'document_open.svg') ac(-1, -1, 0, 'show_book_details', _('Show book details'), @@ -497,39 +492,6 @@ class MainWindowMixin(object): self.action_conn_share.setMenu(self.share_conn_menu) self.action_help.triggered.connect(self.show_help) - md = QMenu() - md.addAction(_('Edit metadata individually'), - partial(self.edit_metadata, False, bulk=False)) - md.addSeparator() - md.addAction(_('Edit metadata in bulk'), - partial(self.edit_metadata, False, bulk=True)) - md.addSeparator() - md.addAction(_('Download metadata and covers'), - partial(self.download_metadata, False, covers=True), - Qt.ControlModifier+Qt.Key_D) - md.addAction(_('Download only metadata'), - partial(self.download_metadata, False, covers=False)) - md.addAction(_('Download only covers'), - partial(self.download_metadata, False, covers=True, - set_metadata=False, set_social_metadata=False)) - md.addAction(_('Download only social metadata'), - partial(self.download_metadata, False, covers=False, - set_metadata=False, set_social_metadata=True)) - self.metadata_menu = md - - mb = QMenu() - mb.addAction(_('Merge into first selected book - delete others'), - self.merge_books) - mb.addSeparator() - mb.addAction(_('Merge into first selected book - keep others'), - partial(self.merge_books, safe_merge=True)) - self.merge_menu = mb - self.action_merge.setMenu(mb) - md.addSeparator() - md.addAction(self.action_merge) - - self.action_edit.triggered.connect(self.edit_metadata) - self.action_merge.triggered.connect(self.merge_books) self.action_save.triggered.connect(self.save_to_disk) self.save_menu = QMenu() @@ -566,7 +528,6 @@ class MainWindowMixin(object): self.action_sync.triggered.connect( self._sync_action_triggered) - self.action_edit.setMenu(md) self.action_save.setMenu(self.save_menu) diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index df0c9091b5..80165ec515 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -439,12 +439,10 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ for action in self.iactions.values(): action.location_selected(location) if location == 'library': - self.action_merge.setEnabled(True) self.action_open_containing_folder.setEnabled(True) self.action_sync.setEnabled(True) self.search_restriction.setEnabled(True) else: - self.action_merge.setEnabled(False) self.action_open_containing_folder.setEnabled(False) self.action_sync.setEnabled(False) self.search_restriction.setEnabled(False) From d9ac3a0e0ab574f8c73620b9c67f6cc349a686b4 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 12 Aug 2010 19:56:40 -0600 Subject: [PATCH 10/28] Migrate view action --- src/calibre/customize/builtins.py | 8 ++++++-- src/calibre/gui2/actions/view.py | 28 ++++++++++++++++++++-------- src/calibre/gui2/cover_flow.py | 2 +- src/calibre/gui2/init.py | 6 +++--- src/calibre/gui2/layout.py | 12 ++---------- src/calibre/gui2/ui.py | 1 - 6 files changed, 32 insertions(+), 25 deletions(-) diff --git a/src/calibre/customize/builtins.py b/src/calibre/customize/builtins.py index bdb76a6066..215a78e862 100644 --- a/src/calibre/customize/builtins.py +++ b/src/calibre/customize/builtins.py @@ -599,7 +599,11 @@ class ActionDelete(InterfaceActionBase): class ActionEditMetadata(InterfaceActionBase): name = 'Edit Metadata' - actual_plugin = 'calibre.gui2.actions.delete:EditMetadataAction' + actual_plugin = 'calibre.gui2.actions.edit_metadata:EditMetadataAction' + +class ActionView(InterfaceActionBase): + name = 'View' + actual_plugin = 'calibre.gui2.actions.view:ViewAction' plugins += [ActionAdd, ActionFetchAnnotations, ActionGenerateCatalog, - ActionConvert, ActionDelete, ActionEditMetadata] + ActionConvert, ActionDelete, ActionEditMetadata, ActionView] diff --git a/src/calibre/gui2/actions/view.py b/src/calibre/gui2/actions/view.py index 4a6e545da6..22592be2fe 100644 --- a/src/calibre/gui2/actions/view.py +++ b/src/calibre/gui2/actions/view.py @@ -6,8 +6,9 @@ __copyright__ = '2010, Kovid Goyal ' __docformat__ = 'restructuredtext en' import os, time +from functools import partial -from PyQt4.Qt import Qt +from PyQt4.Qt import Qt, QMenu from calibre.constants import isosx from calibre.gui2 import error_dialog, Dispatcher, question_dialog, config, \ @@ -15,13 +16,24 @@ from calibre.gui2 import error_dialog, Dispatcher, question_dialog, config, \ from calibre.gui2.dialogs.choose_format import ChooseFormatDialog from calibre.utils.config import prefs from calibre.ptempfile import PersistentTemporaryFile +from calibre.gui2.actions import InterfaceAction -class ViewAction(object): +class ViewAction(InterfaceAction): name = 'View' + action_spec = (_('View'), 'view.svg', None, _('V')) def genesis(self): + self.persistent_files = [] self.metadata_view_id = None + self.qaction.triggered.connect(self.view_book) + self.view_menu = QMenu() + self.view_menu.addAction(_('View'), partial(self.view_book, False)) + ac = self.view_menu.addAction(_('View specific format')) + ac.setShortcut((Qt.ControlModifier if isosx else Qt.AltModifier)+Qt.Key_V) + self.qaction.setMenu(self.view_menu) + ac.triggered.connect(self.view_specific_format, type=Qt.QueuedConnection) + def location_selected(self, loc): enabled = loc == 'library' @@ -49,12 +61,12 @@ class ViewAction(object): def book_downloaded_for_viewing(self, job): if job.failed: - self.device_job_exception(job) + self.gui.device_job_exception(job) return self._view_file(job.result) def _launch_viewer(self, name=None, viewer='ebook-viewer', internal=True): - self.setCursor(Qt.BusyCursor) + self.gui.setCursor(Qt.BusyCursor) try: if internal: args = [viewer] @@ -62,13 +74,13 @@ class ViewAction(object): args.append('--raise-window') if name is not None: args.append(name) - self.job_manager.launch_gui_app(viewer, + self.gui.job_manager.launch_gui_app(viewer, kwargs=dict(args=args)) else: open_local_file(name) time.sleep(2) # User feedback finally: - self.unsetCursor() + self.gui.unsetCursor() def _view_file(self, name): ext = os.path.splitext(name)[1].upper().replace('.', '') @@ -85,7 +97,7 @@ class ViewAction(object): row = rows[0].row() formats = self.gui.library_view.model().db.formats(row).upper().split(',') - d = ChooseFormatDialog(self, _('Choose the format to view'), formats) + d = ChooseFormatDialog(self.gui, _('Choose the format to view'), formats) if d.exec_() == d.Accepted: format = d.format() self.view_format(row, format) @@ -162,7 +174,7 @@ class ViewAction(object): os.path.splitext(path)[1]) self.persistent_files.append(pt) pt.close() - self.device_manager.view_book(\ + self.gui.device_manager.view_book(\ Dispatcher(self.book_downloaded_for_viewing), path, pt.name) diff --git a/src/calibre/gui2/cover_flow.py b/src/calibre/gui2/cover_flow.py index c72f53201f..d3ca6bcd81 100644 --- a/src/calibre/gui2/cover_flow.py +++ b/src/calibre/gui2/cover_flow.py @@ -122,7 +122,7 @@ class CoverFlowMixin(object): self.sync_cf_to_listview) self.db_images = DatabaseImages(self.library_view.model()) self.cover_flow.setImages(self.db_images) - self.cover_flow.itemActivated.connect(self.view_specific_book) + self.cover_flow.itemActivated.connect(self.iactions['View'].view_specific_book) else: self.cover_flow = QLabel('

'+_('Cover browser could not be loaded') +'
'+pictureflowerror) diff --git a/src/calibre/gui2/init.py b/src/calibre/gui2/init.py index 359ea7465c..839bfd536c 100644 --- a/src/calibre/gui2/init.py +++ b/src/calibre/gui2/init.py @@ -118,7 +118,7 @@ class LibraryViewMixin(object): # {{{ for view in ('library', 'memory', 'card_a', 'card_b'): view = getattr(self, view+'_view') - view.verticalHeader().sectionDoubleClicked.connect(self.view_specific_book) + view.verticalHeader().sectionDoubleClicked.connect(self.iactions['View'].view_specific_book) @@ -308,8 +308,8 @@ class LayoutMixin(object): # {{{ self.status_bar.initialize(self.system_tray_icon) self.book_details.show_book_info.connect(self.show_book_info) self.book_details.files_dropped.connect(self.iactions['Add Books'].files_dropped_on_book) - self.book_details.open_containing_folder.connect(self.view_folder_for_id) - self.book_details.view_specific_format.connect(self.view_format_by_id) + self.book_details.open_containing_folder.connect(self.iactions['View'].view_folder_for_id) + self.book_details.view_specific_format.connect(self.iactions['View'].view_format_by_id) m = self.library_view.model() if m.rowCount(None) > 0: diff --git a/src/calibre/gui2/layout.py b/src/calibre/gui2/layout.py index 582818a593..f456201e39 100644 --- a/src/calibre/gui2/layout.py +++ b/src/calibre/gui2/layout.py @@ -13,7 +13,7 @@ from PyQt4.Qt import QIcon, Qt, QWidget, QAction, QToolBar, QSize, \ QObject, QVBoxLayout, QSizePolicy, QLabel, QHBoxLayout, QActionGroup, \ QMenu, QUrl -from calibre.constants import __appname__, isosx +from calibre.constants import __appname__ from calibre.gui2.search_box import SearchBox2, SavedSearchBox from calibre.gui2.throbber import ThrobbingButton from calibre.gui2 import config, open_url, gprefs @@ -510,18 +510,10 @@ class MainWindowMixin(object): self.save_menu.addMenu(self.save_sub_menu) self.save_sub_menu.save_fmt.connect(self.save_specific_format_disk) - self.action_view.triggered.connect(self.view_book) - self.view_menu = QMenu() - self.view_menu.addAction(_('View'), partial(self.view_book, False)) - ac = self.view_menu.addAction(_('View specific format')) - ac.setShortcut((Qt.ControlModifier if isosx else Qt.AltModifier)+Qt.Key_V) - self.action_view.setMenu(self.view_menu) - ac.triggered.connect(self.view_specific_format, type=Qt.QueuedConnection) - self.action_open_containing_folder.setShortcut(Qt.Key_O) self.addAction(self.action_open_containing_folder) - self.action_open_containing_folder.triggered.connect(self.view_folder) + self.action_open_containing_folder.triggered.connect(self.iactions['View'].view_folder) self.action_sync.setShortcut(Qt.Key_D) self.action_sync.setEnabled(True) self.create_device_menu() diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index 80165ec515..f3fa6f743e 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -149,7 +149,6 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ self.verbose = opts.verbose self.get_metadata = GetMetadata() self.upload_memory = {} - self.persistent_files = [] self.metadata_dialogs = [] self.default_thumbnail = None self.tb_wrapper = textwrap.TextWrapper(width=40) From 5c9ec13a295cbc76618cebbca332c5f84c40c168 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 12 Aug 2010 20:04:27 -0600 Subject: [PATCH 11/28] Migrated Fetch News --- src/calibre/customize/builtins.py | 7 ++++++- src/calibre/gui2/actions/fetch_news.py | 23 ++++++++++++++++------- src/calibre/gui2/layout.py | 7 ++----- src/calibre/gui2/ui.py | 1 + 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/calibre/customize/builtins.py b/src/calibre/customize/builtins.py index 215a78e862..d64f36adc9 100644 --- a/src/calibre/customize/builtins.py +++ b/src/calibre/customize/builtins.py @@ -605,5 +605,10 @@ class ActionView(InterfaceActionBase): name = 'View' actual_plugin = 'calibre.gui2.actions.view:ViewAction' +class ActionFetchNews(InterfaceActionBase): + name = 'Fetch News' + actual_plugin = 'calibre.gui2.actions.fetch_news:FetchNewsAction' + plugins += [ActionAdd, ActionFetchAnnotations, ActionGenerateCatalog, - ActionConvert, ActionDelete, ActionEditMetadata, ActionView] + ActionConvert, ActionDelete, ActionEditMetadata, ActionView, + ActionFetchNews] diff --git a/src/calibre/gui2/actions/fetch_news.py b/src/calibre/gui2/actions/fetch_news.py index d161877cea..a63ac6b4a3 100644 --- a/src/calibre/gui2/actions/fetch_news.py +++ b/src/calibre/gui2/actions/fetch_news.py @@ -8,8 +8,12 @@ __docformat__ = 'restructuredtext en' from calibre.gui2 import Dispatcher from calibre.gui2.tools import fetch_scheduled_recipe from calibre.utils.config import dynamic +from calibre.gui2.actions import InterfaceAction -class FetchNewsAction(object): +class FetchNewsAction(InterfaceAction): + + name = 'Fetch News' + action_spec = (_('Fetch news'), 'news.svg', None, _('F')) def location_selected(self, loc): enabled = loc == 'library' @@ -18,10 +22,15 @@ class FetchNewsAction(object): def genesis(self): self.conversion_jobs = {} + def connect_scheduler(self, scheduler): + self.qaction.setMenu(scheduler.news_menu) + self.qaction.triggered.connect( + scheduler.show_dialog) + def download_scheduled_recipe(self, arg): func, args, desc, fmt, temp_files = \ fetch_scheduled_recipe(arg) - job = self.job_manager.run_job( + job = self.gui.job_manager.run_job( Dispatcher(self.scheduled_recipe_fetched), func, args=args, description=desc) self.conversion_jobs[job] = (temp_files, fmt, arg) @@ -31,16 +40,16 @@ class FetchNewsAction(object): temp_files, fmt, arg = self.conversion_jobs.pop(job) pt = temp_files[0] if job.failed: - self.scheduler.recipe_download_failed(arg) - return self.job_exception(job) + self.gui.scheduler.recipe_download_failed(arg) + return self.gui.job_exception(job) id = self.gui.library_view.model().add_news(pt.name, arg) self.gui.library_view.model().reset() sync = dynamic.get('news_to_be_synced', set([])) sync.add(id) dynamic.set('news_to_be_synced', sync) - self.scheduler.recipe_downloaded(arg) + self.gui.scheduler.recipe_downloaded(arg) self.gui.status_bar.show_message(arg['title'] + _(' fetched.'), 3000) - self.email_news(id) - self.sync_news() + self.gui.email_news(id) + self.gui.sync_news() diff --git a/src/calibre/gui2/layout.py b/src/calibre/gui2/layout.py index f456201e39..c5ed84ff00 100644 --- a/src/calibre/gui2/layout.py +++ b/src/calibre/gui2/layout.py @@ -427,7 +427,8 @@ class MainWindowMixin(object): def init_scheduler(self, db): self.scheduler = Scheduler(self, db) self.scheduler.start_recipe_fetch.connect( - self.download_scheduled_recipe, type=Qt.QueuedConnection) + self.iactions['Fetch News'].download_scheduled_recipe, type=Qt.QueuedConnection) + self.iactions['Fetch News'].connect_scheduler(self.scheduler) def read_toolbar_settings(self): pass @@ -462,7 +463,6 @@ class MainWindowMixin(object): ac(-1, 4, 0, 'sync', _('Send to device'), 'sync.svg') ac(5, 5, 3, 'choose_library', _('%d books')%0, 'lt.png', tooltip=_('Choose calibre library to work with')) - ac(6, 6, 3, 'news', _('Fetch news'), 'news.svg', _('F')) ac(7, 7, 0, 'save', _('Save to disk'), 'save.svg', _('S')) ac(8, 8, 0, 'conn_share', _('Connect/share'), 'connect_share.svg') ac(9, 9, 3, 'del', _('Remove books'), 'trash.svg', _('Del')) @@ -482,9 +482,6 @@ class MainWindowMixin(object): ac(-1, -1, 0, 'books_with_the_same_tags', _('Books with the same tags'), 'tags.svg') - self.action_news.setMenu(self.scheduler.news_menu) - self.action_news.triggered.connect( - self.scheduler.show_dialog) self.share_conn_menu = ShareConnMenu(self) self.share_conn_menu.toggle_server.connect(self.toggle_content_server) self.share_conn_menu.config_email.connect(partial(self.do_config, diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index f3fa6f743e..2ba2a4ec52 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -256,6 +256,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ self.keyboard_interrupt.connect(self.quit, type=Qt.QueuedConnection) + self.read_settings() self.finalize_layout() self.donate_button.start_animation() From 886db1b6a8c285470acaa28ae75941a027b5cd56 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 12 Aug 2010 20:22:15 -0600 Subject: [PATCH 12/28] Migrate save to disk --- src/calibre/customize/builtins.py | 6 ++- src/calibre/gui2/actions/save_to_disk.py | 64 +++++++++++++++++++++--- src/calibre/gui2/layout.py | 38 -------------- src/calibre/gui2/ui.py | 7 +-- 4 files changed, 64 insertions(+), 51 deletions(-) diff --git a/src/calibre/customize/builtins.py b/src/calibre/customize/builtins.py index d64f36adc9..22730ba53f 100644 --- a/src/calibre/customize/builtins.py +++ b/src/calibre/customize/builtins.py @@ -609,6 +609,10 @@ class ActionFetchNews(InterfaceActionBase): name = 'Fetch News' actual_plugin = 'calibre.gui2.actions.fetch_news:FetchNewsAction' +class ActionSaveToDisk(InterfaceActionBase): + name = 'Save To Disk' + actual_plugin = 'calibre.gui2.actions.save_to_disk:SaveToDiskAction' + plugins += [ActionAdd, ActionFetchAnnotations, ActionGenerateCatalog, ActionConvert, ActionDelete, ActionEditMetadata, ActionView, - ActionFetchNews] + ActionFetchNews, ActionSaveToDisk] diff --git a/src/calibre/gui2/actions/save_to_disk.py b/src/calibre/gui2/actions/save_to_disk.py index 39df0948d2..4cfcc4d692 100644 --- a/src/calibre/gui2/actions/save_to_disk.py +++ b/src/calibre/gui2/actions/save_to_disk.py @@ -6,13 +6,65 @@ __copyright__ = '2010, Kovid Goyal ' __docformat__ = 'restructuredtext en' import os +from functools import partial + +from PyQt4.Qt import QMenu, pyqtSignal from calibre.utils.config import prefs from calibre.gui2 import error_dialog, Dispatcher, \ choose_dir, warning_dialog, open_local_file +from calibre.gui2.actions import InterfaceAction +from calibre.ebooks import BOOK_EXTENSIONS + +class SaveMenu(QMenu): # {{{ + + save_fmt = pyqtSignal(object) + + def __init__(self, parent): + QMenu.__init__(self, _('Save single format to disk...'), parent) + for ext in sorted(BOOK_EXTENSIONS): + action = self.addAction(ext.upper()) + setattr(self, 'do_'+ext, partial(self.do, ext)) + action.triggered.connect( + getattr(self, 'do_'+ext)) + + def do(self, ext, *args): + self.save_fmt.emit(ext) + +# }}} -class SaveToDiskAction(object): +class SaveToDiskAction(InterfaceAction): + + name = "Save To Disk" + action_spec = (_('Save to disk'), 'save.svg', None, _('S')) + + def genesis(self): + self.qaction.triggered.connect(self.save_to_disk) + self.save_menu = QMenu() + self.save_menu.addAction(_('Save to disk'), partial(self.save_to_disk, + False)) + self.save_menu.addAction(_('Save to disk in a single directory'), + partial(self.save_to_single_dir, False)) + self.save_menu.addAction(_('Save only %s format to disk')% + prefs['output_format'].upper(), + partial(self.save_single_format_to_disk, False)) + self.save_menu.addAction( + _('Save only %s format to disk in a single directory')% + prefs['output_format'].upper(), + partial(self.save_single_fmt_to_single_dir, False)) + self.save_sub_menu = SaveMenu(self.gui) + self.save_sub_menu_action = self.save_menu.addMenu(self.save_sub_menu) + self.save_sub_menu.save_fmt.connect(self.save_specific_format_disk) + self.qaction.setMenu(self.save_menu) + + def reread_prefs(self): + self.save_menu.actions()[2].setText( + _('Save only %s format to disk')% + prefs['output_format'].upper()) + self.save_menu.actions()[3].setText( + _('Save only %s format to disk in a single directory')% + prefs['output_format'].upper()) def save_single_format_to_disk(self, checked): self.save_to_disk(checked, False, prefs['output_format']) @@ -32,7 +84,7 @@ class SaveToDiskAction(object): if not rows or len(rows) == 0: return error_dialog(self.gui, _('Cannot save to disk'), _('No books selected'), show=True) - path = choose_dir(self, 'save to disk dialog', + path = choose_dir(self.gui, 'save to disk dialog', _('Choose destination directory')) if not path: return @@ -61,13 +113,13 @@ class SaveToDiskAction(object): opts.template = opts.template.split('/')[-1].strip() if not opts.template: opts.template = '{title} - {authors}' - self._saver = Saver(self, self.gui.library_view.model().db, + self._saver = Saver(self.gui, self.gui.library_view.model().db, Dispatcher(self._books_saved), rows, path, opts, - spare_server=self.spare_server) + spare_server=self.gui.spare_server) else: paths = self.gui.current_view().model().paths(rows) - self.device_manager.save_books( + self.gui.device_manager.save_books( Dispatcher(self.books_saved), paths, path) @@ -90,6 +142,6 @@ class SaveToDiskAction(object): def books_saved(self, job): if job.failed: - return self.device_job_exception(job) + return self.gui.device_job_exception(job) diff --git a/src/calibre/gui2/layout.py b/src/calibre/gui2/layout.py index c5ed84ff00..fcd3be398b 100644 --- a/src/calibre/gui2/layout.py +++ b/src/calibre/gui2/layout.py @@ -19,28 +19,10 @@ from calibre.gui2.throbber import ThrobbingButton from calibre.gui2 import config, open_url, gprefs from calibre.gui2.widgets import ComboBoxWithHelp from calibre import human_readable -from calibre.utils.config import prefs -from calibre.ebooks import BOOK_EXTENSIONS from calibre.gui2.dialogs.scheduler import Scheduler from calibre.utils.smtp import config as email_config -class SaveMenu(QMenu): # {{{ - - save_fmt = pyqtSignal(object) - - def __init__(self, parent): - QMenu.__init__(self, _('Save single format to disk...'), parent) - for ext in sorted(BOOK_EXTENSIONS): - action = self.addAction(ext.upper()) - setattr(self, 'do_'+ext, partial(self.do, ext)) - action.triggered.connect( - getattr(self, 'do_'+ext)) - - def do(self, ext, *args): - self.save_fmt.emit(ext) - -# }}} class LocationManager(QObject): # {{{ @@ -463,9 +445,7 @@ class MainWindowMixin(object): ac(-1, 4, 0, 'sync', _('Send to device'), 'sync.svg') ac(5, 5, 3, 'choose_library', _('%d books')%0, 'lt.png', tooltip=_('Choose calibre library to work with')) - ac(7, 7, 0, 'save', _('Save to disk'), 'save.svg', _('S')) ac(8, 8, 0, 'conn_share', _('Connect/share'), 'connect_share.svg') - ac(9, 9, 3, 'del', _('Remove books'), 'trash.svg', _('Del')) ac(10, 10, 3, 'help', _('Help'), 'help.svg', _('F1'), _("Browse the calibre User Manual")) ac(11, 11, 0, 'preferences', _('Preferences'), 'config.svg', _('Ctrl+P')) @@ -490,23 +470,6 @@ class MainWindowMixin(object): self.action_help.triggered.connect(self.show_help) - self.action_save.triggered.connect(self.save_to_disk) - self.save_menu = QMenu() - self.save_menu.addAction(_('Save to disk'), partial(self.save_to_disk, - False)) - self.save_menu.addAction(_('Save to disk in a single directory'), - partial(self.save_to_single_dir, False)) - self.save_menu.addAction(_('Save only %s format to disk')% - prefs['output_format'].upper(), - partial(self.save_single_format_to_disk, False)) - self.save_menu.addAction( - _('Save only %s format to disk in a single directory')% - prefs['output_format'].upper(), - partial(self.save_single_fmt_to_single_dir, False)) - self.save_sub_menu = SaveMenu(self) - self.save_menu.addMenu(self.save_sub_menu) - self.save_sub_menu.save_fmt.connect(self.save_specific_format_disk) - self.action_open_containing_folder.setShortcut(Qt.Key_O) self.addAction(self.action_open_containing_folder) @@ -517,7 +480,6 @@ class MainWindowMixin(object): self.action_sync.triggered.connect( self._sync_action_triggered) - self.action_save.setMenu(self.save_menu) pm = QMenu() diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index 2ba2a4ec52..581d02f9ab 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -387,13 +387,8 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ if d.result() == d.Accepted: self.read_toolbar_settings() self.search.search_as_you_type(config['search_as_you_type']) - self.save_menu.actions()[2].setText( - _('Save only %s format to disk')% - prefs['output_format'].upper()) - self.save_menu.actions()[3].setText( - _('Save only %s format to disk in a single directory')% - prefs['output_format'].upper()) self.tags_view.set_new_model() # in case columns changed + self.iactions['Save To Disk'].reread_prefs() self.tags_view.recount() self.create_device_menu() self.set_device_menu_items_state(bool(self.device_connected)) From 72c2d636b0ffe2008082afd4cd18400c8e72ae40 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 12 Aug 2010 22:34:40 -0600 Subject: [PATCH 13/28] Migrate device actions and other minor actions --- src/calibre/customize/builtins.py | 25 ++- src/calibre/gui2/actions/__init__.py | 1 + src/calibre/gui2/actions/device.py | 143 ++++++++++++++++++ src/calibre/gui2/actions/open.py | 24 +++ src/calibre/gui2/actions/restart.py | 22 +++ src/calibre/gui2/actions/show_book_details.py | 31 ++++ src/calibre/gui2/device.py | 16 +- src/calibre/gui2/init.py | 2 +- src/calibre/gui2/layout.py | 101 +------------ src/calibre/gui2/ui.py | 33 +--- 10 files changed, 255 insertions(+), 143 deletions(-) create mode 100644 src/calibre/gui2/actions/device.py create mode 100644 src/calibre/gui2/actions/open.py create mode 100644 src/calibre/gui2/actions/restart.py create mode 100644 src/calibre/gui2/actions/show_book_details.py diff --git a/src/calibre/customize/builtins.py b/src/calibre/customize/builtins.py index 22730ba53f..aa0948e3f8 100644 --- a/src/calibre/customize/builtins.py +++ b/src/calibre/customize/builtins.py @@ -613,6 +613,29 @@ class ActionSaveToDisk(InterfaceActionBase): name = 'Save To Disk' actual_plugin = 'calibre.gui2.actions.save_to_disk:SaveToDiskAction' +class ActionShowBookDetails(InterfaceActionBase): + name = 'Show Book Details' + actual_plugin = 'calibre.gui2.actions.show_book_details:ShowBookDetailsAction' + +class ActionRestart(InterfaceActionBase): + name = 'Restart' + actual_plugin = 'calibre.gui2.actions.restart:RestartAction' + +class ActionOpenFolder(InterfaceActionBase): + name = 'OpenFolder' + actual_plugin = 'calibre.gui2.actions.open:OpenFolderAction' + +class ActionSendToDevice(InterfaceActionBase): + name = 'Send To Device' + actual_plugin = 'calibre.gui2.actions.device:SendToDeviceAction' + +class ActionConnectShare(InterfaceActionBase): + name = 'Connect Share' + actual_plugin = 'calibre.gui2.actions.device:ConnectShareAction' + + plugins += [ActionAdd, ActionFetchAnnotations, ActionGenerateCatalog, ActionConvert, ActionDelete, ActionEditMetadata, ActionView, - ActionFetchNews, ActionSaveToDisk] + ActionFetchNews, ActionSaveToDisk, ActionShowBookDetails, + ActionRestart, ActionOpenFolder, ActionConnectShare, + ActionSendToDevice, ] diff --git a/src/calibre/gui2/actions/__init__.py b/src/calibre/gui2/actions/__init__.py index 4798828074..d5c6a0cf7e 100644 --- a/src/calibre/gui2/actions/__init__.py +++ b/src/calibre/gui2/actions/__init__.py @@ -32,6 +32,7 @@ class InterfaceAction(QObject): def do_genesis(self): self.Dispatcher = partial(Dispatcher, parent=self) self.create_action() + self.gui.addAction(self.qaction) self.genesis() def create_action(self, spec=None, attr='qaction'): diff --git a/src/calibre/gui2/actions/device.py b/src/calibre/gui2/actions/device.py new file mode 100644 index 0000000000..f1cfd84235 --- /dev/null +++ b/src/calibre/gui2/actions/device.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai + +__license__ = 'GPL v3' +__copyright__ = '2010, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +from functools import partial + +from PyQt4.Qt import QToolButton, QMenu, pyqtSignal, QIcon + +from calibre.gui2.actions import InterfaceAction +from calibre.utils.smtp import config as email_config + +class ShareConnMenu(QMenu): # {{{ + + connect_to_folder = pyqtSignal() + connect_to_itunes = pyqtSignal() + config_email = pyqtSignal() + toggle_server = pyqtSignal() + + def __init__(self, parent=None): + QMenu.__init__(self, parent) + mitem = self.addAction(QIcon(I('devices/folder.svg')), _('Connect to folder')) + mitem.setEnabled(True) + mitem.triggered.connect(lambda x : self.connect_to_folder.emit()) + self.connect_to_folder_action = mitem + mitem = self.addAction(QIcon(I('devices/itunes.png')), + _('Connect to iTunes')) + mitem.setEnabled(True) + mitem.triggered.connect(lambda x : self.connect_to_itunes.emit()) + self.connect_to_itunes_action = mitem + self.addSeparator() + self.toggle_server_action = \ + self.addAction(QIcon(I('network-server.svg')), + _('Start Content Server')) + self.toggle_server_action.triggered.connect(lambda x: + self.toggle_server.emit()) + self.addSeparator() + + self.email_actions = [] + + def server_state_changed(self, running): + text = _('Start Content Server') + if running: + text = _('Stop Content Server') + self.toggle_server_action.setText(text) + + def build_email_entries(self, sync_menu): + from calibre.gui2.device import DeviceAction + for ac in self.email_actions: + self.removeAction(ac) + self.email_actions = [] + self.memory = [] + opts = email_config().parse() + if opts.accounts: + self.email_to_menu = QMenu(_('Email to')+'...', self) + keys = sorted(opts.accounts.keys()) + for account in keys: + formats, auto, default = opts.accounts[account] + dest = 'mail:'+account+';'+formats + action1 = DeviceAction(dest, False, False, I('mail.svg'), + _('Email to')+' '+account) + action2 = DeviceAction(dest, True, False, I('mail.svg'), + _('Email to')+' '+account+ _(' and delete from library')) + map(self.email_to_menu.addAction, (action1, action2)) + map(self.memory.append, (action1, action2)) + if default: + map(self.addAction, (action1, action2)) + map(self.email_actions.append, (action1, action2)) + self.email_to_menu.addSeparator() + action1.a_s.connect(sync_menu.action_triggered) + action2.a_s.connect(sync_menu.action_triggered) + ac = self.addMenu(self.email_to_menu) + self.email_actions.append(ac) + else: + ac = self.addAction(_('Setup email based sharing of books')) + self.email_actions.append(ac) + ac.triggered.connect(self.setup_email) + + def setup_email(self, *args): + self.config_email.emit() + + def set_state(self, device_connected): + self.connect_to_folder_action.setEnabled(not device_connected) + self.connect_to_itunes_action.setEnabled(not device_connected) + + +# }}} + +class SendToDeviceAction(InterfaceAction): + + name = 'Send To Device' + action_spec = (_('Send to device'), 'sync.svg', None, _('D')) + + def genesis(self): + self.qaction.triggered.connect(self.do_sync) + self.gui.create_device_menu() + + def location_selected(self, loc): + enabled = loc == 'library' + self.qaction.setEnabled(enabled) + + def do_sync(self, *args): + self.gui._sync_action_triggered() + + +class ConnectShareAction(InterfaceAction): + + name = 'Connect Share' + action_spec = (_('Connect/share'), 'connect_share.svg', None, None) + popup_type = QToolButton.InstantPopup + + def genesis(self): + self.share_conn_menu = ShareConnMenu(self.gui) + self.share_conn_menu.toggle_server.connect(self.toggle_content_server) + self.share_conn_menu.config_email.connect(partial( + self.gui.iactions['Preferences'].do_config, + initial_category='email')) + self.qaction.setMenu(self.share_conn_menu) + self.share_conn_menu.connect_to_folder.connect(self.gui.connect_to_folder) + self.share_conn_menu.connect_to_itunes.connect(self.gui.connect_to_itunes) + + def location_selected(self, loc): + enabled = loc == 'library' + self.qaction.setEnabled(enabled) + + def set_state(self, device_connected): + self.share_conn_menu.set_state(device_connected) + + def build_email_entries(self): + m = self.gui.iactions['Send To Device'].qaction.menu() + self.share_conn_menu.build_email_entries(m) + + def content_server_state_changed(self, running): + self.share_conn_menu.server_state_changed(running) + + def toggle_content_server(self): + if self.gui.content_server is None: + self.gui.start_content_server() + else: + self.gui.content_server.exit() + self.gui.content_server = None diff --git a/src/calibre/gui2/actions/open.py b/src/calibre/gui2/actions/open.py new file mode 100644 index 0000000000..569f037327 --- /dev/null +++ b/src/calibre/gui2/actions/open.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai + +__license__ = 'GPL v3' +__copyright__ = '2010, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + + +from calibre.gui2.actions import InterfaceAction + +class OpenFolderAction(InterfaceAction): + + name = 'Open Folder' + action_spec = (_('Open containing folder'), 'document_open.svg', None, + _('O')) + + def genesis(self): + self.action_open_containing_folder.triggered.connect(self.iactions['View'].view_folder) + + def location_selected(self, loc): + enabled = loc == 'library' + self.qaction.setEnabled(enabled) + + diff --git a/src/calibre/gui2/actions/restart.py b/src/calibre/gui2/actions/restart.py new file mode 100644 index 0000000000..be940fa32e --- /dev/null +++ b/src/calibre/gui2/actions/restart.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai + +__license__ = 'GPL v3' +__copyright__ = '2010, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + + +from calibre.gui2.actions import InterfaceAction + +class RestartAction(InterfaceAction): + + name = 'Restart' + action_spec = (_('&Restart'), None, None, _('Ctrl+R')) + + def genesis(self): + self.qaction.triggered.connect(self.restart) + + def restart(self, *args): + self.gui.quit(restart=True) + + diff --git a/src/calibre/gui2/actions/show_book_details.py b/src/calibre/gui2/actions/show_book_details.py new file mode 100644 index 0000000000..06c63714a7 --- /dev/null +++ b/src/calibre/gui2/actions/show_book_details.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai + +__license__ = 'GPL v3' +__copyright__ = '2010, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + + +from calibre.gui2.actions import InterfaceAction +from calibre.gui2.dialogs.book_info import BookInfo +from calibre.gui2 import error_dialog + +class ShowBookDetailsAction(InterfaceAction): + + name = 'Show Book Details' + action_spec = (_('Show book details'), 'dialog_information.svg', None, + _('I')) + + def genesis(self): + self.qaction.triggered.connect(self.show_book_info) + + def show_book_info(self, *args): + if self.gui.current_view() is not self.gui.library_view: + error_dialog(self.gui, _('No detailed info available'), + _('No detailed information is available for books ' + 'on the device.')).exec_() + return + index = self.gui.library_view.currentIndex() + if index.isValid(): + BookInfo(self.gui, self.gui.library_view, index).show() + diff --git a/src/calibre/gui2/device.py b/src/calibre/gui2/device.py index 1e716a85fe..a9beb317a2 100644 --- a/src/calibre/gui2/device.py +++ b/src/calibre/gui2/device.py @@ -608,8 +608,6 @@ class DeviceMixin(object): # {{{ self.device_error_dialog = error_dialog(self, _('Error'), _('Error communicating with device'), ' ') self.device_error_dialog.setModal(Qt.NonModal) - self.share_conn_menu.connect_to_folder.connect(self.connect_to_folder) - self.share_conn_menu.connect_to_itunes.connect(self.connect_to_itunes) self.emailer = Emailer() self.emailer.start() self.device_manager = DeviceManager(Dispatcher(self.device_detected), @@ -647,21 +645,18 @@ class DeviceMixin(object): # {{{ def create_device_menu(self): self._sync_menu = DeviceMenu(self) - self.share_conn_menu.build_email_entries(self._sync_menu) - self.action_sync.setMenu(self._sync_menu) + self.iactions['Send To Device'].qaction.setMenu(self._sync_menu) + self.iactions['Connect Share'].build_email_entries() self.connect(self._sync_menu, SIGNAL('sync(PyQt_PyObject, PyQt_PyObject, PyQt_PyObject)'), self.dispatch_sync_event) self._sync_menu.fetch_annotations.connect( self.iactions['Fetch Annotations'].fetch_annotations) self._sync_menu.disconnect_mounted_device.connect(self.disconnect_mounted_device) + self.iactions['Connect Share'].set_state(self.device_connected) if self.device_connected: - self.share_conn_menu.connect_to_folder_action.setEnabled(False) - self.share_conn_menu.connect_to_itunes_action.setEnabled(False) self._sync_menu.disconnect_mounted_device_action.setEnabled(True) else: - self.share_conn_menu.connect_to_folder_action.setEnabled(True) - self.share_conn_menu.connect_to_itunes_action.setEnabled(True) self._sync_menu.disconnect_mounted_device_action.setEnabled(False) def device_job_exception(self, job): @@ -697,17 +692,14 @@ class DeviceMixin(object): # {{{ # Device connected {{{ def set_device_menu_items_state(self, connected): + self.iactions['Connect Share'].set_state(connected) if connected: - self.share_conn_menu.connect_to_folder_action.setEnabled(False) - self.share_conn_menu.connect_to_itunes_action.setEnabled(False) self._sync_menu.disconnect_mounted_device_action.setEnabled(True) self._sync_menu.enable_device_actions(True, self.device_manager.device.card_prefix(), self.device_manager.device) self.eject_action.setEnabled(True) else: - self.share_conn_menu.connect_to_folder_action.setEnabled(True) - self.share_conn_menu.connect_to_itunes_action.setEnabled(True) self._sync_menu.disconnect_mounted_device_action.setEnabled(False) self._sync_menu.enable_device_actions(False) self.eject_action.setEnabled(False) diff --git a/src/calibre/gui2/init.py b/src/calibre/gui2/init.py index 839bfd536c..2b89057fc4 100644 --- a/src/calibre/gui2/init.py +++ b/src/calibre/gui2/init.py @@ -306,7 +306,7 @@ class LayoutMixin(object): # {{{ def finalize_layout(self): self.status_bar.initialize(self.system_tray_icon) - self.book_details.show_book_info.connect(self.show_book_info) + self.book_details.show_book_info.connect(self.iactions['Show Book Details'].show_book_info) self.book_details.files_dropped.connect(self.iactions['Add Books'].files_dropped_on_book) self.book_details.open_containing_folder.connect(self.iactions['View'].view_folder_for_id) self.book_details.view_specific_format.connect(self.iactions['View'].view_format_by_id) diff --git a/src/calibre/gui2/layout.py b/src/calibre/gui2/layout.py index fcd3be398b..72d548f287 100644 --- a/src/calibre/gui2/layout.py +++ b/src/calibre/gui2/layout.py @@ -20,7 +20,6 @@ from calibre.gui2 import config, open_url, gprefs from calibre.gui2.widgets import ComboBoxWithHelp from calibre import human_readable from calibre.gui2.dialogs.scheduler import Scheduler -from calibre.utils.smtp import config as email_config @@ -306,77 +305,6 @@ class ToolBar(QToolBar): # {{{ class Action(QAction): pass -class ShareConnMenu(QMenu): # {{{ - - connect_to_folder = pyqtSignal() - connect_to_itunes = pyqtSignal() - config_email = pyqtSignal() - toggle_server = pyqtSignal() - - def __init__(self, parent=None): - QMenu.__init__(self, parent) - mitem = self.addAction(QIcon(I('devices/folder.svg')), _('Connect to folder')) - mitem.setEnabled(True) - mitem.triggered.connect(lambda x : self.connect_to_folder.emit()) - self.connect_to_folder_action = mitem - mitem = self.addAction(QIcon(I('devices/itunes.png')), - _('Connect to iTunes')) - mitem.setEnabled(True) - mitem.triggered.connect(lambda x : self.connect_to_itunes.emit()) - self.connect_to_itunes_action = mitem - self.addSeparator() - self.toggle_server_action = \ - self.addAction(QIcon(I('network-server.svg')), - _('Start Content Server')) - self.toggle_server_action.triggered.connect(lambda x: - self.toggle_server.emit()) - self.addSeparator() - - self.email_actions = [] - - def server_state_changed(self, running): - text = _('Start Content Server') - if running: - text = _('Stop Content Server') - self.toggle_server_action.setText(text) - - def build_email_entries(self, sync_menu): - from calibre.gui2.device import DeviceAction - for ac in self.email_actions: - self.removeAction(ac) - self.email_actions = [] - self.memory = [] - opts = email_config().parse() - if opts.accounts: - self.email_to_menu = QMenu(_('Email to')+'...', self) - keys = sorted(opts.accounts.keys()) - for account in keys: - formats, auto, default = opts.accounts[account] - dest = 'mail:'+account+';'+formats - action1 = DeviceAction(dest, False, False, I('mail.svg'), - _('Email to')+' '+account) - action2 = DeviceAction(dest, True, False, I('mail.svg'), - _('Email to')+' '+account+ _(' and delete from library')) - map(self.email_to_menu.addAction, (action1, action2)) - map(self.memory.append, (action1, action2)) - if default: - map(self.addAction, (action1, action2)) - map(self.email_actions.append, (action1, action2)) - self.email_to_menu.addSeparator() - action1.a_s.connect(sync_menu.action_triggered) - action2.a_s.connect(sync_menu.action_triggered) - ac = self.addMenu(self.email_to_menu) - self.email_actions.append(ac) - else: - ac = self.addAction(_('Setup email based sharing of books')) - self.email_actions.append(ac) - ac.triggered.connect(self.setup_email) - - def setup_email(self, *args): - self.config_email.emit() - -# }}} - class MainWindowMixin(object): def __init__(self, db): @@ -442,17 +370,11 @@ class MainWindowMixin(object): setattr(self, 'action_'+name, action) all_actions.append(action) - ac(-1, 4, 0, 'sync', _('Send to device'), 'sync.svg') ac(5, 5, 3, 'choose_library', _('%d books')%0, 'lt.png', tooltip=_('Choose calibre library to work with')) - ac(8, 8, 0, 'conn_share', _('Connect/share'), 'connect_share.svg') ac(10, 10, 3, 'help', _('Help'), 'help.svg', _('F1'), _("Browse the calibre User Manual")) ac(11, 11, 0, 'preferences', _('Preferences'), 'config.svg', _('Ctrl+P')) - ac(-1, -1, 0, 'open_containing_folder', _('Open containing folder'), - 'document_open.svg') - ac(-1, -1, 0, 'show_book_details', _('Show book details'), - 'dialog_information.svg') ac(-1, -1, 0, 'books_by_same_author', _('Books by same author'), 'user_profile.svg') ac(-1, -1, 0, 'books_in_this_series', _('Books in this series'), @@ -462,24 +384,10 @@ class MainWindowMixin(object): ac(-1, -1, 0, 'books_with_the_same_tags', _('Books with the same tags'), 'tags.svg') - self.share_conn_menu = ShareConnMenu(self) - self.share_conn_menu.toggle_server.connect(self.toggle_content_server) - self.share_conn_menu.config_email.connect(partial(self.do_config, - initial_category='email')) - self.action_conn_share.setMenu(self.share_conn_menu) self.action_help.triggered.connect(self.show_help) - self.action_open_containing_folder.setShortcut(Qt.Key_O) - self.addAction(self.action_open_containing_folder) - self.action_open_containing_folder.triggered.connect(self.iactions['View'].view_folder) - self.action_sync.setShortcut(Qt.Key_D) - self.action_sync.setEnabled(True) - self.create_device_menu() - self.action_sync.triggered.connect( - self._sync_action_triggered) - pm = QMenu() @@ -498,12 +406,5 @@ class MainWindowMixin(object): def show_help(self, *args): open_url(QUrl('http://calibre-ebook.com/user_manual')) - def content_server_state_changed(self, running): - self.share_conn_menu.server_state_changed(running) - def toggle_content_server(self): - if self.content_server is None: - self.start_content_server() - else: - self.content_server.exit() - self.content_server = None + diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index 581d02f9ab..c62a2d3fc8 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -15,7 +15,7 @@ from threading import Thread from PyQt4.Qt import Qt, SIGNAL, QTimer, \ QPixmap, QMenu, QIcon, pyqtSignal, \ QDialog, \ - QSystemTrayIcon, QApplication, QKeySequence, QAction, \ + QSystemTrayIcon, QApplication, QKeySequence, \ QMessageBox, QHelpEvent from calibre import prints @@ -35,7 +35,6 @@ from calibre.gui2.layout import MainWindowMixin from calibre.gui2.device import DeviceMixin from calibre.gui2.jobs import JobManager, JobsDialog, JobsButton from calibre.gui2.dialogs.config import ConfigDialog -from calibre.gui2.dialogs.book_info import BookInfo from calibre.gui2.init import LibraryViewMixin, LayoutMixin from calibre.gui2.search_box import SearchBoxMixin, SavedSearchBoxMixin from calibre.gui2.search_restriction_mixin import SearchRestrictionMixin @@ -172,22 +171,13 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ QIcon(I('eject.svg')), _('&Eject connected device')) self.eject_action.setEnabled(False) self.addAction(self.quit_action) - self.action_restart = QAction(_('&Restart'), self) - self.addAction(self.action_restart) self.system_tray_menu.addAction(self.quit_action) self.quit_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_Q)) - self.action_restart.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_R)) - self.action_show_book_details.setShortcut(QKeySequence(Qt.Key_I)) - self.addAction(self.action_show_book_details) self.system_tray_icon.setContextMenu(self.system_tray_menu) self.connect(self.quit_action, SIGNAL('triggered(bool)'), self.quit) self.connect(self.donate_action, SIGNAL('triggered(bool)'), self.donate) self.connect(self.restore_action, SIGNAL('triggered()'), self.show_windows) - self.connect(self.action_show_book_details, - SIGNAL('triggered(bool)'), self.show_book_info) - self.connect(self.action_restart, SIGNAL('triggered()'), - self.restart) self.connect(self.system_tray_icon, SIGNAL('activated(QSystemTrayIcon::ActivationReason)'), self.system_tray_icon_activated) @@ -270,7 +260,8 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ from calibre.library.server import server_config self.content_server = start_threaded_server( self.library_view.model().db, server_config().parse()) - self.content_server.state_callback = Dispatcher(self.content_server_state_changed) + self.content_server.state_callback = Dispatcher( + self.iactions['Connect Share'].content_server_state_changed) self.content_server.state_callback(True) self.test_server_timer = QTimer.singleShot(10000, self.test_server) @@ -381,7 +372,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ self.content_server = d.server if self.content_server is not None: self.content_server.state_callback = \ - Dispatcher(self.content_server_state_changed) + Dispatcher(self.iactions['Connect Share'].content_server_state_changed) self.content_server.state_callback(self.content_server.is_running) if d.result() == d.Accepted: @@ -411,15 +402,6 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ self.scheduler.database_changed(db) prefs['library_path'] = self.library_path - def show_book_info(self, *args): - if self.current_view() is not self.library_view: - error_dialog(self, _('No detailed info available'), - _('No detailed information is available for books ' - 'on the device.')).exec_() - return - index = self.library_view.currentIndex() - if index.isValid(): - BookInfo(self, self.library_view, index).show() def location_selected(self, location): ''' @@ -434,12 +416,8 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ for action in self.iactions.values(): action.location_selected(location) if location == 'library': - self.action_open_containing_folder.setEnabled(True) - self.action_sync.setEnabled(True) self.search_restriction.setEnabled(True) else: - self.action_open_containing_folder.setEnabled(False) - self.action_sync.setEnabled(False) self.search_restriction.setEnabled(False) # Reset the view in case something changed while it was invisible self.current_view().reset() @@ -503,9 +481,6 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ dynamic.set('sort_history', self.library_view.model().sort_history) self.save_layout_state() - def restart(self): - self.quit(restart=True) - def quit(self, checked=True, restart=False): if not self.confirm_quit(): return From 0ffaa50f6ddce98096dc548428eb2e0994a6fd11 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 12 Aug 2010 22:50:53 -0600 Subject: [PATCH 14/28] ... --- src/calibre/gui2/actions/open.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/gui2/actions/open.py b/src/calibre/gui2/actions/open.py index 569f037327..40fc6372b7 100644 --- a/src/calibre/gui2/actions/open.py +++ b/src/calibre/gui2/actions/open.py @@ -15,7 +15,7 @@ class OpenFolderAction(InterfaceAction): _('O')) def genesis(self): - self.action_open_containing_folder.triggered.connect(self.iactions['View'].view_folder) + self.qaction.triggered.connect(self.gui.iactions['View'].view_folder) def location_selected(self, loc): enabled = loc == 'library' From bfb8cad41af7e867c876ce489513ff463254bad3 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 12 Aug 2010 23:18:31 -0600 Subject: [PATCH 15/28] Migrate help and prefs actions --- src/calibre/customize/builtins.py | 10 +++- src/calibre/gui2/actions/help.py | 25 ++++++++++ src/calibre/gui2/actions/preferences.py | 62 +++++++++++++++++++++++++ src/calibre/gui2/layout.py | 23 +-------- src/calibre/gui2/ui.py | 31 ------------- 5 files changed, 98 insertions(+), 53 deletions(-) create mode 100644 src/calibre/gui2/actions/help.py create mode 100644 src/calibre/gui2/actions/preferences.py diff --git a/src/calibre/customize/builtins.py b/src/calibre/customize/builtins.py index aa0948e3f8..83413b3d3d 100644 --- a/src/calibre/customize/builtins.py +++ b/src/calibre/customize/builtins.py @@ -633,9 +633,17 @@ class ActionConnectShare(InterfaceActionBase): name = 'Connect Share' actual_plugin = 'calibre.gui2.actions.device:ConnectShareAction' +class ActionHelp(InterfaceActionBase): + name = 'Help' + actual_plugin = 'calibre.gui2.actions.help:HelpAction' + +class ActionPreferences(InterfaceActionBase): + name = 'Preferences' + actual_plugin = 'calibre.gui2.actions.preferences:PreferencesAction' + plugins += [ActionAdd, ActionFetchAnnotations, ActionGenerateCatalog, ActionConvert, ActionDelete, ActionEditMetadata, ActionView, ActionFetchNews, ActionSaveToDisk, ActionShowBookDetails, ActionRestart, ActionOpenFolder, ActionConnectShare, - ActionSendToDevice, ] + ActionSendToDevice, ActionHelp, ActionPreferences] diff --git a/src/calibre/gui2/actions/help.py b/src/calibre/gui2/actions/help.py new file mode 100644 index 0000000000..0c6b257b80 --- /dev/null +++ b/src/calibre/gui2/actions/help.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai + +__license__ = 'GPL v3' +__copyright__ = '2010, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +from PyQt4.Qt import QUrl + +from calibre.gui2 import open_url +from calibre.gui2.actions import InterfaceAction + +class HelpAction(InterfaceAction): + + name = 'Help' + action_spec = (_('Help'), 'help.svg', _('Browse the calibre User Manual'), _('F1'),) + + def genesis(self): + self.qaction.triggered.connect(self.show_help) + + def show_help(self, *args): + open_url(QUrl('http://calibre-ebook.com/user_manual')) + + + diff --git a/src/calibre/gui2/actions/preferences.py b/src/calibre/gui2/actions/preferences.py new file mode 100644 index 0000000000..b33c165316 --- /dev/null +++ b/src/calibre/gui2/actions/preferences.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai + +__license__ = 'GPL v3' +__copyright__ = '2010, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +from PyQt4.Qt import QIcon, QMenu + +from calibre.gui2.actions import InterfaceAction +from calibre.gui2.dialogs.config import ConfigDialog +from calibre.gui2 import error_dialog, config + +class PreferencesAction(InterfaceAction): + + name = 'Preferences' + action_spec = (_('Preferences'), 'config.svg', None, _('Ctrl+P')) + + def genesis(self): + pm = QMenu() + pm.addAction(QIcon(I('config.svg')), _('Preferences'), self.do_config) + pm.addAction(QIcon(I('wizard.svg')), _('Run welcome wizard'), + self.gui.run_wizard) + self.qaction.setMenu(pm) + self.preferences_menu = pm + for x in (self.gui.preferences_action, self.qaction): + x.triggered.connect(self.do_config) + + + def do_config(self, checked=False, initial_category='general'): + if self.gui.job_manager.has_jobs(): + d = error_dialog(self.gui, _('Cannot configure'), + _('Cannot configure while there are running jobs.')) + d.exec_() + return + if self.gui.must_restart_before_config: + d = error_dialog(self.gui, _('Cannot configure'), + _('Cannot configure before calibre is restarted.')) + d.exec_() + return + d = ConfigDialog(self.gui, self.gui.library_view, + server=self.gui.content_server, initial_category=initial_category) + + d.exec_() + self.gui.content_server = d.server + if self.gui.content_server is not None: + self.gui.content_server.state_callback = \ + self.Dispatcher(self.gui.iactions['Connect Share'].content_server_state_changed) + self.gui.content_server.state_callback(self.gui.content_server.is_running) + + if d.result() == d.Accepted: + self.gui.read_toolbar_settings() + self.gui.search.search_as_you_type(config['search_as_you_type']) + self.gui.tags_view.set_new_model() # in case columns changed + self.gui.iactions['Save To Disk'].reread_prefs() + self.gui.tags_view.recount() + self.gui.create_device_menu() + self.gui.set_device_menu_items_state(bool(self.gui.device_connected)) + self.gui.tool_bar.apply_settings() + + + diff --git a/src/calibre/gui2/layout.py b/src/calibre/gui2/layout.py index 72d548f287..8143c7355b 100644 --- a/src/calibre/gui2/layout.py +++ b/src/calibre/gui2/layout.py @@ -11,12 +11,12 @@ from functools import partial from PyQt4.Qt import QIcon, Qt, QWidget, QAction, QToolBar, QSize, \ pyqtSignal, QToolButton, \ QObject, QVBoxLayout, QSizePolicy, QLabel, QHBoxLayout, QActionGroup, \ - QMenu, QUrl + QMenu from calibre.constants import __appname__ from calibre.gui2.search_box import SearchBox2, SavedSearchBox from calibre.gui2.throbber import ThrobbingButton -from calibre.gui2 import config, open_url, gprefs +from calibre.gui2 import config, gprefs from calibre.gui2.widgets import ComboBoxWithHelp from calibre import human_readable from calibre.gui2.dialogs.scheduler import Scheduler @@ -372,8 +372,6 @@ class MainWindowMixin(object): ac(5, 5, 3, 'choose_library', _('%d books')%0, 'lt.png', tooltip=_('Choose calibre library to work with')) - ac(10, 10, 3, 'help', _('Help'), 'help.svg', _('F1'), _("Browse the calibre User Manual")) - ac(11, 11, 0, 'preferences', _('Preferences'), 'config.svg', _('Ctrl+P')) ac(-1, -1, 0, 'books_by_same_author', _('Books by same author'), 'user_profile.svg') @@ -385,26 +383,9 @@ class MainWindowMixin(object): 'tags.svg') - self.action_help.triggered.connect(self.show_help) - - - - - pm = QMenu() - pm.addAction(QIcon(I('config.svg')), _('Preferences'), self.do_config) - pm.addAction(QIcon(I('wizard.svg')), _('Run welcome wizard'), - self.run_wizard) - self.action_preferences.setMenu(pm) - self.preferences_menu = pm - for x in (self.preferences_action, self.action_preferences): - x.triggered.connect(self.do_config) - return all_actions # }}} - def show_help(self, *args): - open_url(QUrl('http://calibre-ebook.com/user_manual')) - diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index c62a2d3fc8..0fb52ad7b9 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -34,7 +34,6 @@ from calibre.gui2.main_window import MainWindow from calibre.gui2.layout import MainWindowMixin from calibre.gui2.device import DeviceMixin from calibre.gui2.jobs import JobManager, JobsDialog, JobsButton -from calibre.gui2.dialogs.config import ConfigDialog from calibre.gui2.init import LibraryViewMixin, LayoutMixin from calibre.gui2.search_box import SearchBoxMixin, SavedSearchBoxMixin from calibre.gui2.search_restriction_mixin import SearchRestrictionMixin @@ -354,36 +353,6 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ return self.memory_view.model().db, self.card_a_view.model().db, self.card_b_view.model().db - def do_config(self, checked=False, initial_category='general'): - if self.job_manager.has_jobs(): - d = error_dialog(self, _('Cannot configure'), - _('Cannot configure while there are running jobs.')) - d.exec_() - return - if self.must_restart_before_config: - d = error_dialog(self, _('Cannot configure'), - _('Cannot configure before calibre is restarted.')) - d.exec_() - return - d = ConfigDialog(self, self.library_view, - server=self.content_server, initial_category=initial_category) - - d.exec_() - self.content_server = d.server - if self.content_server is not None: - self.content_server.state_callback = \ - Dispatcher(self.iactions['Connect Share'].content_server_state_changed) - self.content_server.state_callback(self.content_server.is_running) - - if d.result() == d.Accepted: - self.read_toolbar_settings() - self.search.search_as_you_type(config['search_as_you_type']) - self.tags_view.set_new_model() # in case columns changed - self.iactions['Save To Disk'].reread_prefs() - self.tags_view.recount() - self.create_device_menu() - self.set_device_menu_items_state(bool(self.device_connected)) - self.tool_bar.apply_settings() def library_moved(self, newloc): if newloc is None: return From 4635ae37d7143f43031c6caf8ab376543fc38d92 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 12 Aug 2010 23:33:21 -0600 Subject: [PATCH 16/28] Migrate show similar books action --- src/calibre/customize/builtins.py | 6 ++- src/calibre/gui2/actions/__init__.py | 1 + src/calibre/gui2/actions/similar_books.py | 60 +++++++++++++++++++++++ src/calibre/gui2/init.py | 51 +------------------ src/calibre/gui2/layout.py | 9 ---- 5 files changed, 67 insertions(+), 60 deletions(-) create mode 100644 src/calibre/gui2/actions/similar_books.py diff --git a/src/calibre/customize/builtins.py b/src/calibre/customize/builtins.py index 83413b3d3d..1e84570e54 100644 --- a/src/calibre/customize/builtins.py +++ b/src/calibre/customize/builtins.py @@ -641,9 +641,13 @@ class ActionPreferences(InterfaceActionBase): name = 'Preferences' actual_plugin = 'calibre.gui2.actions.preferences:PreferencesAction' +class ActionSimilarBooks(InterfaceActionBase): + name = 'Similar Books' + actual_plugin = 'calibre.gui2.actions.similar_books:SimilarBooksAction' + plugins += [ActionAdd, ActionFetchAnnotations, ActionGenerateCatalog, ActionConvert, ActionDelete, ActionEditMetadata, ActionView, ActionFetchNews, ActionSaveToDisk, ActionShowBookDetails, ActionRestart, ActionOpenFolder, ActionConnectShare, - ActionSendToDevice, ActionHelp, ActionPreferences] + ActionSendToDevice, ActionHelp, ActionPreferences, ActionSimilarBooks] diff --git a/src/calibre/gui2/actions/__init__.py b/src/calibre/gui2/actions/__init__.py index d5c6a0cf7e..f2905885bf 100644 --- a/src/calibre/gui2/actions/__init__.py +++ b/src/calibre/gui2/actions/__init__.py @@ -51,6 +51,7 @@ class InterfaceAction(QObject): if shortcut: action.setShortcut(shortcut) setattr(self, attr, action) + return action def genesis(self): pass diff --git a/src/calibre/gui2/actions/similar_books.py b/src/calibre/gui2/actions/similar_books.py new file mode 100644 index 0000000000..9c3a52e694 --- /dev/null +++ b/src/calibre/gui2/actions/similar_books.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai + +__license__ = 'GPL v3' +__copyright__ = '2010, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +from functools import partial + +from PyQt4.Qt import QMenu + +from calibre.gui2.actions import InterfaceAction + +class SimilarBooksAction(InterfaceAction): + + name = 'Similar Books' + action_spec = (_('Similar books...'), None, None, None) + + def genesis(self): + m = QMenu(self.gui) + for text, icon, target, shortcut in [ + (_('Books by same author'), 'user_profile.svg', 'authors', _('Alt+A')), + (_('Books in this series'), 'books_in_series.svg', 'series', _('Alt+S')), + (_('Books by this publisher'), 'publisher.png', 'publisher', _('Alt+P')) + (_('Books with the same tags'), 'tags.svg', 'tag', _('Alt+T'))]: + ac = self.create_action(spec=(text, icon, None, shortcut), + attr=target) + m.addAction(ac) + m.triggered.connect(partial(self.show_similar_books, target)) + self.qaction.setMenu(m) + self.similar_menu = m + + def show_similar_books(self, type, *args): + search, join = [], ' ' + idx = self.gui.library_view.currentIndex() + if not idx.isValid(): + return + row = idx.row() + if type == 'series': + series = idx.model().db.series(row) + if series: + search = ['series:"'+series+'"'] + elif type == 'publisher': + publisher = idx.model().db.publisher(row) + if publisher: + search = ['publisher:"'+publisher+'"'] + elif type == 'tag': + tags = idx.model().db.tags(row) + if tags: + search = ['tag:"='+t+'"' for t in tags.split(',')] + elif type in ('author', 'authors'): + authors = idx.model().db.authors(row) + if authors: + search = ['author:"='+a.strip().replace('|', ',')+'"' \ + for a in authors.split(',')] + join = ' or ' + if search: + self.gui.search.set_search_string(join.join(search)) + + diff --git a/src/calibre/gui2/init.py b/src/calibre/gui2/init.py index 2b89057fc4..86452fecee 100644 --- a/src/calibre/gui2/init.py +++ b/src/calibre/gui2/init.py @@ -7,7 +7,7 @@ __docformat__ = 'restructuredtext en' import functools, sys, os -from PyQt4.Qt import QMenu, Qt, QStackedWidget, \ +from PyQt4.Qt import Qt, QStackedWidget, \ QSize, QSizePolicy, QStatusBar, QLabel, QFont from calibre.utils.config import prefs @@ -30,28 +30,6 @@ def partial(*args, **kwargs): class LibraryViewMixin(object): # {{{ def __init__(self, db): - similar_menu = QMenu(_('Similar books...')) - similar_menu.addAction(self.action_books_by_same_author) - similar_menu.addAction(self.action_books_in_this_series) - similar_menu.addAction(self.action_books_with_the_same_tags) - similar_menu.addAction(self.action_books_by_this_publisher) - self.action_books_by_same_author.setShortcut(Qt.ALT + Qt.Key_A) - self.action_books_in_this_series.setShortcut(Qt.ALT + Qt.Key_S) - self.action_books_by_this_publisher.setShortcut(Qt.ALT + Qt.Key_P) - self.action_books_with_the_same_tags.setShortcut(Qt.ALT+Qt.Key_T) - self.addAction(self.action_books_by_same_author) - self.addAction(self.action_books_by_this_publisher) - self.addAction(self.action_books_in_this_series) - self.addAction(self.action_books_with_the_same_tags) - self.similar_menu = similar_menu - self.action_books_by_same_author.triggered.connect( - partial(self.show_similar_books, 'authors')) - self.action_books_in_this_series.triggered.connect( - partial(self.show_similar_books, 'series')) - self.action_books_with_the_same_tags.triggered.connect( - partial(self.show_similar_books, 'tag')) - self.action_books_by_this_publisher.triggered.connect( - partial(self.show_similar_books, 'publisher')) self.library_view.set_context_menu(self.action_edit, self.action_sync, self.action_convert, self.action_view, @@ -122,33 +100,6 @@ class LibraryViewMixin(object): # {{{ - def show_similar_books(self, type, *args): - search, join = [], ' ' - idx = self.library_view.currentIndex() - if not idx.isValid(): - return - row = idx.row() - if type == 'series': - series = idx.model().db.series(row) - if series: - search = ['series:"'+series+'"'] - elif type == 'publisher': - publisher = idx.model().db.publisher(row) - if publisher: - search = ['publisher:"'+publisher+'"'] - elif type == 'tag': - tags = idx.model().db.tags(row) - if tags: - search = ['tag:"='+t+'"' for t in tags.split(',')] - elif type in ('author', 'authors'): - authors = idx.model().db.authors(row) - if authors: - search = ['author:"='+a.strip().replace('|', ',')+'"' \ - for a in authors.split(',')] - join = ' or ' - if search: - self.search.set_search_string(join.join(search)) - def search_done(self, view, ok): if view is self.current_view(): self.search.search_done(ok) diff --git a/src/calibre/gui2/layout.py b/src/calibre/gui2/layout.py index 8143c7355b..aaf94f7585 100644 --- a/src/calibre/gui2/layout.py +++ b/src/calibre/gui2/layout.py @@ -373,15 +373,6 @@ class MainWindowMixin(object): ac(5, 5, 3, 'choose_library', _('%d books')%0, 'lt.png', tooltip=_('Choose calibre library to work with')) - ac(-1, -1, 0, 'books_by_same_author', _('Books by same author'), - 'user_profile.svg') - ac(-1, -1, 0, 'books_in_this_series', _('Books in this series'), - 'books_in_series.svg') - ac(-1, -1, 0, 'books_by_this_publisher', _('Books by this publisher'), - 'publisher.png') - ac(-1, -1, 0, 'books_with_the_same_tags', _('Books with the same tags'), - 'tags.svg') - return all_actions From c02272593eae36f69fed1ae9531b67b600fe81ac Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 12 Aug 2010 23:53:06 -0600 Subject: [PATCH 17/28] Migrate choose library and cleanup fetch news connections --- src/calibre/customize/builtins.py | 4 ++ src/calibre/gui2/actions/choose_library.py | 39 +++++++++++++++++ src/calibre/gui2/actions/fetch_news.py | 17 ++++++-- src/calibre/gui2/layout.py | 49 +--------------------- src/calibre/gui2/ui.py | 11 ++--- 5 files changed, 62 insertions(+), 58 deletions(-) create mode 100644 src/calibre/gui2/actions/choose_library.py diff --git a/src/calibre/customize/builtins.py b/src/calibre/customize/builtins.py index 1e84570e54..b71e06ed38 100644 --- a/src/calibre/customize/builtins.py +++ b/src/calibre/customize/builtins.py @@ -645,6 +645,10 @@ class ActionSimilarBooks(InterfaceActionBase): name = 'Similar Books' actual_plugin = 'calibre.gui2.actions.similar_books:SimilarBooksAction' +class ActionChooseLibrary(InterfaceActionBase): + name = 'Choose Library' + actual_plugin = 'calibre.gui2.actions.choose_library:ChooseLibraryAction' + plugins += [ActionAdd, ActionFetchAnnotations, ActionGenerateCatalog, ActionConvert, ActionDelete, ActionEditMetadata, ActionView, diff --git a/src/calibre/gui2/actions/choose_library.py b/src/calibre/gui2/actions/choose_library.py new file mode 100644 index 0000000000..3e5ddd163f --- /dev/null +++ b/src/calibre/gui2/actions/choose_library.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai + +__license__ = 'GPL v3' +__copyright__ = '2010, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +from calibre.gui2.actions import InterfaceAction + +class ChooseLibraryAction(InterfaceAction): + + name = 'Choose Library' + action_spec = (_('%d books')%0, 'lt.png', + _('Choose calibre library to work with'), None) + + def genesis(self): + pass + + def location_selected(self, loc): + enabled = loc == 'library' + self.qaction.setEnabled(enabled) + self.qaction.triggered.connect(self.choose_library) + + def count_changed(self, new_count): + text = self.action_spec[0]%new_count + a = self.qaction + a.setText(text) + tooltip = self.action_spec[2] + '\n\n' + text + a.setToolTip(tooltip) + a.setStatusTip(tooltip) + a.setWhatsThis(tooltip) + + def choose_library(self, *args): + from calibre.gui2.dialogs.choose_library import ChooseLibrary + db = self.gui.library_view.model().db + c = ChooseLibrary(db, self.gui.library_moved, self.gui) + c.exec_() + + diff --git a/src/calibre/gui2/actions/fetch_news.py b/src/calibre/gui2/actions/fetch_news.py index a63ac6b4a3..fbdbb3fd85 100644 --- a/src/calibre/gui2/actions/fetch_news.py +++ b/src/calibre/gui2/actions/fetch_news.py @@ -5,6 +5,8 @@ __license__ = 'GPL v3' __copyright__ = '2010, Kovid Goyal ' __docformat__ = 'restructuredtext en' +from PyQt4.Qt import Qt + from calibre.gui2 import Dispatcher from calibre.gui2.tools import fetch_scheduled_recipe from calibre.utils.config import dynamic @@ -22,10 +24,19 @@ class FetchNewsAction(InterfaceAction): def genesis(self): self.conversion_jobs = {} - def connect_scheduler(self, scheduler): - self.qaction.setMenu(scheduler.news_menu) + def init_scheduler(self, db): + from calibre.gui2.dialogs.scheduler import Scheduler + self.scheduler = Scheduler(self.gui, db) + self.scheduler.start_recipe_fetch.connect(self.download_scheduled_recipe, type=Qt.QueuedConnection) + self.qaction.setMenu(self.scheduler.news_menu) self.qaction.triggered.connect( - scheduler.show_dialog) + self.scheduler.show_dialog) + self.database_changed = self.scheduler.database_changed + + def connect_scheduler(self): + self.scheduler.delete_old_news.connect( + self.gui.library_view.model().delete_books_by_id, + type=Qt.QueuedConnection) def download_scheduled_recipe(self, arg): func, args, desc, fmt, temp_files = \ diff --git a/src/calibre/gui2/layout.py b/src/calibre/gui2/layout.py index aaf94f7585..4b99f2fbaa 100644 --- a/src/calibre/gui2/layout.py +++ b/src/calibre/gui2/layout.py @@ -19,7 +19,6 @@ from calibre.gui2.throbber import ThrobbingButton from calibre.gui2 import config, gprefs from calibre.gui2.widgets import ComboBoxWithHelp from calibre import human_readable -from calibre.gui2.dialogs.scheduler import Scheduler @@ -279,11 +278,6 @@ class ToolBar(QToolBar): # {{{ self.choose_action.setVisible(not showing_device) - def count_changed(self, new_count): - text = _('%d books')%new_count - a = self.choose_action - a.setText(text) - a.setToolTip(_('Choose calibre library to work with') + '\n\n' + text) def resizeEvent(self, ev): QToolBar.resizeEvent(self, ev) @@ -322,61 +316,20 @@ class MainWindowMixin(object): self.donate_button = ThrobbingButton(self.centralwidget) self.location_manager = LocationManager(self) - self.init_scheduler(db) - all_actions = self.setup_actions() + self.iactions['Fetch News'].init_scheduler(db) self.search_bar = SearchBar(self) self.tool_bar = ToolBar(all_actions, self.donate_button, self.location_manager, self) self.addToolBar(Qt.TopToolBarArea, self.tool_bar) - self.tool_bar.choose_action.triggered.connect(self.choose_library) l = self.centralwidget.layout() l.addWidget(self.search_bar) - def init_scheduler(self, db): - self.scheduler = Scheduler(self, db) - self.scheduler.start_recipe_fetch.connect( - self.iactions['Fetch News'].download_scheduled_recipe, type=Qt.QueuedConnection) - self.iactions['Fetch News'].connect_scheduler(self.scheduler) def read_toolbar_settings(self): pass - def choose_library(self, *args): - from calibre.gui2.dialogs.choose_library import ChooseLibrary - db = self.library_view.model().db - c = ChooseLibrary(db, self.library_moved, self) - c.exec_() - - def setup_actions(self): # {{{ - all_actions = [] - - def ac(normal_order, device_order, separator_before, - name, text, icon, shortcut=None, tooltip=None): - action = Action(QIcon(I(icon)), text, self) - action.normal_order = normal_order - action.device_order = device_order - action.separator_before = separator_before - action.action_name = name - text = tooltip if tooltip else text - action.setToolTip(text) - action.setStatusTip(text) - action.setWhatsThis(text) - action.setAutoRepeat(False) - action.setObjectName('action_'+name) - if shortcut: - action.setShortcut(shortcut) - setattr(self, 'action_'+name, action) - all_actions.append(action) - - ac(5, 5, 3, 'choose_library', _('%d books')%0, 'lt.png', - tooltip=_('Choose calibre library to work with')) - - - - return all_actions - # }}} diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index 0fb52ad7b9..266023bfaa 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -204,9 +204,8 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ if self.system_tray_icon.isVisible() and opts.start_in_tray: self.hide_windows() - for t in (self.tool_bar, ): - self.library_view.model().count_changed_signal.connect \ - (t.count_changed) + self.library_view.model().count_changed_signal.connect( + self.iactions['Choose Library'].count_changed) if not gprefs.get('quick_start_guide_added', False): from calibre.ebooks.metadata import MetaInformation mi = MetaInformation(_('Calibre Quick Start Guide'), ['John Schember']) @@ -250,9 +249,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ self.finalize_layout() self.donate_button.start_animation() - self.scheduler.delete_old_news.connect( - self.library_view.model().delete_books_by_id, - type=Qt.QueuedConnection) + self.iactions['Fetch News'].connect_scheduler() def start_content_server(self): from calibre.library.server.main import start_threaded_server @@ -368,7 +365,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ self.saved_search.clear_to_help() self.book_details.reset_info() self.library_view.model().count_changed() - self.scheduler.database_changed(db) + self.iactions['Fetch News'].database_changed(db) prefs['library_path'] = self.library_path From d605d6b340732fdd902a9b68e00efc96653ac546 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 12 Aug 2010 23:54:15 -0600 Subject: [PATCH 18/28] ... --- src/calibre/gui2/actions/preferences.py | 1 - src/calibre/gui2/ui.py | 1 - 2 files changed, 2 deletions(-) diff --git a/src/calibre/gui2/actions/preferences.py b/src/calibre/gui2/actions/preferences.py index b33c165316..d047e51dac 100644 --- a/src/calibre/gui2/actions/preferences.py +++ b/src/calibre/gui2/actions/preferences.py @@ -49,7 +49,6 @@ class PreferencesAction(InterfaceAction): self.gui.content_server.state_callback(self.gui.content_server.is_running) if d.result() == d.Accepted: - self.gui.read_toolbar_settings() self.gui.search.search_as_you_type(config['search_as_you_type']) self.gui.tags_view.set_new_model() # in case columns changed self.gui.iactions['Save To Disk'].reread_prefs() diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index 266023bfaa..3b8040db94 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -439,7 +439,6 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ geometry = config['main_window_geometry'] if geometry is not None: self.restoreGeometry(geometry) - self.read_toolbar_settings() self.read_layout_settings() def write_settings(self): From e121e77b63d91317265d90501114f6ce0336c75e Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 12 Aug 2010 23:54:34 -0600 Subject: [PATCH 19/28] ... --- src/calibre/gui2/layout.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/calibre/gui2/layout.py b/src/calibre/gui2/layout.py index 4b99f2fbaa..c47e50faab 100644 --- a/src/calibre/gui2/layout.py +++ b/src/calibre/gui2/layout.py @@ -327,8 +327,6 @@ class MainWindowMixin(object): l.addWidget(self.search_bar) - def read_toolbar_settings(self): - pass From 9e10b0b71c074595cccae905cd08cc186c043cd9 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 13 Aug 2010 00:03:29 -0600 Subject: [PATCH 20/28] ... --- src/calibre/gui2/layout.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/calibre/gui2/layout.py b/src/calibre/gui2/layout.py index c47e50faab..ffd8bfe4ea 100644 --- a/src/calibre/gui2/layout.py +++ b/src/calibre/gui2/layout.py @@ -8,7 +8,7 @@ __docformat__ = 'restructuredtext en' from operator import attrgetter from functools import partial -from PyQt4.Qt import QIcon, Qt, QWidget, QAction, QToolBar, QSize, \ +from PyQt4.Qt import QIcon, Qt, QWidget, QToolBar, QSize, \ pyqtSignal, QToolButton, \ QObject, QVBoxLayout, QSizePolicy, QLabel, QHBoxLayout, QActionGroup, \ QMenu @@ -201,7 +201,7 @@ class SearchBar(QWidget): # {{{ class ToolBar(QToolBar): # {{{ - def __init__(self, actions, donate, location_manager, parent=None): + def __init__(self, donate, location_manager, parent): QToolBar.__init__(self, parent) self.setContextMenuPolicy(Qt.PreventContextMenu) self.setMovable(False) @@ -212,7 +212,6 @@ class ToolBar(QToolBar): # {{{ self.donate = donate self.apply_settings() - self.all_actions = actions self.location_manager = location_manager self.location_manager.locations_changed.connect(self.build_bar) self.d_widget = QWidget() @@ -296,9 +295,6 @@ class ToolBar(QToolBar): # {{{ # }}} -class Action(QAction): - pass - class MainWindowMixin(object): def __init__(self, db): @@ -319,7 +315,7 @@ class MainWindowMixin(object): self.iactions['Fetch News'].init_scheduler(db) self.search_bar = SearchBar(self) - self.tool_bar = ToolBar(all_actions, self.donate_button, + self.tool_bar = ToolBar(self.donate_button, self.location_manager, self) self.addToolBar(Qt.TopToolBarArea, self.tool_bar) From 78f14b550014a36e602c0ddf91c6c04d101da574 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 13 Aug 2010 14:06:21 -0600 Subject: [PATCH 21/28] IGN:Tag release --- Changelog.yaml | 2 +- resources/recipes/esquire.recipe | 7 +- src/calibre/translations/calibre.pot | 5723 +++++++++++++------------- 3 files changed, 2890 insertions(+), 2842 deletions(-) diff --git a/Changelog.yaml b/Changelog.yaml index 46d4f8ef9b..a08418e15c 100644 --- a/Changelog.yaml +++ b/Changelog.yaml @@ -23,7 +23,7 @@ - title: "Allow editing of tweaks via Preferences->Advanced" - - title: "Add button to manage authors dialog to automatically reset all author sort values" + - title: "Add button to the manage authors dialog to automatically reset all author sort values" bug fixes: - title: "Fix regression in 0.7.13 that broke changing libraries" diff --git a/resources/recipes/esquire.recipe b/resources/recipes/esquire.recipe index d9c189b473..f559f5a6cf 100644 --- a/resources/recipes/esquire.recipe +++ b/resources/recipes/esquire.recipe @@ -5,7 +5,6 @@ __copyright__ = '2009-2010, Darko Miletic ' www.esquire.com ''' -from calibre import strftime from calibre.web.feeds.news import BasicNewsRecipe class Esquire(BasicNewsRecipe): @@ -20,8 +19,8 @@ class Esquire(BasicNewsRecipe): encoding = 'cp1250' use_embedded_content = False language = 'en' - publication_type = 'magazine' - masthead_url = 'http://www.esquire.com/cm/shared/site_images/print_this/esquire_logo.gif' + publication_type = 'magazine' + masthead_url = 'http://www.esquire.com/cm/shared/site_images/print_this/esquire_logo.gif' conversion_options = { 'comment' : description @@ -33,7 +32,7 @@ class Esquire(BasicNewsRecipe): keep_only_tags = [dict(name='div', attrs={'id':['article_header','article_content']})] remove_tags = [dict(name=['object','link','embed','iframe','base'])] remove_attributes = ['width','height'] - + feeds = [ (u'Style' , u'http://www.esquire.com/style/rss/' ) ,(u'Women' , u'http://www.esquire.com/women/rss/' ) diff --git a/src/calibre/translations/calibre.pot b/src/calibre/translations/calibre.pot index 9b967343b4..cf7aa6f652 100644 --- a/src/calibre/translations/calibre.pot +++ b/src/calibre/translations/calibre.pot @@ -4,9 +4,9 @@ # msgid "" msgstr "" -"Project-Id-Version: calibre 0.7.13\n" -"POT-Creation-Date: 2010-08-10 18:33+MDT\n" -"PO-Revision-Date: 2010-08-10 18:33+MDT\n" +"Project-Id-Version: calibre 0.7.14\n" +"POT-Creation-Date: 2010-08-13 13:27+MDT\n" +"PO-Revision-Date: 2010-08-13 13:27+MDT\n" "Last-Translator: Automatically generated\n" "Language-Team: LANGUAGE\n" "MIME-Version: 1.0\n" @@ -15,371 +15,371 @@ msgstr "" "Generated-By: pygettext.py 1.5\n" -#: /home/kovid/work/trunk/src/calibre/customize/__init__.py:43 +#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:43 msgid "Does absolutely nothing" msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/__init__.py:46 -#: /home/kovid/work/trunk/src/calibre/devices/jetbook/driver.py:72 -#: /home/kovid/work/trunk/src/calibre/devices/kindle/driver.py:75 -#: /home/kovid/work/trunk/src/calibre/devices/nook/driver.py:70 -#: /home/kovid/work/trunk/src/calibre/devices/nook/driver.py:71 -#: /home/kovid/work/trunk/src/calibre/devices/prs500/books.py:267 -#: /home/kovid/work/trunk/src/calibre/devices/prs505/sony_cache.py:506 -#: /home/kovid/work/trunk/src/calibre/devices/usbms/driver.py:405 -#: /home/kovid/work/trunk/src/calibre/ebooks/chm/input.py:97 -#: /home/kovid/work/trunk/src/calibre/ebooks/chm/input.py:100 -#: /home/kovid/work/trunk/src/calibre/ebooks/chm/metadata.py:56 -#: /home/kovid/work/trunk/src/calibre/ebooks/comic/input.py:402 -#: /home/kovid/work/trunk/src/calibre/ebooks/fb2/input.py:70 -#: /home/kovid/work/trunk/src/calibre/ebooks/fb2/input.py:72 -#: /home/kovid/work/trunk/src/calibre/ebooks/html/input.py:335 -#: /home/kovid/work/trunk/src/calibre/ebooks/html/input.py:338 -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/html/convert_from.py:1894 -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/html/convert_from.py:1896 -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/output.py:24 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/__init__.py:236 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/__init__.py:279 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/__init__.py:282 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/__init__.py:398 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/book/base.py:20 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/book/base.py:21 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/ereader.py:36 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/ereader.py:61 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/fb2.py:46 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/fetch.py:332 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/meta.py:36 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/meta.py:64 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/meta.py:66 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/meta.py:123 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/meta.py:125 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/opf2.py:945 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/opf2.py:1057 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/pdb.py:39 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/pdf.py:28 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/pml.py:23 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/pml.py:49 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/txt.py:14 -#: /home/kovid/work/trunk/src/calibre/ebooks/mobi/reader.py:39 -#: /home/kovid/work/trunk/src/calibre/ebooks/mobi/reader.py:65 -#: /home/kovid/work/trunk/src/calibre/ebooks/mobi/reader.py:78 -#: /home/kovid/work/trunk/src/calibre/ebooks/mobi/reader.py:119 -#: /home/kovid/work/trunk/src/calibre/ebooks/mobi/reader.py:153 -#: /home/kovid/work/trunk/src/calibre/ebooks/mobi/reader.py:611 -#: /home/kovid/work/trunk/src/calibre/ebooks/mobi/reader.py:817 -#: /home/kovid/work/trunk/src/calibre/ebooks/mobi/reader.py:819 -#: /home/kovid/work/trunk/src/calibre/ebooks/odt/input.py:49 -#: /home/kovid/work/trunk/src/calibre/ebooks/odt/input.py:51 -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/base.py:911 -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/base.py:916 -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/base.py:982 -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/reader.py:137 -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/reader.py:139 -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/transforms/jacket.py:108 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdb/ereader/writer.py:173 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdb/ereader/writer.py:174 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdb/input.py:39 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdb/palmdoc/writer.py:29 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdb/ztxt/writer.py:27 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/crop.py:82 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/crop.py:83 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/decrypt.py:73 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/decrypt.py:74 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/encrypt.py:63 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/encrypt.py:64 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/info.py:52 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/merge.py:65 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/merge.py:66 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/reverse.py:63 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/reverse.py:64 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/rotate.py:62 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/rotate.py:63 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/split.py:81 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/split.py:82 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/writer.py:97 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/writer.py:98 -#: /home/kovid/work/trunk/src/calibre/ebooks/rtf/input.py:234 -#: /home/kovid/work/trunk/src/calibre/ebooks/rtf/input.py:236 -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:287 -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:294 -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:826 -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:829 -#: /home/kovid/work/trunk/src/calibre/gui2/add.py:172 -#: /home/kovid/work/trunk/src/calibre/gui2/add.py:179 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/__init__.py:22 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata.py:110 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata.py:135 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata.py:137 -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:868 -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:877 -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:1162 -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:1165 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/comicconf.py:47 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata.py:120 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata.py:155 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:512 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler.py:173 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:362 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:382 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:882 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:1060 -#: /home/kovid/work/trunk/src/calibre/gui2/metadata.py:91 -#: /home/kovid/work/trunk/src/calibre/gui2/metadata.py:96 -#: /home/kovid/work/trunk/src/calibre/gui2/viewer/main.py:185 -#: /home/kovid/work/trunk/src/calibre/library/cli.py:213 -#: /home/kovid/work/trunk/src/calibre/library/database.py:913 -#: /home/kovid/work/trunk/src/calibre/library/database2.py:358 -#: /home/kovid/work/trunk/src/calibre/library/database2.py:370 -#: /home/kovid/work/trunk/src/calibre/library/database2.py:979 -#: /home/kovid/work/trunk/src/calibre/library/database2.py:1048 -#: /home/kovid/work/trunk/src/calibre/library/database2.py:1649 -#: /home/kovid/work/trunk/src/calibre/library/database2.py:1651 -#: /home/kovid/work/trunk/src/calibre/library/database2.py:1773 -#: /home/kovid/work/trunk/src/calibre/library/server/mobile.py:199 -#: /home/kovid/work/trunk/src/calibre/library/server/opds.py:134 -#: /home/kovid/work/trunk/src/calibre/library/server/opds.py:137 -#: /home/kovid/work/trunk/src/calibre/library/server/xml.py:68 -#: /home/kovid/work/trunk/src/calibre/utils/localization.py:117 -#: /home/kovid/work/trunk/src/calibre/utils/podofo/__init__.py:46 -#: /home/kovid/work/trunk/src/calibre/utils/podofo/__init__.py:64 -#: /home/kovid/work/trunk/src/calibre/utils/podofo/__init__.py:78 -#: /home/kovid/work/trunk/src/calibre/web/feeds/recipes/collection.py:47 -#: /home/kovid/work/trunk/src/calibre/web/feeds/recipes/collection.py:50 +#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:46 +#: /home/kovid/work/calibre/src/calibre/devices/jetbook/driver.py:72 +#: /home/kovid/work/calibre/src/calibre/devices/kindle/driver.py:75 +#: /home/kovid/work/calibre/src/calibre/devices/nook/driver.py:70 +#: /home/kovid/work/calibre/src/calibre/devices/nook/driver.py:71 +#: /home/kovid/work/calibre/src/calibre/devices/prs500/books.py:267 +#: /home/kovid/work/calibre/src/calibre/devices/prs505/sony_cache.py:506 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:405 +#: /home/kovid/work/calibre/src/calibre/ebooks/chm/input.py:97 +#: /home/kovid/work/calibre/src/calibre/ebooks/chm/input.py:100 +#: /home/kovid/work/calibre/src/calibre/ebooks/chm/metadata.py:56 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:402 +#: /home/kovid/work/calibre/src/calibre/ebooks/fb2/input.py:70 +#: /home/kovid/work/calibre/src/calibre/ebooks/fb2/input.py:72 +#: /home/kovid/work/calibre/src/calibre/ebooks/html/input.py:335 +#: /home/kovid/work/calibre/src/calibre/ebooks/html/input.py:338 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/html/convert_from.py:1894 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/html/convert_from.py:1896 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/output.py:24 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/__init__.py:236 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/__init__.py:279 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/__init__.py:282 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/__init__.py:398 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/book/base.py:20 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/book/base.py:21 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/ereader.py:36 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/ereader.py:61 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/fb2.py:46 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/fetch.py:333 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/meta.py:36 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/meta.py:64 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/meta.py:66 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/meta.py:123 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/meta.py:125 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/opf2.py:945 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/opf2.py:1057 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/pdb.py:39 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/pdf.py:28 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/pml.py:23 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/pml.py:49 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/txt.py:14 +#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:39 +#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:65 +#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:78 +#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:119 +#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:153 +#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:611 +#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:817 +#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:819 +#: /home/kovid/work/calibre/src/calibre/ebooks/odt/input.py:49 +#: /home/kovid/work/calibre/src/calibre/ebooks/odt/input.py:51 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:911 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:916 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:982 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/reader.py:137 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/reader.py:139 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/transforms/jacket.py:108 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/ereader/writer.py:173 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/ereader/writer.py:174 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/input.py:39 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/palmdoc/writer.py:29 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/ztxt/writer.py:27 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:82 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:83 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/decrypt.py:73 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/decrypt.py:74 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/encrypt.py:63 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/encrypt.py:64 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/info.py:52 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/merge.py:65 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/merge.py:66 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/reverse.py:63 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/reverse.py:64 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/rotate.py:62 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/rotate.py:63 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/split.py:81 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/split.py:82 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/writer.py:97 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/writer.py:98 +#: /home/kovid/work/calibre/src/calibre/ebooks/rtf/input.py:234 +#: /home/kovid/work/calibre/src/calibre/ebooks/rtf/input.py:236 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:287 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:294 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:850 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:853 +#: /home/kovid/work/calibre/src/calibre/gui2/add.py:172 +#: /home/kovid/work/calibre/src/calibre/gui2/add.py:179 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/__init__.py:22 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata.py:110 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata.py:135 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata.py:137 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:868 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:877 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:1162 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:1165 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comicconf.py:47 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:120 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:155 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:512 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:173 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:362 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:382 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:882 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1060 +#: /home/kovid/work/calibre/src/calibre/gui2/metadata.py:91 +#: /home/kovid/work/calibre/src/calibre/gui2/metadata.py:96 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:186 +#: /home/kovid/work/calibre/src/calibre/library/cli.py:213 +#: /home/kovid/work/calibre/src/calibre/library/database.py:913 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:358 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:370 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:1001 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:1070 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:1671 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:1673 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:1796 +#: /home/kovid/work/calibre/src/calibre/library/server/mobile.py:199 +#: /home/kovid/work/calibre/src/calibre/library/server/opds.py:134 +#: /home/kovid/work/calibre/src/calibre/library/server/opds.py:137 +#: /home/kovid/work/calibre/src/calibre/library/server/xml.py:68 +#: /home/kovid/work/calibre/src/calibre/utils/localization.py:117 +#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:46 +#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:64 +#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:78 +#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/collection.py:47 +#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/collection.py:50 msgid "Unknown" msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/__init__.py:64 +#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:64 msgid "Base" msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/__init__.py:172 +#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:172 msgid "File type" msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/__init__.py:206 +#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:206 msgid "Metadata reader" msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/__init__.py:235 +#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:235 msgid "Metadata writer" msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/__init__.py:263 +#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:263 msgid "Catalog generator" msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:16 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:16 msgid "Follow all local links in an HTML file and create a ZIP file containing all linked files. This plugin is run every time you add an HTML file to the library." msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:52 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:52 msgid "Character encoding for the input HTML files. Common choices include: cp1252, latin1, iso-8859-1 and utf-8." msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:59 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:59 msgid "Create a PMLZ archive containing the PML file and all images in the directory pmlname_img or images. This plugin is run every time you add a PML file to the library." msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:93 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:93 msgid "Extract cover from comic files" msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:120 -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:131 -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:143 -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:153 -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:163 -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:174 -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:184 -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:194 -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:204 -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:214 -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:224 -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:235 -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:246 -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:258 -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:279 -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:290 -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:300 -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:310 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:120 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:131 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:143 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:153 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:163 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:174 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:184 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:194 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:204 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:214 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:224 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:235 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:246 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:258 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:279 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:290 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:300 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:310 msgid "Read metadata from %s files" msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:269 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:269 msgid "Read metadata from ebooks in RAR archives" msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:321 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:321 msgid "Read metadata from ebooks in ZIP archives" msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:334 -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:344 -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:354 -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:376 -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:387 -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:397 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:334 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:344 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:354 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:376 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:387 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:397 msgid "Set metadata in %s files" msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/builtins.py:365 +#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:365 msgid "Set metadata from %s files" msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/conversion.py:102 +#: /home/kovid/work/calibre/src/calibre/customize/conversion.py:102 msgid "Conversion Input" msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/conversion.py:125 +#: /home/kovid/work/calibre/src/calibre/customize/conversion.py:125 msgid "Specify the character encoding of the input document. If set this option will override any encoding declared by the document itself. Particularly useful for documents that do not declare an encoding or that have erroneous encoding declarations." msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/conversion.py:237 +#: /home/kovid/work/calibre/src/calibre/customize/conversion.py:237 msgid "Conversion Output" msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/conversion.py:251 +#: /home/kovid/work/calibre/src/calibre/customize/conversion.py:251 msgid "If specified, the output plugin will try to create output that is as human readable as possible. May not have any effect for some output plugins." msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:45 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:45 msgid "Input profile" msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:49 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:49 msgid "This profile tries to provide sane defaults and is useful if you know nothing about the input document." msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:57 -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:414 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:57 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:414 msgid "This profile is intended for the SONY PRS line. The 500/505/600/700 etc." msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:69 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:69 msgid "This profile is intended for the SONY PRS 300." msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:78 -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:449 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:78 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:449 msgid "This profile is intended for the SONY PRS-900." msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:86 -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:479 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:86 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:479 msgid "This profile is intended for the Microsoft Reader." msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:97 -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:490 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:97 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:490 msgid "This profile is intended for the Mobipocket books." msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:110 -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:503 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:110 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:503 msgid "This profile is intended for the Hanlin V3 and its clones." msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:122 -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:515 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:122 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:515 msgid "This profile is intended for the Hanlin V5 and its clones." msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:132 -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:523 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:132 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:523 msgid "This profile is intended for the Cybook G3." msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:145 -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:536 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:145 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:536 msgid "This profile is intended for the Cybook Opus." msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:157 -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:547 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:157 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:547 msgid "This profile is intended for the Amazon Kindle." msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:169 -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:584 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:169 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:584 msgid "This profile is intended for the Irex Illiad." msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:181 -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:597 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:181 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:597 msgid "This profile is intended for the IRex Digital Reader 1000." msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:194 -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:611 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:194 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:611 msgid "This profile is intended for the IRex Digital Reader 800." msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:206 -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:625 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:206 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:625 msgid "This profile is intended for the B&N Nook." msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:228 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:228 msgid "Output profile" msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:232 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:232 msgid "This profile tries to provide sane defaults and is useful if you want to produce a document intended to be read at a computer or on a range of devices." msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:259 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:259 msgid "Intended for the iPad and similar devices with a resolution of 768x1024" msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:427 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:427 msgid "This profile is intended for the Kobo Reader." msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:440 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:440 msgid "This profile is intended for the SONY PRS-300." msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:458 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:458 msgid "This profile is intended for the 5-inch JetBook." msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:467 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:467 msgid "This profile is intended for the SONY PRS line. The 500/505/700 etc, in landscape mode. Mainly useful for comics." msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/profiles.py:566 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:566 msgid "This profile is intended for the Amazon Kindle DX." msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/ui.py:33 +#: /home/kovid/work/calibre/src/calibre/customize/ui.py:33 msgid "Installed plugins" msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/ui.py:34 +#: /home/kovid/work/calibre/src/calibre/customize/ui.py:34 msgid "Mapping for filetype plugins" msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/ui.py:35 +#: /home/kovid/work/calibre/src/calibre/customize/ui.py:35 msgid "Local plugin customization" msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/ui.py:36 +#: /home/kovid/work/calibre/src/calibre/customize/ui.py:36 msgid "Disabled plugins" msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/ui.py:37 +#: /home/kovid/work/calibre/src/calibre/customize/ui.py:37 msgid "Enabled plugins" msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/ui.py:85 +#: /home/kovid/work/calibre/src/calibre/customize/ui.py:85 msgid "No valid plugin found in " msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/ui.py:478 +#: /home/kovid/work/calibre/src/calibre/customize/ui.py:478 msgid "Initialization of plugin %s failed with traceback:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/ui.py:511 +#: /home/kovid/work/calibre/src/calibre/customize/ui.py:511 msgid "" " %prog options\n" "\n" @@ -387,608 +387,608 @@ msgid "" " " msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/ui.py:517 +#: /home/kovid/work/calibre/src/calibre/customize/ui.py:517 msgid "Add a plugin by specifying the path to the zip file containing it." msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/ui.py:519 +#: /home/kovid/work/calibre/src/calibre/customize/ui.py:519 msgid "Remove a custom plugin by name. Has no effect on builtin plugins" msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/ui.py:521 +#: /home/kovid/work/calibre/src/calibre/customize/ui.py:521 msgid "Customize plugin. Specify name of plugin and customization string separated by a comma." msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/ui.py:523 +#: /home/kovid/work/calibre/src/calibre/customize/ui.py:523 msgid "List all installed plugins" msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/ui.py:525 +#: /home/kovid/work/calibre/src/calibre/customize/ui.py:525 msgid "Enable the named plugin" msgstr "" -#: /home/kovid/work/trunk/src/calibre/customize/ui.py:527 +#: /home/kovid/work/calibre/src/calibre/customize/ui.py:527 msgid "Disable the named plugin" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/android/driver.py:13 +#: /home/kovid/work/calibre/src/calibre/devices/android/driver.py:13 msgid "Communicate with Android phones." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/android/driver.py:48 +#: /home/kovid/work/calibre/src/calibre/devices/android/driver.py:50 msgid "Comma separated list of directories to send e-books to on the device. The first one that exists will be used" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/android/driver.py:90 +#: /home/kovid/work/calibre/src/calibre/devices/android/driver.py:92 msgid "Communicate with S60 phones." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/apple/driver.py:87 +#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:87 msgid "Communicate with iTunes/iBooks." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/apple/driver.py:93 +#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:93 msgid "Apple device detected, launching iTunes, please wait ..." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/apple/driver.py:246 -#: /home/kovid/work/trunk/src/calibre/devices/apple/driver.py:249 +#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:246 +#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:249 msgid "Updating device metadata listing..." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/apple/driver.py:323 -#: /home/kovid/work/trunk/src/calibre/devices/apple/driver.py:362 -#: /home/kovid/work/trunk/src/calibre/devices/apple/driver.py:921 -#: /home/kovid/work/trunk/src/calibre/devices/apple/driver.py:957 -#: /home/kovid/work/trunk/src/calibre/devices/apple/driver.py:2822 -#: /home/kovid/work/trunk/src/calibre/devices/apple/driver.py:2861 +#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:323 +#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:362 +#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:921 +#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:957 +#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:2822 +#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:2861 msgid "%d of %d" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/apple/driver.py:369 -#: /home/kovid/work/trunk/src/calibre/devices/apple/driver.py:962 -#: /home/kovid/work/trunk/src/calibre/devices/apple/driver.py:2867 +#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:369 +#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:962 +#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:2867 msgid "finished" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/apple/driver.py:544 +#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:544 msgid "Use Series as Category in iTunes/iBooks" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/apple/driver.py:546 +#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:546 msgid "Cache covers from iTunes/iBooks" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/apple/driver.py:558 +#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:558 msgid "" "Some books not found in iTunes database.\n" "Delete using the iBooks app.\n" "Click 'Show Details' for a list." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/apple/driver.py:886 +#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:886 msgid "" "Some cover art could not be converted.\n" "Click 'Show Details' for a list." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/apple/driver.py:2491 -#: /home/kovid/work/trunk/src/calibre/devices/usbms/device.py:817 -#: /home/kovid/work/trunk/src/calibre/devices/usbms/device.py:823 -#: /home/kovid/work/trunk/src/calibre/devices/usbms/device.py:851 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler.py:244 -#: /home/kovid/work/trunk/src/calibre/library/database2.py:187 -#: /home/kovid/work/trunk/src/calibre/library/database2.py:200 -#: /home/kovid/work/trunk/src/calibre/library/database2.py:1533 -#: /home/kovid/work/trunk/src/calibre/library/field_metadata.py:132 +#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:2491 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:817 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:823 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:851 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:244 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:187 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:200 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:1555 +#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:132 msgid "News" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/apple/driver.py:2729 +#: /home/kovid/work/calibre/src/calibre/devices/apple/driver.py:2729 msgid "Communicate with iTunes." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/binatone/driver.py:17 +#: /home/kovid/work/calibre/src/calibre/devices/binatone/driver.py:17 msgid "Communicate with the Binatone Readme eBook reader." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/blackberry/driver.py:13 +#: /home/kovid/work/calibre/src/calibre/devices/blackberry/driver.py:13 msgid "Communicate with the Blackberry smart phone." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/blackberry/driver.py:14 -#: /home/kovid/work/trunk/src/calibre/devices/nuut2/driver.py:18 -#: /home/kovid/work/trunk/src/calibre/devices/prs500/driver.py:90 +#: /home/kovid/work/calibre/src/calibre/devices/blackberry/driver.py:14 +#: /home/kovid/work/calibre/src/calibre/devices/nuut2/driver.py:18 +#: /home/kovid/work/calibre/src/calibre/devices/prs500/driver.py:90 msgid "Kovid Goyal" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/cybook/driver.py:22 +#: /home/kovid/work/calibre/src/calibre/devices/cybook/driver.py:22 msgid "Communicate with the Cybook Gen 3 / Opus eBook reader." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/eb600/driver.py:24 +#: /home/kovid/work/calibre/src/calibre/devices/eb600/driver.py:24 msgid "Communicate with the EB600 eBook reader." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/eb600/driver.py:193 +#: /home/kovid/work/calibre/src/calibre/devices/eb600/driver.py:193 msgid "Communicate with the Astak Mentor EB600" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/eb600/driver.py:216 +#: /home/kovid/work/calibre/src/calibre/devices/eb600/driver.py:216 msgid "Communicate with the PocketBook 301 reader." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/edge/driver.py:17 +#: /home/kovid/work/calibre/src/calibre/devices/edge/driver.py:17 msgid "Entourage Edge" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/edge/driver.py:18 +#: /home/kovid/work/calibre/src/calibre/devices/edge/driver.py:18 msgid "Communicate with the Entourage Edge." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/eslick/driver.py:16 +#: /home/kovid/work/calibre/src/calibre/devices/eslick/driver.py:16 msgid "Communicate with the ESlick eBook reader." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/eslick/driver.py:49 +#: /home/kovid/work/calibre/src/calibre/devices/eslick/driver.py:49 msgid "Communicate with the Sigmatek eBook reader." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/folder_device/driver.py:16 -#: /home/kovid/work/trunk/src/calibre/devices/folder_device/driver.py:30 +#: /home/kovid/work/calibre/src/calibre/devices/folder_device/driver.py:16 +#: /home/kovid/work/calibre/src/calibre/devices/folder_device/driver.py:30 msgid "Use an arbitrary folder as a device." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/folder_device/driver.py:26 -#: /home/kovid/work/trunk/src/calibre/devices/interface.py:14 +#: /home/kovid/work/calibre/src/calibre/devices/folder_device/driver.py:26 +#: /home/kovid/work/calibre/src/calibre/devices/interface.py:14 msgid "Device Interface" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/hanlin/driver.py:19 +#: /home/kovid/work/calibre/src/calibre/devices/hanlin/driver.py:19 msgid "Communicate with Hanlin V3 eBook readers." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/hanlin/driver.py:87 +#: /home/kovid/work/calibre/src/calibre/devices/hanlin/driver.py:87 msgid "Communicate with Hanlin V5 eBook readers." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/hanlin/driver.py:106 +#: /home/kovid/work/calibre/src/calibre/devices/hanlin/driver.py:106 msgid "Communicate with the BOOX eBook reader." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/hanlin/driver.py:123 +#: /home/kovid/work/calibre/src/calibre/devices/hanlin/driver.py:123 msgid "Comma separated list of directories to send e-books to on the device. The first one that exists will be used." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/hanvon/driver.py:18 +#: /home/kovid/work/calibre/src/calibre/devices/hanvon/driver.py:18 msgid "Communicate with the Hanvon N520 eBook reader." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/hanvon/driver.py:40 +#: /home/kovid/work/calibre/src/calibre/devices/hanvon/driver.py:40 msgid "Communicate with The Book reader." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/hanvon/driver.py:52 +#: /home/kovid/work/calibre/src/calibre/devices/hanvon/driver.py:52 msgid "Communicate with the SpringDesign Alex eBook reader." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/hanvon/driver.py:68 +#: /home/kovid/work/calibre/src/calibre/devices/hanvon/driver.py:68 msgid "Communicate with the Azbooka" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/hanvon/driver.py:81 +#: /home/kovid/work/calibre/src/calibre/devices/hanvon/driver.py:81 msgid "Communicate with the Elonex EB 511 eBook reader." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/iliad/driver.py:16 +#: /home/kovid/work/calibre/src/calibre/devices/iliad/driver.py:16 msgid "Communicate with the IRex Iliad eBook reader." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/iliad/driver.py:17 -#: /home/kovid/work/trunk/src/calibre/devices/irexdr/driver.py:18 -#: /home/kovid/work/trunk/src/calibre/devices/usbms/driver.py:42 +#: /home/kovid/work/calibre/src/calibre/devices/iliad/driver.py:17 +#: /home/kovid/work/calibre/src/calibre/devices/irexdr/driver.py:18 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:42 msgid "John Schember" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/irexdr/driver.py:16 +#: /home/kovid/work/calibre/src/calibre/devices/irexdr/driver.py:16 msgid "Communicate with the IRex Digital Reader 1000 eBook reader." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/irexdr/driver.py:42 +#: /home/kovid/work/calibre/src/calibre/devices/irexdr/driver.py:42 msgid "Communicate with the IRex Digital Reader 800" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/iriver/driver.py:15 +#: /home/kovid/work/calibre/src/calibre/devices/iriver/driver.py:15 msgid "Communicate with the Iriver Story reader." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/jetbook/driver.py:20 +#: /home/kovid/work/calibre/src/calibre/devices/jetbook/driver.py:20 msgid "Communicate with the JetBook eBook reader." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/jetbook/driver.py:86 +#: /home/kovid/work/calibre/src/calibre/devices/jetbook/driver.py:86 msgid "Communicate with the MiBuk Wolder reader." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/kindle/driver.py:42 +#: /home/kovid/work/calibre/src/calibre/devices/kindle/driver.py:42 msgid "Communicate with the Kindle eBook reader." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/kindle/driver.py:169 +#: /home/kovid/work/calibre/src/calibre/devices/kindle/driver.py:169 msgid "Communicate with the Kindle 2 eBook reader." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/kindle/driver.py:210 +#: /home/kovid/work/calibre/src/calibre/devices/kindle/driver.py:210 msgid "Communicate with the Kindle DX eBook reader." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/kobo/driver.py:22 +#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:22 msgid "Communicate with the Kobo Reader" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/kobo/driver.py:53 -#: /home/kovid/work/trunk/src/calibre/devices/kobo/driver.py:56 -#: /home/kovid/work/trunk/src/calibre/devices/kobo/driver.py:59 -#: /home/kovid/work/trunk/src/calibre/devices/kobo/driver.py:161 -#: /home/kovid/work/trunk/src/calibre/devices/usbms/driver.py:68 -#: /home/kovid/work/trunk/src/calibre/devices/usbms/driver.py:71 -#: /home/kovid/work/trunk/src/calibre/devices/usbms/driver.py:74 -#: /home/kovid/work/trunk/src/calibre/devices/usbms/driver.py:136 -#: /home/kovid/work/trunk/src/calibre/devices/usbms/driver.py:143 -#: /home/kovid/work/trunk/src/calibre/devices/usbms/driver.py:166 +#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:53 +#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:56 +#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:59 +#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:161 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:68 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:71 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:74 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:136 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:143 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:166 msgid "Getting list of books on device..." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/kobo/driver.py:221 -#: /home/kovid/work/trunk/src/calibre/devices/kobo/driver.py:265 -#: /home/kovid/work/trunk/src/calibre/devices/usbms/driver.py:253 -#: /home/kovid/work/trunk/src/calibre/devices/usbms/driver.py:271 +#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:221 +#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:265 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:253 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:271 msgid "Removing books from device..." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/kobo/driver.py:269 -#: /home/kovid/work/trunk/src/calibre/devices/kobo/driver.py:276 -#: /home/kovid/work/trunk/src/calibre/devices/usbms/driver.py:278 -#: /home/kovid/work/trunk/src/calibre/devices/usbms/driver.py:283 +#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:269 +#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:276 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:278 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:283 msgid "Removing books from device metadata listing..." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/kobo/driver.py:281 -#: /home/kovid/work/trunk/src/calibre/devices/kobo/driver.py:315 -#: /home/kovid/work/trunk/src/calibre/devices/usbms/driver.py:217 -#: /home/kovid/work/trunk/src/calibre/devices/usbms/driver.py:247 +#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:281 +#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:315 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:217 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:247 msgid "Adding books to device metadata listing..." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/kobo/driver.py:366 -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:441 +#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:366 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:458 msgid "Not Implemented" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/kobo/driver.py:367 +#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:367 msgid "\".kobo\" files do not exist on the device as books instead, they are rows in the sqlite database. Currently they cannot be exported or viewed." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/misc.py:17 +#: /home/kovid/work/calibre/src/calibre/devices/misc.py:17 msgid "Communicate with the Palm Pre" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/misc.py:37 +#: /home/kovid/work/calibre/src/calibre/devices/misc.py:37 msgid "Communicate with the Booq Avant" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/misc.py:58 +#: /home/kovid/work/calibre/src/calibre/devices/misc.py:58 msgid "Communicate with the Sweex MM300" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/misc.py:78 +#: /home/kovid/work/calibre/src/calibre/devices/misc.py:78 msgid "Communicate with the Pandigital Novel" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/nokia/driver.py:17 +#: /home/kovid/work/calibre/src/calibre/devices/nokia/driver.py:17 msgid "Communicate with the Nokia 770 internet tablet." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/nokia/driver.py:40 +#: /home/kovid/work/calibre/src/calibre/devices/nokia/driver.py:40 msgid "Communicate with the Nokia 810 internet tablet." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/nokia/driver.py:74 +#: /home/kovid/work/calibre/src/calibre/devices/nokia/driver.py:74 msgid "Communicate with the Nokia E52" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/nook/driver.py:20 +#: /home/kovid/work/calibre/src/calibre/devices/nook/driver.py:20 msgid "The Nook" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/nook/driver.py:21 +#: /home/kovid/work/calibre/src/calibre/devices/nook/driver.py:21 msgid "Communicate with the Nook eBook reader." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/nuut2/driver.py:17 +#: /home/kovid/work/calibre/src/calibre/devices/nuut2/driver.py:17 msgid "Communicate with the Nuut2 eBook reader." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/prs500/driver.py:89 +#: /home/kovid/work/calibre/src/calibre/devices/prs500/driver.py:89 msgid "Communicate with the Sony PRS-500 eBook reader." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/prs505/driver.py:22 +#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:22 msgid "Communicate with all the Sony eBook readers." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/prs505/driver.py:61 +#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:61 msgid "Comma separated list of metadata fields to turn into collections on the device. Possibilities include: " msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/prs505/sony_cache.py:144 -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/transforms/structure.py:68 +#: /home/kovid/work/calibre/src/calibre/devices/prs505/sony_cache.py:144 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/transforms/structure.py:68 msgid "Unnamed" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/sne/driver.py:17 +#: /home/kovid/work/calibre/src/calibre/devices/sne/driver.py:17 msgid "Communicate with the Samsung SNE eBook reader." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/teclast/driver.py:11 -msgid "Communicate with the Teclast K3 reader." +#: /home/kovid/work/calibre/src/calibre/devices/teclast/driver.py:11 +msgid "Communicate with the Teclast K3/K5 reader." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/teclast/driver.py:37 +#: /home/kovid/work/calibre/src/calibre/devices/teclast/driver.py:36 msgid "Communicate with the Newsmy reader." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/teclast/driver.py:49 +#: /home/kovid/work/calibre/src/calibre/devices/teclast/driver.py:48 msgid "Communicate with the iPapyrus reader." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/usbms/device.py:255 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:255 msgid "Unable to detect the %s disk drive. Try rebooting." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/usbms/device.py:435 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:435 msgid "Unable to detect the %s mount point. Try rebooting." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/usbms/device.py:500 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:500 msgid "Unable to detect the %s disk drive." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/usbms/device.py:593 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:593 msgid "Could not find mount helper: %s." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/usbms/device.py:605 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:605 msgid "Unable to detect the %s disk drive. Your kernel is probably exporting a deprecated version of SYSFS." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/usbms/device.py:613 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:613 msgid "Unable to mount main memory (Error code: %d)" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/usbms/device.py:750 -#: /home/kovid/work/trunk/src/calibre/devices/usbms/device.py:752 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:750 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:752 msgid "The reader has no storage card in this slot." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/usbms/device.py:754 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:754 msgid "Selected slot: %s is not supported." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/usbms/device.py:783 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:783 msgid "There is insufficient free space in main memory" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/usbms/device.py:785 -#: /home/kovid/work/trunk/src/calibre/devices/usbms/device.py:787 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:785 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:787 msgid "There is insufficient free space on the storage card" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/usbms/deviceconfig.py:12 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/deviceconfig.py:12 msgid "Configure Device" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/usbms/deviceconfig.py:37 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/deviceconfig.py:37 msgid "settings for device drivers" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/usbms/deviceconfig.py:39 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/deviceconfig.py:39 msgid "Ordered list of formats the device will accept" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/usbms/deviceconfig.py:41 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/deviceconfig.py:41 msgid "Place files in sub directories if the device supports them" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/usbms/deviceconfig.py:43 -#: /home/kovid/work/trunk/src/calibre/gui2/device_drivers/configwidget_ui.py:81 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/deviceconfig.py:43 +#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/configwidget_ui.py:81 msgid "Read metadata from files on device" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/usbms/deviceconfig.py:45 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/deviceconfig.py:45 msgid "Use author sort instead of author" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/usbms/deviceconfig.py:47 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/deviceconfig.py:47 msgid "Template to control how books are saved" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/usbms/deviceconfig.py:50 -#: /home/kovid/work/trunk/src/calibre/gui2/device_drivers/configwidget_ui.py:84 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/deviceconfig.py:50 +#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/configwidget_ui.py:84 msgid "Extra customization" msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/usbms/driver.py:41 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:41 msgid "Communicate with an eBook reader." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/usbms/driver.py:57 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:57 msgid "Get device information..." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/usbms/driver.py:194 -#: /home/kovid/work/trunk/src/calibre/devices/usbms/driver.py:196 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:194 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:196 msgid "Transferring books to device..." msgstr "" -#: /home/kovid/work/trunk/src/calibre/devices/usbms/driver.py:314 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:314 msgid "Sending metadata to device..." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/chm/reader.py:41 +#: /home/kovid/work/calibre/src/calibre/ebooks/chm/reader.py:41 msgid "%prog [options] mybook.chm" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/chm/reader.py:42 +#: /home/kovid/work/calibre/src/calibre/ebooks/chm/reader.py:42 msgid "Output directory. Defaults to current directory" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/chm/reader.py:45 -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/meta.py:589 +#: /home/kovid/work/calibre/src/calibre/ebooks/chm/reader.py:45 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/meta.py:589 msgid "Set the book title" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/chm/reader.py:47 -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/meta.py:591 +#: /home/kovid/work/calibre/src/calibre/ebooks/chm/reader.py:47 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/meta.py:591 msgid "Set sort key for the title" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/chm/reader.py:49 -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/meta.py:593 +#: /home/kovid/work/calibre/src/calibre/ebooks/chm/reader.py:49 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/meta.py:593 msgid "Set the author" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/chm/reader.py:51 -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/meta.py:595 +#: /home/kovid/work/calibre/src/calibre/ebooks/chm/reader.py:51 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/meta.py:595 msgid "Set sort key for the author" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/chm/reader.py:53 -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/meta.py:597 +#: /home/kovid/work/calibre/src/calibre/ebooks/chm/reader.py:53 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/meta.py:597 msgid "The category this book belongs to. E.g.: History" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/chm/reader.py:56 -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/meta.py:600 +#: /home/kovid/work/calibre/src/calibre/ebooks/chm/reader.py:56 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/meta.py:600 msgid "Path to a graphic that will be set as this files' thumbnail" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/chm/reader.py:59 +#: /home/kovid/work/calibre/src/calibre/ebooks/chm/reader.py:59 msgid "Path to a txt file containing a comment." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/chm/reader.py:62 -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/meta.py:607 +#: /home/kovid/work/calibre/src/calibre/ebooks/chm/reader.py:62 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/meta.py:607 msgid "Extract thumbnail from LRF file" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/chm/reader.py:63 -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/meta.py:608 +#: /home/kovid/work/calibre/src/calibre/ebooks/chm/reader.py:63 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/meta.py:608 msgid "Set the publisher" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/chm/reader.py:64 -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/meta.py:609 +#: /home/kovid/work/calibre/src/calibre/ebooks/chm/reader.py:64 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/meta.py:609 msgid "Set the book classification" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/chm/reader.py:65 -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/meta.py:610 +#: /home/kovid/work/calibre/src/calibre/ebooks/chm/reader.py:65 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/meta.py:610 msgid "Set the book creator" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/chm/reader.py:66 -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/meta.py:611 +#: /home/kovid/work/calibre/src/calibre/ebooks/chm/reader.py:66 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/meta.py:611 msgid "Set the book producer" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/chm/reader.py:68 -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/meta.py:613 +#: /home/kovid/work/calibre/src/calibre/ebooks/chm/reader.py:68 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/meta.py:613 msgid "Extract cover from LRF file. Note that the LRF format has no defined cover, so we use some heuristics to guess the cover." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/chm/reader.py:70 -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/meta.py:615 +#: /home/kovid/work/calibre/src/calibre/ebooks/chm/reader.py:70 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/meta.py:615 msgid "Set book ID" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/chm/reader.py:72 +#: /home/kovid/work/calibre/src/calibre/ebooks/chm/reader.py:72 msgid "Set font delta" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/comic/input.py:178 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:178 msgid "Rendered %s" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/comic/input.py:181 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:181 msgid "Failed %s" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/comic/input.py:235 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:235 msgid "" "Failed to process comic: \n" "\n" "%s" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/comic/input.py:253 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:253 msgid "Number of colors for grayscale image conversion. Default: %default. Values of less than 256 may result in blurred text on your device if you are creating your comics in EPUB format." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/comic/input.py:257 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:257 msgid "Disable normalize (improve contrast) color range for pictures. Default: False" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/comic/input.py:260 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:260 msgid "Maintain picture aspect ratio. Default is to fill the screen." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/comic/input.py:262 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:262 msgid "Disable sharpening." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/comic/input.py:264 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:264 msgid "Disable trimming of comic pages. For some comics, trimming might remove content as well as borders." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/comic/input.py:267 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:267 msgid "Don't split landscape images into two portrait images" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/comic/input.py:269 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:269 msgid "Keep aspect ratio and scale image using screen height as image width for viewing in landscape mode." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/comic/input.py:272 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:272 msgid "Used for right-to-left publications like manga. Causes landscape pages to be split into portrait pages from right to left." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/comic/input.py:276 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:276 msgid "Enable Despeckle. Reduces speckle noise. May greatly increase processing time." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/comic/input.py:279 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:279 msgid "Don't sort the files found in the comic alphabetically by name. Instead use the order they were added to the comic." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/comic/input.py:283 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:283 msgid "The format that images in the created ebook are converted to. You can experiment to see which format gives you optimal size and look on your device." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/comic/input.py:287 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:287 msgid "Apply no processing to the image" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/comic/input.py:289 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:289 msgid "Do not convert the image to grayscale (black and white)" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/comic/input.py:426 -#: /home/kovid/work/trunk/src/calibre/ebooks/comic/input.py:437 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:426 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:437 msgid "Page" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/cli.py:19 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:19 msgid "" "input_file output_file [options]\n" "\n" @@ -1003,321 +1003,321 @@ msgid "" "For full documentation of the conversion system see\n" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/cli.py:97 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:97 msgid "INPUT OPTIONS" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/cli.py:98 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:98 msgid "Options to control the processing of the input %s file" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/cli.py:104 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:104 msgid "OUTPUT OPTIONS" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/cli.py:105 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:105 msgid "Options to control the processing of the output %s" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/cli.py:119 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:119 msgid "Options to control the look and feel of the output" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/cli.py:135 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:135 msgid "Control auto-detection of document structure." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/cli.py:145 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:145 msgid "Control the automatic generation of a Table of Contents. By default, if the source file has a Table of Contents, it will be used in preference to the automatically generated one." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/cli.py:155 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:155 msgid "Options to set metadata in the output" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/cli.py:158 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:158 msgid "Options to help with debugging the conversion" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/cli.py:183 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:183 msgid "List builtin recipes" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/cli.py:256 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:256 msgid "Output saved to" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:95 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:95 msgid "Level of verbosity. Specify multiple times for greater verbosity." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:102 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:102 msgid "Save the output from different stages of the conversion pipeline to the specified directory. Useful if you are unsure at which stage of the conversion process a bug is occurring." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:111 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:111 msgid "Specify the input profile. The input profile gives the conversion system information on how to interpret various information in the input document. For example resolution dependent lengths (i.e. lengths in pixels). Choices are:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:122 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:122 msgid "Specify the output profile. The output profile tells the conversion system how to optimize the created document for the specified device. In some cases, an output profile is required to produce documents that will work on a device. For example EPUB on the SONY reader. Choices are:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:133 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:133 msgid "The base font size in pts. All font sizes in the produced book will be rescaled based on this size. By choosing a larger size you can make the fonts in the output bigger and vice versa. By default, the base font size is chosen based on the output profile you chose." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:143 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:143 msgid "Mapping from CSS font names to font sizes in pts. An example setting is 12,12,14,16,18,20,22,24. These are the mappings for the sizes xx-small to xx-large, with the final size being for huge fonts. The font rescaling algorithm uses these sizes to intelligently rescale fonts. The default is to use a mapping based on the output profile you chose." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:155 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:155 msgid "Disable all rescaling of font sizes." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:162 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:162 msgid "The line height in pts. Controls spacing between consecutive lines of text. By default no line height manipulation is performed." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:170 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:170 msgid "Some badly designed documents use tables to control the layout of text on the page. When converted these documents often have text that runs off the page and other artifacts. This option will extract the content from the tables and present it in a linear fashion." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:180 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:180 msgid "XPath expression that specifies all tags that should be added to the Table of Contents at level one. If this is specified, it takes precedence over other forms of auto-detection." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:189 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:189 msgid "XPath expression that specifies all tags that should be added to the Table of Contents at level two. Each entry is added under the previous level one entry." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:197 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:197 msgid "XPath expression that specifies all tags that should be added to the Table of Contents at level three. Each entry is added under the previous level two entry." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:205 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:205 msgid "Normally, if the source file already has a Table of Contents, it is used in preference to the auto-generated one. With this option, the auto-generated one is always used." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:213 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:213 msgid "Don't add auto-detected chapters to the Table of Contents." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:220 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:220 msgid "If fewer than this number of chapters is detected, then links are added to the Table of Contents. Default: %default" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:227 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:227 msgid "Maximum number of links to insert into the TOC. Set to 0 to disable. Default is: %default. Links are only added to the TOC if less than the threshold number of chapters were detected." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:235 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:235 msgid "Remove entries from the Table of Contents whose titles match the specified regular expression. Matching entries and all their children are removed." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:246 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:246 msgid "An XPath expression to detect chapter titles. The default is to consider

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/trunk/src/calibre/ebooks/conversion/plumber.py:260 +#: /home/kovid/work/calibre/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/trunk/src/calibre/ebooks/conversion/plumber.py:270 +#: /home/kovid/work/calibre/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/trunk/src/calibre/ebooks/conversion/plumber.py:279 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:279 msgid "An XPath expression. Page breaks are inserted before the specified elements." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:285 +#: /home/kovid/work/calibre/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/trunk/src/calibre/ebooks/conversion/plumber.py:290 +#: /home/kovid/work/calibre/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/trunk/src/calibre/ebooks/conversion/plumber.py:295 +#: /home/kovid/work/calibre/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/trunk/src/calibre/ebooks/conversion/plumber.py:300 +#: /home/kovid/work/calibre/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/trunk/src/calibre/ebooks/conversion/plumber.py:306 +#: /home/kovid/work/calibre/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/trunk/src/calibre/ebooks/conversion/plumber.py:316 +#: /home/kovid/work/calibre/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 (

or

tags)." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:323 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:323 msgid "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/trunk/src/calibre/ebooks/conversion/plumber.py:330 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:330 msgid "Use the cover detected from the source file in preference to the specified cover." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:336 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:336 msgid "Insert a blank line between paragraphs. Will not work if the source file does not use paragraphs (

or

tags)." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:343 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:343 msgid "Remove the first image from the input ebook. Useful if the first image in the source file is a cover and you are specifying an external cover." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:351 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:351 msgid "Insert the book metadata at the start of the book. This is useful if your ebook reader does not support displaying/searching metadata directly." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:359 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:359 msgid "Attempt to detect and correct hard line breaks and other problems in the source file. This may make things worse, so use with care." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:367 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:367 msgid "Use a regular expression to try and remove the header." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:374 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:374 msgid "The regular expression to use to remove the header." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:380 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:380 msgid "Use a regular expression to try and remove the footer." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:387 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:387 msgid "The regular expression to use to remove the footer." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:394 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:394 msgid "Read metadata from the specified OPF file. Metadata read from this file will override any metadata in the source file." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:401 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:401 msgid "Transliterate unicode characters to an ASCII representation. Use with care because this will replace unicode characters with ASCII. For instance it will replace \"%s\" with \"Mikhail Gorbachiov\". Also, note that in cases where there are multiple representations of a character (characters shared by Chinese and Japanese for instance) the representation used by the largest number of people will be used (Chinese in the previous example)." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:416 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:416 msgid "Preserve ligatures present in the input document. A ligature is a special rendering of a pair of characters like ff, fi, fl et cetera. Most readers do not have support for ligatures in their default fonts, so they are unlikely to render correctly. By default, calibre will turn a ligature into the corresponding pair of normal characters. This option will preserve them instead." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:428 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/cli.py:38 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:428 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:38 msgid "Set the title." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:432 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:432 msgid "Set the authors. Multiple authors should be separated by ampersands." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:437 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:437 msgid "The version of the title to be used for sorting. " msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:441 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:441 msgid "String to be used when sorting by author. " msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:445 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:445 msgid "Set the cover to the specified file or URL" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:449 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/cli.py:54 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:449 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:54 msgid "Set the ebook description." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:453 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/cli.py:56 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:453 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:56 msgid "Set the ebook publisher." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:457 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/cli.py:60 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:457 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:60 msgid "Set the series this ebook belongs to." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:461 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/cli.py:62 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:461 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:62 msgid "Set the index of the book in this series." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:465 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/cli.py:64 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:465 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:64 msgid "Set the rating. Should be a number between 1 and 5." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:469 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/cli.py:66 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:469 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:66 msgid "Set the ISBN of the book." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:473 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/cli.py:68 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:473 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:68 msgid "Set the tags for the book. Should be a comma separated list." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:477 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/cli.py:70 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:477 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:70 msgid "Set the book producer." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:481 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/cli.py:72 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:481 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:72 msgid "Set the language." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:485 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:485 msgid "Set the publication date." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:489 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:489 msgid "Set the book timestamp (used by the date column in calibre)." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:589 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:589 msgid "Could not find an ebook inside the archive" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:647 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:647 msgid "Values of series index and rating must be numbers. Ignoring" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:654 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:654 msgid "Failed to parse date/time" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:809 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:809 msgid "Converting input to HTML..." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:836 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:836 msgid "Running transforms on ebook..." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/conversion/plumber.py:923 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:923 msgid "Creating" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/epub/fix/__init__.py:18 +#: /home/kovid/work/calibre/src/calibre/ebooks/epub/fix/__init__.py:18 msgid "ePub Fixer" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/epub/fix/epubcheck.py:18 +#: /home/kovid/work/calibre/src/calibre/ebooks/epub/fix/epubcheck.py:18 msgid "Workaround epubcheck bugs" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/epub/fix/epubcheck.py:22 +#: /home/kovid/work/calibre/src/calibre/ebooks/epub/fix/epubcheck.py:22 msgid "Workarounds for bugs in the latest release of epubcheck. epubcheck reports many things as errors that are not actually errors. epub-fix will try to detect these and replace them with constructs that epubcheck likes. This may cause significant changes to your epub, complain to the epubcheck project." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/epub/fix/main.py:19 +#: /home/kovid/work/calibre/src/calibre/ebooks/epub/fix/main.py:19 msgid "" "%prog [options] file.epub\n" "\n" @@ -1326,223 +1326,223 @@ msgid "" "By default, no fixing is done and messages are printed out for each error detected. Use the options to control which errors are automatically fixed." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/epub/fix/main.py:50 +#: /home/kovid/work/calibre/src/calibre/ebooks/epub/fix/main.py:50 msgid "You must specify an epub file" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/epub/fix/unmanifested.py:17 +#: /home/kovid/work/calibre/src/calibre/ebooks/epub/fix/unmanifested.py:17 msgid "Fix unmanifested files" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/epub/fix/unmanifested.py:21 +#: /home/kovid/work/calibre/src/calibre/ebooks/epub/fix/unmanifested.py:21 msgid "Fix unmanifested files. epub-fix can either add them to the manifest or delete them as specified by the delete unmanifested option." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/epub/fix/unmanifested.py:32 +#: /home/kovid/work/calibre/src/calibre/ebooks/epub/fix/unmanifested.py:32 msgid "Delete unmanifested files instead of adding them to the manifest" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/epub/output.py:56 +#: /home/kovid/work/calibre/src/calibre/ebooks/epub/output.py:56 msgid "Extract the contents of the generated EPUB file to the specified directory. The contents of the directory are first deleted, so be careful." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/epub/output.py:62 +#: /home/kovid/work/calibre/src/calibre/ebooks/epub/output.py:62 msgid "Turn off splitting at page breaks. Normally, input files are automatically split at every page break into two files. This gives an output ebook that can be parsed faster and with less resources. However, splitting is slow and if your source file contains a very large number of page breaks, you should turn off splitting on page breaks." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/epub/output.py:73 +#: /home/kovid/work/calibre/src/calibre/ebooks/epub/output.py:73 msgid "Split all HTML files larger than this size (in KB). This is necessary as most EPUB readers cannot handle large file sizes. The default of %defaultKB is the size required for Adobe Digital Editions." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/epub/output.py:80 +#: /home/kovid/work/calibre/src/calibre/ebooks/epub/output.py:80 msgid "Normally, if the input file has no cover and you don't specify one, a default cover is generated with the title, authors, etc. This option disables the generation of this cover." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/epub/output.py:86 +#: /home/kovid/work/calibre/src/calibre/ebooks/epub/output.py:86 msgid "Do not use SVG for the book cover. Use this option if your EPUB is going to be used on a device that does not support SVG, like the iPhone or the JetBook Lite. Without this option, such devices will display the cover as a blank page." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/epub/output.py:94 +#: /home/kovid/work/calibre/src/calibre/ebooks/epub/output.py:94 msgid "When using an SVG cover, this option will cause the cover to scale to cover the available screen area, but still preserve its aspect ratio (ratio of width to height). That means there may be white borders at the sides or top and bottom of the image, but the image will never be distorted. Without this option the image may be slightly distorted, but there will be no borders." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/epub/output.py:169 +#: /home/kovid/work/calibre/src/calibre/ebooks/epub/output.py:169 msgid "Start" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/fb2/fb2ml.py:144 -#: /home/kovid/work/trunk/src/calibre/ebooks/rb/rbml.py:102 -#: /home/kovid/work/trunk/src/calibre/ebooks/txt/txtml.py:77 +#: /home/kovid/work/calibre/src/calibre/ebooks/fb2/fb2ml.py:144 +#: /home/kovid/work/calibre/src/calibre/ebooks/rb/rbml.py:102 +#: /home/kovid/work/calibre/src/calibre/ebooks/txt/txtml.py:77 msgid "Table of Contents:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/fb2/input.py:32 +#: /home/kovid/work/calibre/src/calibre/ebooks/fb2/input.py:32 msgid "Do not insert a Table of Contents at the beginning of the book." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/fb2/output.py:21 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdb/output.py:32 -#: /home/kovid/work/trunk/src/calibre/ebooks/pml/output.py:37 -#: /home/kovid/work/trunk/src/calibre/ebooks/rb/output.py:21 -#: /home/kovid/work/trunk/src/calibre/ebooks/txt/output.py:35 +#: /home/kovid/work/calibre/src/calibre/ebooks/fb2/output.py:21 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/output.py:32 +#: /home/kovid/work/calibre/src/calibre/ebooks/pml/output.py:37 +#: /home/kovid/work/calibre/src/calibre/ebooks/rb/output.py:21 +#: /home/kovid/work/calibre/src/calibre/ebooks/txt/output.py:35 msgid "Add Table of Contents to beginning of the book." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/html/input.py:248 +#: /home/kovid/work/calibre/src/calibre/ebooks/html/input.py:248 msgid "Traverse links in HTML files breadth first. Normally, they are traversed depth first." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/html/input.py:255 +#: /home/kovid/work/calibre/src/calibre/ebooks/html/input.py:255 msgid "Maximum levels of recursion when following links in HTML files. Must be non-negative. 0 implies that no links in the root HTML file are followed. Default is %default." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/html/input.py:264 +#: /home/kovid/work/calibre/src/calibre/ebooks/html/input.py:264 msgid "Normally this input plugin re-arranges all the input files into a standard folder hierarchy. Only use this option if you know what you are doing as it can result in various nasty side effects in the rest of of the conversion pipeline." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/html/input.py:272 +#: /home/kovid/work/calibre/src/calibre/ebooks/html/input.py:272 msgid "Average line length for line breaking if the HTML is from a previous partial conversion of a PDF file. Default is %default which disables this." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lit/from_any.py:47 +#: /home/kovid/work/calibre/src/calibre/ebooks/lit/from_any.py:47 msgid "Creating LIT file from EPUB..." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/html/convert_from.py:320 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/html/convert_from.py:320 msgid "\tBook Designer file detected." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/html/convert_from.py:322 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/html/convert_from.py:322 msgid "\tParsing HTML..." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/html/convert_from.py:345 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/html/convert_from.py:345 msgid "\tBaen file detected. Re-parsing..." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/html/convert_from.py:361 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/html/convert_from.py:361 msgid "Written preprocessed HTML to " msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/html/convert_from.py:379 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/html/convert_from.py:379 msgid "Processing %s" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/html/convert_from.py:393 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/html/convert_from.py:393 msgid "\tConverting to BBeB..." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/html/convert_from.py:539 -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/html/convert_from.py:552 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/html/convert_from.py:539 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/html/convert_from.py:552 msgid "Could not parse file: %s" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/html/convert_from.py:544 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/html/convert_from.py:544 msgid "%s is an empty file" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/html/convert_from.py:564 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/html/convert_from.py:564 msgid "Failed to parse link %s %s" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/html/convert_from.py:608 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/html/convert_from.py:608 msgid "Cannot add link %s to TOC" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/html/convert_from.py:957 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/html/convert_from.py:957 msgid "Unable to process image %s. Error: %s" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/html/convert_from.py:1002 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/html/convert_from.py:1002 msgid "Unable to process interlaced PNG %s" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/html/convert_from.py:1017 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/html/convert_from.py:1017 msgid "" "Could not process image: %s\n" "%s" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/html/convert_from.py:1772 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/html/convert_from.py:1772 msgid "An error occurred while processing a table: %s. Ignoring table markup." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/html/convert_from.py:1774 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/html/convert_from.py:1774 msgid "" "Bad table:\n" "%s" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/html/convert_from.py:1796 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/html/convert_from.py:1796 msgid "Table has cell that is too large" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/html/convert_from.py:1862 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/html/convert_from.py:1862 msgid "Could not read cover image: %s" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/html/convert_from.py:1865 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/html/convert_from.py:1865 msgid "Cannot read from: %s" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/html/convert_from.py:1994 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/html/convert_from.py:1994 msgid "Failed to process opf file" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/lrfparser.py:136 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/lrfparser.py:136 msgid "" "%prog book.lrf\n" "Convert an LRF file into an LRS (XML UTF-8 encoded) file" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/lrfparser.py:137 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/lrfparser.py:137 msgid "Output LRS file" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/lrfparser.py:139 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/lrfparser.py:139 msgid "Do not save embedded image and font files to disk" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/lrfparser.py:158 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/lrfparser.py:158 msgid "Parsing LRF..." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/lrfparser.py:161 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/lrfparser.py:161 msgid "Creating XML..." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/lrfparser.py:163 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/lrfparser.py:163 msgid "LRS written to " msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/lrs/convert_from.py:267 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/lrs/convert_from.py:267 msgid "Could not read from thumbnail file:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/lrs/convert_from.py:287 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/lrs/convert_from.py:287 msgid "" "%prog [options] file.lrs\n" "Compile an LRS file into an LRF file." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/lrs/convert_from.py:288 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/lrs/convert_from.py:288 msgid "Path to output file" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/lrs/convert_from.py:290 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/isbndb.py:114 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/lrs/convert_from.py:290 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/isbndb.py:114 msgid "Verbose processing" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/lrs/convert_from.py:292 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/lrs/convert_from.py:292 msgid "Convert LRS to LRS, useful for debugging." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/meta.py:457 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/meta.py:457 msgid "Invalid LRF file. Could not set metadata." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/meta.py:582 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/meta.py:582 msgid "" "%prog [options] mybook.lrf\n" "\n" @@ -1551,154 +1551,154 @@ msgid "" "\n" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/meta.py:603 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/meta.py:603 msgid "Path to a txt file containing the comment to be stored in the lrf file." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/output.py:90 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/output.py:90 msgid "Enable autorotation of images that are wider than the screen width." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/output.py:94 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/output.py:94 msgid "Set the space between words in pts. Default is %default" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/output.py:97 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/output.py:97 msgid "Add a header to all the pages with title and author." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/output.py:100 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/output.py:100 msgid "Set the format of the header. %a is replaced by the author and %t by the title. Default is %default" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/output.py:104 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/output.py:104 msgid "Add extra spacing below the header. Default is %default pt." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/output.py:107 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/output.py:107 msgid "Minimum paragraph indent (the indent of the first line of a paragraph) in pts. Default: %default" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/output.py:112 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/output.py:112 msgid "Render tables in the HTML as images (useful if the document has large or complex tables)" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/output.py:117 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/output.py:117 msgid "Multiply the size of text in rendered tables by this factor. Default is %default" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/output.py:121 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/output.py:121 msgid "The serif family of fonts to embed" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/output.py:124 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/output.py:124 msgid "The sans-serif family of fonts to embed" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/output.py:127 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/output.py:127 msgid "The monospace family of fonts to embed" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/lrf/output.py:152 +#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/output.py:152 msgid "Comic" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/__init__.py:397 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/info.py:45 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/book_info.py:97 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/book_info.py:98 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/delete_matching_from_device.py:75 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata.py:58 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:65 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:359 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:887 -#: /home/kovid/work/trunk/src/calibre/library/server/opds.py:550 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/__init__.py:397 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/info.py:45 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:97 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:98 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/delete_matching_from_device.py:75 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:58 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:65 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:359 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:887 +#: /home/kovid/work/calibre/src/calibre/library/server/opds.py:550 msgid "Title" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/__init__.py:398 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata.py:59 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:67 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:364 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:888 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/__init__.py:398 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:59 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:67 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:364 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:888 msgid "Author(s)" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/__init__.py:399 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata.py:61 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:72 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/__init__.py:399 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:61 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:72 msgid "Publisher" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/__init__.py:400 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/info.py:49 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/__init__.py:400 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/info.py:49 msgid "Producer" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/__init__.py:401 -#: /home/kovid/work/trunk/src/calibre/gui2/book_details.py:35 -#: /home/kovid/work/trunk/src/calibre/gui2/book_details.py:210 -#: /home/kovid/work/trunk/src/calibre/gui2/book_details.py:211 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:184 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/book_info.py:99 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/book_info_ui.py:67 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:318 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:1079 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/__init__.py:401 +#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:35 +#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:210 +#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:211 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:184 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:99 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info_ui.py:67 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:318 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1079 msgid "Comments" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/__init__.py:409 -#: /home/kovid/work/trunk/src/calibre/gui2/book_details.py:27 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories.py:50 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:73 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:306 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:1075 -#: /home/kovid/work/trunk/src/calibre/library/field_metadata.py:143 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/__init__.py:409 +#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:27 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories.py:50 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:73 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:306 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1075 +#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:143 msgid "Tags" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/__init__.py:411 -#: /home/kovid/work/trunk/src/calibre/gui2/book_details.py:26 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories.py:50 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:74 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:323 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:1084 -#: /home/kovid/work/trunk/src/calibre/library/field_metadata.py:91 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/__init__.py:411 +#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:26 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories.py:50 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:74 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:323 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1084 +#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:91 msgid "Series" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/__init__.py:412 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/__init__.py:412 msgid "Language" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/__init__.py:414 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:1067 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/__init__.py:414 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1067 msgid "Timestamp" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/__init__.py:416 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata.py:63 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:70 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/__init__.py:416 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:63 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:70 msgid "Published" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/__init__.py:418 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/__init__.py:418 msgid "Rights" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/amazon.py:85 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/amazon.py:85 msgid "EDITORIAL REVIEW" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/archive.py:41 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/archive.py:41 msgid "Extract common e-book formats from archives (zip/rar) files. Also try to autodetect if they are actually cbz/cbr files." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/cli.py:20 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:20 msgid "options" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/cli.py:21 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:21 msgid "" "\n" "Read/Write metadata from/to ebook files.\n" @@ -1712,147 +1712,147 @@ msgid "" "silently ignored.\n" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/cli.py:40 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:40 msgid "Set the authors. Multiple authors should be separated by the & character. Author names should be in the order Firstname Lastname." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/cli.py:44 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:44 msgid "The version of the title to be used for sorting. If unspecified, and the title is specified, it will be auto-generated from the title." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/cli.py:48 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:48 msgid "String to be used when sorting by author. If unspecified, and the author(s) are specified, it will be auto-generated from the author(s)." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/cli.py:52 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:52 msgid "Set the cover to the specified file." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/cli.py:58 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:58 msgid "Set the book category." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/cli.py:74 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:74 msgid "Set the published date." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/cli.py:77 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:77 msgid "Get the cover from the ebook and save it at as the specified file." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/cli.py:80 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:80 msgid "Specify the name of an OPF file. The metadata will be written to the OPF file." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/cli.py:83 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:83 msgid "Read metadata from the specified OPF file and use it to set metadata in the ebook. Metadata specified on the command line will override metadata read from the OPF file" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/cli.py:88 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:88 msgid "Set the BookID in LRF files" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/cli.py:153 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:153 msgid "No file specified" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/cli.py:168 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:168 msgid "Original metadata" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/cli.py:185 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:185 msgid "Changed metadata" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/cli.py:197 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:197 msgid "OPF created in" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/cli.py:203 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:203 msgid "Cover saved to" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/cli.py:205 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:205 msgid "No cover found" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/covers.py:27 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/covers.py:27 msgid "Cover download" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/covers.py:79 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/covers.py:79 msgid "Download covers from openlibrary.org" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/covers.py:107 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/covers.py:136 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/covers.py:107 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/covers.py:136 msgid "ISBN: %s not found" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/covers.py:117 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/covers.py:117 msgid "Download covers from librarything.com" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/covers.py:128 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/library_thing.py:68 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/covers.py:128 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/library_thing.py:68 msgid "LibraryThing.com timed out. Try again later." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/covers.py:135 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/library_thing.py:75 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/covers.py:135 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/library_thing.py:75 msgid "Could not fetch cover as server is experiencing high load. Please try again later." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/covers.py:139 -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/library_thing.py:79 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/covers.py:139 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/library_thing.py:79 msgid "LibraryThing.com server error. Try again later." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/douban.py:42 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/douban.py:42 msgid "Downloads metadata from Douban.com" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/fetch.py:50 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/fetch.py:51 msgid "Metadata download" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/fetch.py:127 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/fetch.py:128 msgid "ratings" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/fetch.py:127 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/fetch.py:128 msgid "tags" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/fetch.py:128 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/fetch.py:129 msgid "description/reviews" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/fetch.py:129 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/fetch.py:130 msgid "Download %s from %s" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/fetch.py:155 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/fetch.py:156 msgid "Downloads metadata from Google Books" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/fetch.py:172 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/fetch.py:173 msgid "Downloads metadata from isbndb.com" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/fetch.py:200 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/fetch.py:201 msgid "To use isbndb.com you must sign up for a %sfree account%s and enter your access key below." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/fetch.py:210 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/fetch.py:211 msgid "Downloads social metadata from amazon.com" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/fetch.py:229 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/fetch.py:230 msgid "Downloads series/tags/rating information from librarything.com" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/isbndb.py:95 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/isbndb.py:95 msgid "" "\n" "%prog [options] key\n" @@ -1865,27 +1865,27 @@ msgid "" "\n" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/isbndb.py:106 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/isbndb.py:106 msgid "The ISBN ID of the book you want metadata for." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/isbndb.py:108 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/isbndb.py:108 msgid "The author whose book to search for." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/isbndb.py:110 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/isbndb.py:110 msgid "The title of the book to search for." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/isbndb.py:112 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/isbndb.py:112 msgid "The publisher of the book to search for." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/library_thing.py:76 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/library_thing.py:76 msgid " not found." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/library_thing.py:86 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/library_thing.py:86 msgid "" "\n" "%prog [options] ISBN\n" @@ -1893,180 +1893,180 @@ msgid "" "Fetch a cover image/social metadata for the book identified by ISBN from LibraryThing.com\n" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/metadata/opf2.py:1226 -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/base.py:1399 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/opf2.py:1226 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:1399 msgid "Cover" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/mobi/output.py:22 +#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/output.py:22 msgid "Modify images to meet Palm device size limitations." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/mobi/output.py:26 +#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/output.py:26 msgid "When present, use author sort field as author." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/mobi/output.py:30 +#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/output.py:30 msgid "Don't add Table of Contents to end of book. Useful if the book has its own table of contents." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/mobi/output.py:33 -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/transforms/htmltoc.py:56 +#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/output.py:33 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/transforms/htmltoc.py:56 msgid "Title for any generated in-line table of contents." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/mobi/output.py:37 +#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/output.py:37 msgid "Disable compression of the file contents." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/mobi/output.py:40 +#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/output.py:40 msgid "Tag marking book to be filed with Personal Docs" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/mobi/output.py:108 +#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/output.py:108 msgid "All articles" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/mobi/reader.py:259 +#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:259 msgid "This is an Amazon Topaz book. It cannot be processed." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/base.py:1400 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:1400 msgid "Title Page" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/base.py:1401 -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/transforms/htmltoc.py:15 -#: /home/kovid/work/trunk/src/calibre/gui2/viewer/main.py:53 -#: /home/kovid/work/trunk/src/calibre/gui2/viewer/main_ui.py:194 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:1401 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/transforms/htmltoc.py:15 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:53 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main_ui.py:194 msgid "Table of Contents" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/base.py:1402 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:1402 msgid "Index" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/base.py:1403 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:1403 msgid "Glossary" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/base.py:1404 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:1404 msgid "Acknowledgements" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/base.py:1405 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:1405 msgid "Bibliography" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/base.py:1406 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:1406 msgid "Colophon" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/base.py:1407 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:1407 msgid "Copyright" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/base.py:1408 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:1408 msgid "Dedication" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/base.py:1409 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:1409 msgid "Epigraph" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/base.py:1410 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:1410 msgid "Foreword" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/base.py:1411 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:1411 msgid "List of Illustrations" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/base.py:1412 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:1412 msgid "List of Tables" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/base.py:1413 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:1413 msgid "Notes" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/base.py:1414 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:1414 msgid "Preface" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/base.py:1415 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:1415 msgid "Main Text" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/iterator.py:41 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/iterator.py:41 msgid "%s format books are not supported" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/transforms/htmltoc.py:54 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/transforms/htmltoc.py:54 msgid "HTML TOC generation options." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/transforms/jacket.py:113 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/transforms/jacket.py:113 msgid "Book Jacket" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/transforms/split.py:34 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/transforms/split.py:34 msgid "Could not find reasonable point at which to split: %s Sub-tree size: %d KB" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/writer.py:32 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/writer.py:32 msgid "OPF/NCX/etc. generation options." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/writer.py:35 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/writer.py:35 msgid "OPF version to generate. Default is %default." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/oeb/writer.py:37 +#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/writer.py:37 msgid "Generate an Adobe \"page-map\" file if pagination information is available." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdb/ereader/reader132.py:128 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/ereader/reader132.py:128 msgid "Footnotes" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdb/ereader/reader132.py:135 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/ereader/reader132.py:135 msgid "Sidebar" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdb/input.py:22 -#: /home/kovid/work/trunk/src/calibre/ebooks/tcr/input.py:23 -#: /home/kovid/work/trunk/src/calibre/ebooks/txt/input.py:24 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/input.py:22 +#: /home/kovid/work/calibre/src/calibre/ebooks/tcr/input.py:23 +#: /home/kovid/work/calibre/src/calibre/ebooks/txt/input.py:24 msgid "Normally calibre treats blank lines as paragraph markers. With this option it will assume that every line represents a paragraph instead." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdb/input.py:26 -#: /home/kovid/work/trunk/src/calibre/ebooks/tcr/input.py:27 -#: /home/kovid/work/trunk/src/calibre/ebooks/txt/input.py:28 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/input.py:26 +#: /home/kovid/work/calibre/src/calibre/ebooks/tcr/input.py:27 +#: /home/kovid/work/calibre/src/calibre/ebooks/txt/input.py:28 msgid "Normally calibre treats blank lines as paragraph markers. With this option it will assume that every line starting with an indent (either a tab or 2+ spaces) represents a paragraph. Paragraphs end when the next line that starts with an indent is reached." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdb/output.py:23 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/output.py:23 msgid "Format to use inside the pdb container. Choices are:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdb/output.py:27 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/output.py:27 msgid "Specify the character encoding of the output document. The default is cp1252. Note: This option is not honored by all formats." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/input.py:24 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/input.py:24 msgid "Do not extract images from the document" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/input.py:26 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/input.py:26 msgid "Scale used to determine the length at which a line should be unwrapped. Valid values are a decimal between 0 and 1. The default is 0.5, this is the median line length." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/input.py:30 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/input.py:30 msgid "Use the new PDF conversion engine." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/cli.py:31 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/cli.py:31 msgid "" "command ...\n" "\n" @@ -2078,113 +2078,113 @@ msgid "" "Manipulate a PDF.\n" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/crop.py:29 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:29 msgid "" "[options] file.pdf\n" "\n" "Crop a PDF file.\n" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/crop.py:38 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/decrypt.py:32 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/encrypt.py:34 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/merge.py:36 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/reverse.py:34 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/rotate.py:33 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/split.py:41 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:38 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/decrypt.py:32 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/encrypt.py:34 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/merge.py:36 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/reverse.py:34 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/rotate.py:33 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/split.py:41 msgid "Path to output file. By default a file is created in the current directory." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/crop.py:41 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:41 msgid "Number of pixels to crop from the left most x (default is %s)" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/crop.py:44 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:44 msgid "Number of pixels to crop from the left most y (default is %s)" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/crop.py:47 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:47 msgid "Number of pixels to crop from the right most x (default is %s)" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/crop.py:50 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:50 msgid "Number of pixels to crop from the right most y (default is %s)" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/crop.py:53 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:53 msgid "A file generated by ghostscript which allows each page to be individually cropped `gs -dSAFER -dNOPAUSE -dBATCH -sDEVICE=bbox file.pdf 2> bounding`" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/crop.py:73 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:73 msgid "Crop Options:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/crop.py:73 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/decrypt.py:60 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/encrypt.py:54 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/merge.py:56 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/reverse.py:54 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/rotate.py:53 -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/split.py:61 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:73 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/decrypt.py:60 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/encrypt.py:54 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/merge.py:56 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/reverse.py:54 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/rotate.py:53 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/split.py:61 msgid "Options to control the transformation of pdf" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/decrypt.py:23 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/decrypt.py:23 msgid "" "[options] file.pdf password\n" "\n" "Decrypt a PDF.\n" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/decrypt.py:60 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/decrypt.py:60 msgid "Decrypt Options:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/encrypt.py:25 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/encrypt.py:25 msgid "" "[options] file.pdf password\n" "\n" "Encrypt a PDF.\n" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/encrypt.py:54 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/encrypt.py:54 msgid "Encrypt Options:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/info.py:21 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/info.py:21 msgid "" "file.pdf ...\n" "\n" "Get info about a PDF.\n" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/info.py:46 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/delete_matching_from_device.py:75 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/edit_authors_dialog.py:33 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/info.py:46 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/delete_matching_from_device.py:75 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/edit_authors_dialog.py:33 msgid "Author" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/info.py:47 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/info.py:47 msgid "Subject" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/info.py:48 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/info.py:48 msgid "Creator" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/info.py:50 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/info.py:50 msgid "Pages" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/info.py:51 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/info.py:51 msgid "File Size" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/info.py:52 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/info.py:52 msgid "PDF Version" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/merge.py:25 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/merge.py:25 msgid "" "[options] file1.pdf file2.pdf ...\n" "\n" @@ -2193,33 +2193,33 @@ msgid "" "Merges individual PDFs.\n" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/merge.py:56 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/merge.py:56 msgid "Merge Options:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/reverse.py:25 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/reverse.py:25 msgid "" "[options] file.pdf\n" "\n" "Reverse a PDF.\n" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/reverse.py:54 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/reverse.py:54 msgid "Reverse Options:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/rotate.py:24 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/rotate.py:24 msgid "" "file.pdf degrees\n" "\n" "Rotate pages of a PDF clockwise.\n" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/rotate.py:53 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/rotate.py:53 msgid "Rotate Options:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/split.py:25 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/split.py:25 msgid "" "\n" "%prog %%name [options] file.pdf page_to_split_on ...\n" @@ -2234,948 +2234,948 @@ msgid "" "Split a PDF.\n" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/manipulate/split.py:61 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/split.py:61 msgid "Split Options:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/output.py:31 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/output.py:31 msgid "The unit of measure. Default is inch. Choices are %s Note: This does not override the unit for margins!" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/output.py:36 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/output.py:36 msgid "The size of the paper. This size will be overridden when an output profile is used. Default is letter. Choices are %s" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/output.py:40 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/output.py:40 msgid "Custom size of the document. Use the form widthxheight EG. `123x321` to specify the width and height. This overrides any specified paper-size." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/output.py:45 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/output.py:45 msgid "The orientation of the page. Default is portrait. Choices are %s" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/output.py:49 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/output.py:49 msgid "Preserve the aspect ratio of the cover, instead of stretching it to fill the ull first page of the generated pdf." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pdf/pdftohtml.py:55 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/pdftohtml.py:55 msgid "Could not find pdftohtml, check it is in your PATH" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/pml/output.py:33 +#: /home/kovid/work/calibre/src/calibre/ebooks/pml/output.py:33 msgid "Specify the character encoding of the output document. The default is cp1252." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/rtf/input.py:194 +#: /home/kovid/work/calibre/src/calibre/ebooks/rtf/input.py:194 msgid "" "This RTF file has a feature calibre does not support. Convert it to HTML first and then try it.\n" "%s" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/tcr/output.py:23 +#: /home/kovid/work/calibre/src/calibre/ebooks/tcr/output.py:23 msgid "Specify the character encoding of the output document. The default is utf-8." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/tcr/output.py:27 +#: /home/kovid/work/calibre/src/calibre/ebooks/tcr/output.py:27 msgid "Specify the compression level to use. Scale 1 - 10. 1 being the lowest compression but the fastest and 10 being the highest compression but the slowest." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/txt/input.py:34 +#: /home/kovid/work/calibre/src/calibre/ebooks/txt/input.py:34 msgid "Normally extra spaces are condensed into a single space. With this option all spaces will be displayed." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/txt/input.py:37 +#: /home/kovid/work/calibre/src/calibre/ebooks/txt/input.py:37 msgid "Run the text input through the markdown pre-processor. To learn more about markdown see" msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/txt/input.py:40 +#: /home/kovid/work/calibre/src/calibre/ebooks/txt/input.py:40 msgid "Do not insert a Table of Contents into the output text." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/txt/output.py:24 +#: /home/kovid/work/calibre/src/calibre/ebooks/txt/output.py:24 msgid "Type of newline to use. Options are %s. Default is 'system'. Use 'old_mac' for compatibility with Mac OS 9 and earlier. For Mac OS X use 'unix'. 'system' will default to the newline type used by this OS." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/txt/output.py:30 +#: /home/kovid/work/calibre/src/calibre/ebooks/txt/output.py:30 msgid "Specify the character encoding of the output document. The default is utf-8. Note: This option is not honored by all formats." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/txt/output.py:38 +#: /home/kovid/work/calibre/src/calibre/ebooks/txt/output.py:38 msgid "The maximum number of characters per line. This splits on the first space before the specified value. If no space is found the line will be broken at the space after and will exceed the specified value. Also, there is a minimum of 25 characters. Use 0 to disable line splitting." msgstr "" -#: /home/kovid/work/trunk/src/calibre/ebooks/txt/output.py:45 +#: /home/kovid/work/calibre/src/calibre/ebooks/txt/output.py:45 msgid "Force splitting on the max-line-length value when no space is present. Also allows max-line-length to be below the minimum" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:33 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:33 msgid "Send file to storage card instead of main memory by default" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:35 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:35 msgid "Confirm before deleting" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:37 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:37 msgid "Main window geometry" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:39 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:39 msgid "Notify when a new version is available" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:41 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:41 msgid "Use Roman numerals for series number" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:43 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:43 msgid "Sort tags list by name, popularity, or rating" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:45 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:45 msgid "Number of covers to show in the cover browsing mode" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:47 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:47 msgid "Defaults for conversion to LRF" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:49 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:49 msgid "Options for the LRF ebook viewer" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:52 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:52 msgid "Formats that are viewed using the internal viewer" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:54 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:54 msgid "Columns to be displayed in the book list" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:55 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:55 msgid "Automatically launch content server on application startup" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:56 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:56 msgid "Oldest news kept in database" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:57 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:57 msgid "Show system tray icon" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:59 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:59 msgid "Upload downloaded news to device" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:61 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:61 msgid "Delete books from library after uploading to device" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:63 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:63 msgid "Show the cover flow in a separate window instead of in the main calibre window" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:65 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:65 msgid "Disable notifications from the system tray icon" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:67 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:67 msgid "Default action to perform when send to device button is clicked" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:89 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:89 msgid "Maximum number of waiting worker processes" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:91 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:91 msgid "Download social metadata (tags/rating/etc.)" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:93 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:93 msgid "Overwrite author and title with new metadata" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:95 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:95 msgid "Limit max simultaneous jobs to number of CPUs" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:97 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:97 msgid "tag browser categories not to display" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:99 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:99 msgid "The layout of the user interface" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:101 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:101 msgid "Show the average rating per item indication in the tag browser" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:103 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:103 msgid "Disable UI animations" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:151 -#: /home/kovid/work/trunk/src/calibre/gui2/wizard/__init__.py:479 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:151 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:479 msgid "Copied" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:185 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:185 msgid "Copy" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:185 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:185 msgid "Copy to Clipboard" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/__init__.py:397 +#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:397 msgid "Choose Files" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:67 -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:245 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:67 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:245 msgid "Use library only" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:68 -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:246 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:68 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:246 msgid "User annotations generated from main library only" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:75 -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:623 -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:682 -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:719 -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:740 -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:925 -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:998 -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:1116 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:75 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:640 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:706 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:743 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:764 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:949 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:1022 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:1140 msgid "No books selected" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:76 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:76 msgid "No books selected to fetch annotations from" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:101 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:101 msgid "Merging user annotations into database" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:129 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:129 msgid "%s
Last Page Read: %d (%d%%)" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:135 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:135 msgid "%s
Last Page Read: Location %d (%d%%)" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:154 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:154 msgid "Location %d • %s
%s
" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:163 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:163 msgid "Page %d • %s
" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:168 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:168 msgid "Location %d • %s
" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:291 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:291 msgid "How many empty books?" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:292 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:292 msgid "How many empty books should be added?" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:339 -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:390 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:350 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:407 msgid "Uploading books to device." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:350 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:164 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:367 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:164 msgid "Books" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:351 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:368 msgid "EPUB Books" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:352 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:369 msgid "LRF Books" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:353 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:370 msgid "HTML Books" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:354 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:371 msgid "LIT Books" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:355 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:372 msgid "MOBI Books" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:356 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:373 msgid "Topaz books" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:357 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:374 msgid "Text books" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:358 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:375 msgid "PDF Books" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:359 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:376 msgid "Comics" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:360 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:377 msgid "Archives" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:364 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:381 msgid "Supported books" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:399 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:416 msgid "Merged some books" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:400 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:417 msgid "Some duplicates were found and merged into the following existing books:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:409 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:426 msgid "Failed to read metadata" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:410 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:427 msgid "Failed to read metadata from the following" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:429 -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:448 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:446 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:465 msgid "Add to library" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:429 -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:473 -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:1260 -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:1285 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:446 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:490 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:1284 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:1309 msgid "No book selected" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:442 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:459 msgid "The following books are virtual and cannot be added to the calibre library:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:448 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:465 msgid "No book files found" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:470 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:487 msgid "Cannot delete" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:483 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:500 msgid "Choose formats to be deleted" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:501 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:518 msgid "Choose formats not to be deleted" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:521 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:538 msgid "Cannot delete books" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:522 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:539 msgid "No device is connected" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:532 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:549 msgid "Main memory" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:533 -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:436 -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:445 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:550 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:436 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:445 msgid "Storage Card A" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:534 -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:438 -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:447 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:551 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:438 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:447 msgid "Storage Card B" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:539 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:556 msgid "No books to delete" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:540 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:557 msgid "None of the selected books are on the device" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:557 -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:612 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:574 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:629 msgid "Deleting books from device." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:578 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:595 msgid "The selected books will be permanently deleted and the files removed from your computer. Are you sure?" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:597 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:614 msgid "The selected books will be permanently deleted from your device. Are you sure?" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:622 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:639 msgid "Cannot download metadata" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:638 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:662 msgid "social metadata" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:640 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:664 msgid "covers" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:640 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:664 msgid "metadata" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:642 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:666 msgid "Downloading %s for %d book(s)" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:666 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:690 msgid "Failed to download some metadata" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:667 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:691 msgid "Failed to download metadata for the following:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:670 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:694 msgid "Failed to download metadata:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:671 -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:608 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:560 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:990 -#: /home/kovid/work/trunk/src/calibre/utils/ipc/job.py:53 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:695 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:608 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:560 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:989 +#: /home/kovid/work/calibre/src/calibre/utils/ipc/job.py:53 msgid "Error" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:681 -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:718 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:705 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:742 msgid "Cannot edit metadata" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:739 -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:742 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:763 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:766 msgid "Cannot merge books" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:743 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:767 msgid "At least two books must be selected for merging" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:747 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:771 msgid "All book formats and metadata from the selected books will be added to the first selected book.

The second and subsequently selected books will not be deleted or changed.

Please confirm you want to proceed." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:758 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:782 msgid "All book formats and metadata from the selected books will be merged into the first selected book.

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/trunk/src/calibre/gui2/actions/__init__.py:770 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:794 msgid "You are about to merge more than 5 books. Are you sure you want to proceed?" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:924 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:948 msgid "Cannot save to disk" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:927 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:951 msgid "Choose destination directory" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:933 -#: /home/kovid/work/trunk/src/calibre/gui2/library/views.py:566 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:957 +#: /home/kovid/work/calibre/src/calibre/gui2/library/views.py:566 msgid "Not allowed" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:934 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:958 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/trunk/src/calibre/gui2/actions/__init__.py:968 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:992 msgid "Error while saving" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:969 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:993 msgid "There was an error while saving." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:976 -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:977 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:1000 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:1001 msgid "Could not save some books" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:978 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:1002 msgid "Click the show details button to see which ones." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:999 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:1023 msgid "No books selected to generate catalog for" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:1016 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:1040 msgid "Generating %s catalog..." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:1021 -#: /home/kovid/work/trunk/src/calibre/gui2/add.py:264 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:1045 +#: /home/kovid/work/calibre/src/calibre/gui2/add.py:264 msgid "No books found" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:1022 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:1046 msgid "" "No books to catalog\n" "Check exclude tags" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:1032 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:1056 msgid "Catalog generated." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:1035 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:1059 msgid "Export Catalog Directory" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:1036 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:1060 msgid "Select destination for %s.%s" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:1052 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:1076 msgid "Fetching news from " msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:1066 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:1090 msgid " fetched." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:1115 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:1139 msgid "Cannot convert" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:1144 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:1168 msgid "Starting conversion of %d book(s)" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:1260 -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:1321 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:1284 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:1345 msgid "Cannot view" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:1266 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/regex_builder.py:77 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:1290 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/regex_builder.py:77 msgid "Choose the format to view" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:1274 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:1298 msgid "Multiple Books Selected" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:1275 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:1299 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/trunk/src/calibre/gui2/actions/__init__.py:1284 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:1308 msgid "Cannot open folder" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/actions/__init__.py:1322 +#: /home/kovid/work/calibre/src/calibre/gui2/actions/__init__.py:1346 msgid "%s has no available formats." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add.py:54 +#: /home/kovid/work/calibre/src/calibre/gui2/add.py:54 msgid "Searching in" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add.py:232 +#: /home/kovid/work/calibre/src/calibre/gui2/add.py:232 msgid "Adding..." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add.py:245 +#: /home/kovid/work/calibre/src/calibre/gui2/add.py:245 msgid "Searching in all sub-directories..." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add.py:258 +#: /home/kovid/work/calibre/src/calibre/gui2/add.py:258 msgid "Path error" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add.py:259 +#: /home/kovid/work/calibre/src/calibre/gui2/add.py:259 msgid "The specified directory could not be processed." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add.py:263 -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:810 +#: /home/kovid/work/calibre/src/calibre/gui2/add.py:263 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:810 msgid "No books" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add.py:330 +#: /home/kovid/work/calibre/src/calibre/gui2/add.py:330 msgid "Added" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add.py:343 +#: /home/kovid/work/calibre/src/calibre/gui2/add.py:343 msgid "Adding failed" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add.py:344 +#: /home/kovid/work/calibre/src/calibre/gui2/add.py:344 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/trunk/src/calibre/gui2/add.py:356 +#: /home/kovid/work/calibre/src/calibre/gui2/add.py:356 msgid "Duplicates found!" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add.py:357 +#: /home/kovid/work/calibre/src/calibre/gui2/add.py:357 msgid "Books with the same title as the following already exist in the database. Add them anyway?" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add.py:360 +#: /home/kovid/work/calibre/src/calibre/gui2/add.py:360 msgid "Adding duplicates..." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add.py:427 +#: /home/kovid/work/calibre/src/calibre/gui2/add.py:427 msgid "Saving..." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add.py:480 +#: /home/kovid/work/calibre/src/calibre/gui2/add.py:480 msgid "Saved" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/__init__.py:57 +#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/__init__.py:57 msgid "Searching for sub-folders" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/__init__.py:62 +#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/__init__.py:62 msgid "Searching for books" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/__init__.py:74 +#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/__init__.py:74 msgid "Looking for duplicates based on file hash" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/__init__.py:109 -#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/welcome_ui.py:65 +#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/__init__.py:109 +#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/welcome_ui.py:65 msgid "Choose root folder" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/__init__.py:137 +#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/__init__.py:137 msgid "Invalid root folder" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/__init__.py:138 +#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/__init__.py:138 msgid "is not a valid root folder" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/__init__.py:148 +#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/__init__.py:148 msgid "Add books to calibre" msgstr "" -#: /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:57 -#: /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 +#: /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:57 +#: /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 msgid "WizardPage" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/scan_ui.py:22 +#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/scan_ui.py:22 msgid "Scanning root folder for books" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/scan_ui.py:23 +#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/scan_ui.py:23 msgid "This may take a few minutes" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/welcome_ui.py:58 +#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/welcome_ui.py:58 msgid "Choose the location to add books from" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/welcome_ui.py:59 +#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/welcome_ui.py:59 msgid "Select a folder on your hard disk" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/welcome_ui.py:60 +#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/welcome_ui.py:60 msgid "" "

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.

\n" "

Choose a root folder. Books will be searched for only inside this folder and any sub-folders.

\n" "

Make sure that the folder you chose for your calibre library is not under the root folder you choose.

" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/welcome_ui.py:63 +#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/welcome_ui.py:63 msgid "&Root folder:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/welcome_ui.py:64 +#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/welcome_ui.py:64 msgid "This folder and its sub-folders will be scanned for books to import into calibre's library" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/welcome_ui.py:66 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/debug_ui.py:52 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/debug_ui.py:53 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel_ui.py:125 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:171 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/xexp_edit_ui.py:53 -#: /home/kovid/work/trunk/src/calibre/gui2/device_drivers/configwidget_ui.py:79 -#: /home/kovid/work/trunk/src/calibre/gui2/device_drivers/configwidget_ui.py:80 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library_ui.py:72 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:599 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:600 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:612 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:614 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:616 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:618 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:619 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:668 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:365 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:370 -#: /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:395 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:397 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:399 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:404 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:406 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/saved_search_editor_ui.py:87 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/saved_search_editor_ui.py:90 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories_ui.py:156 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories_ui.py:159 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories_ui.py:163 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories_ui.py:166 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_editor_ui.py:126 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_editor_ui.py:128 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_editor_ui.py:131 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_editor_ui.py:135 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_list_editor_ui.py:75 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_list_editor_ui.py:77 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles_ui.py:267 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles_ui.py:269 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles_ui.py:270 -#: /home/kovid/work/trunk/src/calibre/gui2/shortcuts_ui.py:75 -#: /home/kovid/work/trunk/src/calibre/gui2/shortcuts_ui.py:80 -#: /home/kovid/work/trunk/src/calibre/gui2/viewer/main_ui.py:186 +#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/welcome_ui.py:66 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/debug_ui.py:52 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/debug_ui.py:53 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:125 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:171 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xexp_edit_ui.py:53 +#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/configwidget_ui.py:79 +#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/configwidget_ui.py:80 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library_ui.py:72 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:599 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:600 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:612 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:614 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:616 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:618 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:619 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:668 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:365 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:370 +#: /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:395 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:397 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:399 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:404 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:406 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/saved_search_editor_ui.py:87 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/saved_search_editor_ui.py:90 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories_ui.py:156 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories_ui.py:159 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories_ui.py:163 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories_ui.py:166 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_editor_ui.py:126 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_editor_ui.py:128 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_editor_ui.py:131 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_editor_ui.py:135 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor_ui.py:75 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor_ui.py:77 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles_ui.py:267 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles_ui.py:269 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles_ui.py:270 +#: /home/kovid/work/calibre/src/calibre/gui2/shortcuts_ui.py:75 +#: /home/kovid/work/calibre/src/calibre/gui2/shortcuts_ui.py:80 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main_ui.py:186 msgid "..." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/welcome_ui.py:67 +#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/welcome_ui.py:67 msgid "Handle multiple files per book" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/welcome_ui.py:68 +#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/welcome_ui.py:68 msgid "&One book per folder, assumes every ebook file in a folder is the same book in a different format" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/add_wizard/welcome_ui.py:69 +#: /home/kovid/work/calibre/src/calibre/gui2/add_wizard/welcome_ui.py:69 msgid "&Multiple books per folder, assumes every ebook file is a different book" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/book_details.py:23 -#: /home/kovid/work/trunk/src/calibre/gui2/book_details.py:45 -#: /home/kovid/work/trunk/src/calibre/gui2/book_details.py:54 -#: /home/kovid/work/trunk/src/calibre/gui2/book_details.py:311 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/book_info.py:114 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/book_info.py:115 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/book_info.py:116 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/book_info.py:126 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/delete_matching_from_device.py:76 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:313 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:1065 +#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:23 +#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:45 +#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:54 +#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:311 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:114 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:115 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:116 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:126 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/delete_matching_from_device.py:76 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:313 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1065 msgid "Path" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/book_details.py:24 -#: /home/kovid/work/trunk/src/calibre/gui2/book_details.py:48 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/book_info.py:117 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/book_info.py:118 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/book_info.py:119 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/book_info.py:122 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:230 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:312 -#: /home/kovid/work/trunk/src/calibre/library/field_metadata.py:100 +#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:24 +#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:48 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:117 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:118 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:119 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:122 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:230 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:312 +#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:100 msgid "Formats" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/book_details.py:25 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:891 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:1068 +#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:25 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:891 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1068 msgid "Collections" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/book_details.py:47 -#: /home/kovid/work/trunk/src/calibre/gui2/book_details.py:56 +#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:47 +#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:56 msgid "Click to open" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/book_details.py:48 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:305 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:311 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:317 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:1074 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:1078 -#: /home/kovid/work/trunk/src/calibre/gui2/shortcuts.py:47 -#: /home/kovid/work/trunk/src/calibre/gui2/shortcuts_ui.py:73 -#: /home/kovid/work/trunk/src/calibre/gui2/shortcuts_ui.py:78 -#: /home/kovid/work/trunk/src/calibre/gui2/widgets.py:274 +#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:48 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:305 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:311 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:317 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1074 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1078 +#: /home/kovid/work/calibre/src/calibre/gui2/shortcuts.py:47 +#: /home/kovid/work/calibre/src/calibre/gui2/shortcuts_ui.py:73 +#: /home/kovid/work/calibre/src/calibre/gui2/shortcuts_ui.py:78 +#: /home/kovid/work/calibre/src/calibre/gui2/widgets.py:274 msgid "None" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/book_details.py:310 +#: /home/kovid/work/calibre/src/calibre/gui2/book_details.py:310 msgid "Click to open Book Details window" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_bibtex.py:16 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_bibtex.py:16 msgid "BibTeX Options" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_bibtex.py:17 -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_csv_xml.py:17 -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_epub_mobi.py:18 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/comic_input.py:16 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/epub_output.py:16 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/fb2_input.py:13 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/fb2_output.py:15 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output.py:20 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/mobi_output.py:21 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdb_input.py:13 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdb_output.py:17 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdf_input.py:13 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdf_output.py:18 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/rb_output.py:15 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/txt_input.py:13 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/txt_output.py:17 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_bibtex.py:17 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_csv_xml.py:17 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_epub_mobi.py:18 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input.py:16 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output.py:16 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_input.py:13 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_output.py:15 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output.py:20 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output.py:21 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_input.py:13 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_output.py:17 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_input.py:13 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_output.py:18 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/rb_output.py:15 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_input.py:13 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output.py:17 msgid "Options specific to" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_bibtex.py:17 -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_csv_xml.py:17 -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_epub_mobi.py:18 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/epub_output.py:16 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/fb2_output.py:15 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output.py:20 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/mobi_output.py:21 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdb_output.py:17 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdf_output.py:18 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/rb_output.py:15 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/txt_output.py:17 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_bibtex.py:17 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_csv_xml.py:17 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_epub_mobi.py:18 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output.py:16 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_output.py:15 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output.py:20 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output.py:21 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_output.py:17 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_output.py:18 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/rb_output.py:15 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output.py:17 msgid "output" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_bibtex_ui.py:81 -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_csv_xml_ui.py:37 -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_epub_mobi_ui.py:68 -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_tab_template_ui.py:27 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/comic_input_ui.py:88 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/debug_ui.py:49 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/epub_output_ui.py:48 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/fb2_input_ui.py:28 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/fb2_output_ui.py:28 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel_ui.py:119 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output_ui.py:115 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:166 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/mobi_output_ui.py:66 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/page_setup_ui.py:115 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdb_input_ui.py:31 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdb_output_ui.py:35 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdf_input_ui.py:38 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdf_output_ui.py:42 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/rb_output_ui.py:28 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection_ui.py:60 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/toc_ui.py:62 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/txt_input_ui.py:46 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/txt_output_ui.py:45 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/xexp_edit_ui.py:50 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:67 -#: /home/kovid/work/trunk/src/calibre/gui2/device_drivers/configwidget_ui.py:77 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/save_template_ui.py:41 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_item_ui.py:35 -#: /home/kovid/work/trunk/src/calibre/gui2/filename_pattern_ui.py:106 -#: /home/kovid/work/trunk/src/calibre/gui2/wizard/send_email_ui.py:107 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_bibtex_ui.py:81 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_csv_xml_ui.py:37 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_epub_mobi_ui.py:68 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_tab_template_ui.py:27 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input_ui.py:88 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/debug_ui.py:49 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output_ui.py:48 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_input_ui.py:28 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_output_ui.py:28 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:119 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:115 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:166 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output_ui.py:66 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/page_setup_ui.py:115 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_input_ui.py:31 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_output_ui.py:35 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_input_ui.py:38 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_output_ui.py:42 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/rb_output_ui.py:28 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:60 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/toc_ui.py:62 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_input_ui.py:46 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output_ui.py:45 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xexp_edit_ui.py:50 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:67 +#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/configwidget_ui.py:77 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/save_template_ui.py:41 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_item_ui.py:35 +#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:106 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/send_email_ui.py:107 msgid "Form" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_bibtex_ui.py:82 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_bibtex_ui.py:82 msgid "Bib file encoding:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_bibtex_ui.py:83 -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_csv_xml_ui.py:38 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_bibtex_ui.py:83 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_csv_xml_ui.py:38 msgid "Fields to include in output:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_bibtex_ui.py:84 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_bibtex_ui.py:84 msgid "ascii/LaTeX" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_bibtex_ui.py:85 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_bibtex_ui.py:85 msgid "Encoding configuration (change if you have errors) :" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_bibtex_ui.py:86 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_bibtex_ui.py:86 msgid "strict" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_bibtex_ui.py:87 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_bibtex_ui.py:87 msgid "replace" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_bibtex_ui.py:88 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_bibtex_ui.py:88 msgid "ignore" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_bibtex_ui.py:89 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_bibtex_ui.py:89 msgid "backslashreplace" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_bibtex_ui.py:90 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_bibtex_ui.py:90 msgid "BibTeX entry type:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_bibtex_ui.py:91 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_bibtex_ui.py:91 msgid "mixed" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_bibtex_ui.py:92 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_bibtex_ui.py:92 msgid "misc" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_bibtex_ui.py:93 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_bibtex_ui.py:93 msgid "book" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_bibtex_ui.py:94 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_bibtex_ui.py:94 msgid "Create a citation tag?" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_bibtex_ui.py:95 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_bibtex_ui.py:95 msgid "Expression to form the BibTeX citation tag:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_bibtex_ui.py:96 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_bibtex_ui.py:96 msgid "" "Some explanation about this template:\n" " -The fields availables are 'author_sort', 'authors', 'id',\n" @@ -3186,1666 +3186,1686 @@ msgid "" " -For time field, only the date will be used. " msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_csv_xml.py:16 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_csv_xml.py:16 msgid "CSV/XML Options" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_epub_mobi.py:17 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_epub_mobi.py:17 msgid "E-book options" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_epub_mobi.py:20 -#: /home/kovid/work/trunk/src/calibre/library/catalog.py:550 -#: /home/kovid/work/trunk/src/calibre/library/database2.py:1496 -#: /home/kovid/work/trunk/src/calibre/library/database2.py:1514 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_epub_mobi.py:20 +#: /home/kovid/work/calibre/src/calibre/library/catalog.py:550 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:1518 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:1536 msgid "Catalog" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_epub_mobi_ui.py:69 +#: +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_epub_mobi_ui.py:69 msgid "'Don't include this book' tag:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_epub_mobi_ui.py:70 +#: +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_epub_mobi_ui.py:70 msgid "'Mark this book as read' tag:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_epub_mobi_ui.py:71 +#: +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_epub_mobi_ui.py:71 msgid "Additional note tag prefix:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_epub_mobi_ui.py:72 +#: +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_epub_mobi_ui.py:72 msgid "Regex pattern describing tags to exclude as genres:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_epub_mobi_ui.py:73 +#: +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_epub_mobi_ui.py:73 msgid "" "Regex tips:\n" "- The default regex - \\[[\\w ]*\\] - excludes genre tags of the form [tag], e.g., [Amazon Freebie]\n" "- A regex pattern of a single dot excludes all genre tags, generating no Genre Section" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_epub_mobi_ui.py:76 +#: +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_epub_mobi_ui.py:76 msgid "Include 'Titles' Section" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_epub_mobi_ui.py:77 +#: +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_epub_mobi_ui.py:77 msgid "Include 'Recently Added' Section" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_epub_mobi_ui.py:78 +#: +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_epub_mobi_ui.py:78 msgid "Sort numbers as text" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/catalog/catalog_tab_template_ui.py:28 +#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_tab_template_ui.py:28 msgid "Tab template for catalog.ui" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/bulk.py:36 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/bulk.py:36 msgid "For settings that cannot be specified in this dialog, use the values saved in a previous conversion (if they exist) instead of using the defaults specified in the Preferences" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/bulk.py:67 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/bulk.py:67 msgid "Bulk Convert" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/bulk.py:80 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/single.py:185 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/bulk.py:80 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/single.py:185 msgid "Options specific to the output format." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/comic_input.py:15 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input.py:15 msgid "Comic Input" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/comic_input.py:16 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/fb2_input.py:13 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdb_input.py:13 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdf_input.py:13 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/txt_input.py:13 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input.py:16 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_input.py:13 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_input.py:13 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_input.py:13 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_input.py:13 msgid "input" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/comic_input_ui.py:89 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/comicconf_ui.py:94 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input_ui.py:89 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comicconf_ui.py:94 msgid "&Number of Colors:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/comic_input_ui.py:90 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/comicconf_ui.py:96 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input_ui.py:90 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comicconf_ui.py:96 msgid "Disable &normalize" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/comic_input_ui.py:91 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/comicconf_ui.py:97 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input_ui.py:91 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comicconf_ui.py:97 msgid "Keep &aspect ratio" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/comic_input_ui.py:92 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/comicconf_ui.py:98 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input_ui.py:92 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comicconf_ui.py:98 msgid "Disable &Sharpening" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/comic_input_ui.py:93 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/comicconf_ui.py:104 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input_ui.py:93 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comicconf_ui.py:104 msgid "Disable &Trimming" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/comic_input_ui.py:94 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/comicconf_ui.py:103 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input_ui.py:94 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comicconf_ui.py:103 msgid "&Wide" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/comic_input_ui.py:95 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/comicconf_ui.py:99 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input_ui.py:95 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comicconf_ui.py:99 msgid "&Landscape" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/comic_input_ui.py:96 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/comicconf_ui.py:101 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input_ui.py:96 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comicconf_ui.py:101 msgid "&Right to left" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/comic_input_ui.py:97 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/comicconf_ui.py:100 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input_ui.py:97 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comicconf_ui.py:100 msgid "Don't so&rt" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/comic_input_ui.py:98 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/comicconf_ui.py:102 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input_ui.py:98 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comicconf_ui.py:102 msgid "De&speckle" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/comic_input_ui.py:99 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input_ui.py:99 msgid "&Disable comic processing" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/comic_input_ui.py:100 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/single_ui.py:115 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input_ui.py:100 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/single_ui.py:115 msgid "&Output format:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/comic_input_ui.py:101 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input_ui.py:101 msgid "Disable conversion of images to &black and white" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/debug.py:19 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/debug.py:19 msgid "Debug" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/debug.py:21 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/debug.py:21 msgid "Debug the conversion process." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/debug.py:38 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/debug_ui.py:51 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/debug.py:38 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/debug_ui.py:51 msgid "Choose debug folder" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/debug.py:57 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/debug.py:57 msgid "Invalid debug directory" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/debug.py:58 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/debug.py:58 msgid "Failed to create debug directory" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/debug_ui.py:50 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/debug_ui.py:50 msgid "Choose a folder to put the debug output into. If you specify a folder, calibre will place a lot of debug output into it. This will be useful in understanding the conversion process and figuring out the correct values for conversion parameters like Table of Contents and Chapter Detection." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/debug_ui.py:54 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/debug_ui.py:54 msgid "The debug process outputs the intermediate HTML generated at various stages of the conversion process. This HTML can sometimes serve as a good starting point for hand editing a conversion." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/epub_output.py:15 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output.py:15 msgid "EPUB Output" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/epub_output_ui.py:49 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output_ui.py:49 msgid "Do not &split on page breaks" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/epub_output_ui.py:50 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output_ui.py:50 msgid "No default &cover" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/epub_output_ui.py:51 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output_ui.py:51 msgid "No &SVG cover" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/epub_output_ui.py:52 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output_ui.py:52 msgid "Preserve cover &aspect ratio" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/epub_output_ui.py:53 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output_ui.py:53 msgid "Split files &larger than:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/epub_output_ui.py:54 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output_ui.py:54 msgid " KB" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/fb2_input.py:12 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_input.py:12 msgid "FB2 Input" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/fb2_input_ui.py:29 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_input_ui.py:29 msgid "Do not insert a &Table of Contents at the beginning of the book." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/fb2_output.py:14 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_output.py:14 msgid "FB2 Output" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/fb2_output_ui.py:29 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdb_output_ui.py:37 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/rb_output_ui.py:29 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/txt_output_ui.py:47 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_output_ui.py:29 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_output_ui.py:37 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/rb_output_ui.py:29 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output_ui.py:47 msgid "&Inline TOC" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/font_key_ui.py:99 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/font_key_ui.py:99 msgid "Font rescaling wizard" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/font_key_ui.py:100 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/font_key_ui.py:100 msgid "" "

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.

\n" "

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.

\n" "

See the User Manual for a discussion of how font size rescaling works.

" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/font_key_ui.py:103 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/font_key_ui.py:103 msgid "&Output document" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/font_key_ui.py:104 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/font_key_ui.py:109 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/font_key_ui.py:104 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/font_key_ui.py:109 msgid "&Base font size:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/font_key_ui.py:105 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel_ui.py:123 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/font_key_ui.py:105 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:123 msgid "Font size &key:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/font_key_ui.py:106 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/font_key_ui.py:110 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/font_key_ui.py:112 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel_ui.py:122 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel_ui.py:127 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output_ui.py:118 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output_ui.py:120 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output_ui.py:125 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/page_setup_ui.py:121 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/page_setup_ui.py:123 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/page_setup_ui.py:125 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/page_setup_ui.py:127 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/font_key_ui.py:106 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/font_key_ui.py:110 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/font_key_ui.py:112 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:122 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:127 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:118 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:120 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:125 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/page_setup_ui.py:121 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/page_setup_ui.py:123 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/page_setup_ui.py:125 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/page_setup_ui.py:127 msgid " pt" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/font_key_ui.py:107 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/font_key_ui.py:107 msgid "Use &default values" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/font_key_ui.py:108 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/font_key_ui.py:108 msgid "&Input document" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/font_key_ui.py:111 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/font_key_ui.py:111 msgid "&Font size: " msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/font_key_ui.py:113 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/font_key_ui.py:113 msgid " will map to size: " msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/font_key_ui.py:114 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/font_key_ui.py:114 msgid "0.0 pt" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel.py:16 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel.py:16 msgid "Look & Feel" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel.py:18 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel.py:18 msgid "Control the look and feel of the output" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel.py:30 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel.py:30 msgid "Original" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel.py:31 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel.py:31 msgid "Left align" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel.py:32 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel.py:32 msgid "Justify text" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel_ui.py:120 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:120 msgid "&Disable font size rescaling" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel_ui.py:121 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:121 msgid "Base &font size:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel_ui.py:124 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:124 msgid "Wizard to help you choose an appropriate font size key" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel_ui.py:126 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:126 msgid "Line &height:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel_ui.py:128 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:128 msgid "Input character &encoding:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel_ui.py:129 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:129 msgid "Remove &spacing between paragraphs" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel_ui.py:130 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:130 msgid "Indent size:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel_ui.py:131 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:131 msgid "

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/trunk/src/calibre/gui2/convert/look_and_feel_ui.py:132 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:132 msgid " em" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel_ui.py:133 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:133 msgid "Text justification:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel_ui.py:134 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:134 msgid "&Linearize tables" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel_ui.py:135 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:135 msgid "Extra &CSS" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel_ui.py:136 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:136 msgid "&Transliterate unicode characters to ASCII" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel_ui.py:137 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:137 msgid "Insert &blank line" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/look_and_feel_ui.py:138 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:138 msgid "Keep &ligatures" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output.py:19 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output.py:19 msgid "LRF Output" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output_ui.py:116 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:116 msgid "Enable &autorotation of wide images" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output_ui.py:117 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:117 msgid "&Wordspace:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output_ui.py:119 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:119 msgid "Minimum para. &indent:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output_ui.py:121 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:121 msgid "Render &tables as images" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output_ui.py:122 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:122 msgid "Text size multiplier for text in rendered tables:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output_ui.py:123 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:123 msgid "Add &header" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output_ui.py:124 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:124 msgid "Header &separation:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output_ui.py:126 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:126 msgid "Header &format:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output_ui.py:127 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:127 msgid "&Embed fonts" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output_ui.py:128 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:128 msgid "&Serif font family:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output_ui.py:129 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:129 msgid "S&ans-serif font family:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/lrf_output_ui.py:130 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:130 msgid "&Monospaced font family:" msgstr "" -#: /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:195 +#: /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:195 msgid "Metadata" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata.py:43 +#: /home/kovid/work/calibre/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/trunk/src/calibre/gui2/convert/metadata.py:164 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:111 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata.py:164 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:111 msgid "Choose cover for " msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata.py:171 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:118 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata.py:171 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:118 msgid "Cannot read" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata.py:172 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:119 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata.py:172 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:119 msgid "You do not have permission to read the file: " msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata.py:180 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata.py:187 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:127 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata.py:180 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata.py:187 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:127 msgid "Error reading file" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata.py:181 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:128 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata.py:181 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:128 msgid "

There was an error reading from file:
" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata.py:188 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:136 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata.py:188 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:136 msgid " is not a valid picture" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:167 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:401 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:167 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:401 msgid "Book Cover" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:168 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:168 msgid "Use cover from &source file" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:169 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:402 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:169 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:402 msgid "Change &cover image:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:170 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:403 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:170 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:403 msgid "Browse for an image to use as the cover of this book." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:172 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:362 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:172 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:362 msgid "&Title: " msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:173 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:363 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:173 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:363 msgid "Change the title of this book" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:174 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:158 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:366 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:174 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:158 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:366 msgid "&Author(s): " msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:175 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:175 msgid "Author So&rt:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:176 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:176 msgid "Change the author(s) of this book. Multiple authors should be separated by a comma" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:177 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:167 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:375 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:177 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:167 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:375 msgid "&Publisher: " msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:178 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:376 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:178 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:376 msgid "Ta&gs: " msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:179 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:169 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:377 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:179 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:169 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:377 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/trunk/src/calibre/gui2/convert/metadata_ui.py:180 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:174 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:380 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:180 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:174 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:380 msgid "&Series:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:181 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:182 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:175 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:176 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:381 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:382 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:181 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:182 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:175 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:176 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:381 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:382 msgid "List of known series. You can add new series." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/metadata_ui.py:183 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:387 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:183 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:387 msgid "Book " msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/mobi_output.py:20 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output.py:20 msgid "MOBI Output" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/mobi_output.py:42 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output.py:42 msgid "Default" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/mobi_output_ui.py:67 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output_ui.py:67 msgid "&Title for Table of Contents:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/mobi_output_ui.py:68 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output_ui.py:68 msgid "Rescale images for &Palm devices" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/mobi_output_ui.py:69 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output_ui.py:69 msgid "Use author &sort for author" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/mobi_output_ui.py:70 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output_ui.py:70 msgid "Disable compression of the file contents" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/mobi_output_ui.py:71 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output_ui.py:71 msgid "Do not add Table of Contents to book" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/mobi_output_ui.py:72 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output_ui.py:72 msgid "Kindle options" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/mobi_output_ui.py:73 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output_ui.py:73 msgid "Periodical masthead font:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/mobi_output_ui.py:74 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output_ui.py:74 msgid "Personal Doc tag:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/page_setup.py:35 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/page_setup.py:35 msgid "Page Setup" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/page_setup_ui.py:116 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/page_setup_ui.py:116 msgid "&Output profile:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/page_setup_ui.py:117 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/page_setup_ui.py:117 msgid "Profile description" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/page_setup_ui.py:118 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/page_setup_ui.py:118 msgid "&Input profile:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/page_setup_ui.py:119 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/page_setup_ui.py:119 msgid "Margins" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/page_setup_ui.py:120 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/page_setup_ui.py:120 msgid "&Left:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/page_setup_ui.py:122 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/page_setup_ui.py:122 msgid "&Top:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/page_setup_ui.py:124 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/page_setup_ui.py:124 msgid "&Right:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/page_setup_ui.py:126 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/page_setup_ui.py:126 msgid "&Bottom:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdb_input.py:12 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_input.py:12 msgid "PDB Input" msgstr "" -#: /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 +#: /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 msgid "Treat each &line as a paragraph" msgstr "" -#: /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 +#: /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 msgid "Assume print formatting" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdb_output.py:16 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_output.py:16 msgid "PDB Output" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdb_output_ui.py:36 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_output_ui.py:36 msgid "&Format:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdf_input.py:12 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_input.py:12 msgid "PDF Input" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdf_input_ui.py:39 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_input_ui.py:39 msgid "Line &Un-Wrapping Factor:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdf_input_ui.py:40 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_input_ui.py:40 msgid "No &Images" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdf_output.py:17 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_output.py:17 msgid "PDF Output" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdf_output_ui.py:43 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_output_ui.py:43 msgid "&Paper Size:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdf_output_ui.py:44 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_output_ui.py:44 msgid "&Orientation:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/pdf_output_ui.py:45 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_output_ui.py:45 msgid "Preserve &aspect ratio of cover" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/rb_output.py:14 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/rb_output.py:14 msgid "RB Output" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/regex_builder.py:83 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/regex_builder.py:83 msgid "No formats available" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/regex_builder.py:84 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/regex_builder.py:84 msgid "Cannot build regex using the GUI builder without a book." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/regex_builder.py:103 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/regex_builder.py:103 msgid "Open book" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/regex_builder_ui.py:52 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/regex_builder_ui.py:52 msgid "Regex Builder" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/regex_builder_ui.py:53 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/regex_builder_ui.py:53 msgid "Preview" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/regex_builder_ui.py:54 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/regex_builder_ui.py:54 msgid "Regex:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/regex_builder_ui.py:55 -#: /home/kovid/work/trunk/src/calibre/gui2/filename_pattern_ui.py:117 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/regex_builder_ui.py:55 +#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:117 msgid "Test" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/single.py:171 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/single.py:171 msgid "Convert" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/single.py:196 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/single.py:196 msgid "Options specific to the input format." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/single_ui.py:112 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/book_info_ui.py:64 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/comicconf_ui.py:91 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/progress_ui.py:48 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/single_ui.py:112 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info_ui.py:64 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comicconf_ui.py:91 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/progress_ui.py:48 msgid "Dialog" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/single_ui.py:113 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/single_ui.py:113 msgid "&Input format:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/single_ui.py:114 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/single_ui.py:114 msgid "Use &saved conversion settings for individual books" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection.py:17 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:17 msgid "" "Structure\n" "Detection" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection.py:19 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:19 msgid "Fine tune the detection of chapter headings and other document structure." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection.py:34 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:34 msgid "Detect chapters at (XPath expression):" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection.py:35 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:35 msgid "Insert page breaks before (XPath expression):" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection.py:37 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:37 msgid "Header regular expression:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection.py:40 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:40 msgid "Footer regular expression:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection.py:56 -#: /home/kovid/work/trunk/src/calibre/gui2/widgets.py:76 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:56 +#: /home/kovid/work/calibre/src/calibre/gui2/widgets.py:76 msgid "Invalid regular expression" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection.py:57 -#: /home/kovid/work/trunk/src/calibre/gui2/widgets.py:77 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:57 +#: /home/kovid/work/calibre/src/calibre/gui2/widgets.py:77 msgid "Invalid regular expression: %s" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection.py:62 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/toc.py:38 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:62 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/toc.py:38 msgid "Invalid XPath" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection.py:63 -#: /home/kovid/work/trunk/src/calibre/gui2/convert/toc.py:39 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:63 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/toc.py:39 msgid "The XPath expression %s is invalid." msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection_ui.py:61 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:61 msgid "Chapter &mark:" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection_ui.py:62 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:62 msgid "Remove first &image" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection_ui.py:63 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:63 msgid "Insert &metadata as page at start of book" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection_ui.py:64 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:64 msgid "&Preprocess input file to possibly improve structure detection" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection_ui.py:65 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:65 msgid "Remove F&ooter" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/convert/structure_detection_ui.py:66 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:66 msgid "Remove H&eader" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/toc.py:16 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/toc.py:16 msgid "" "Table of\n" "Contents" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/toc.py:18 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/toc.py:18 msgid "Control the creation/conversion of the Table of Contents." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/toc.py:29 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/toc.py:29 msgid "Level &1 TOC (XPath expression):" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/toc.py:30 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/toc.py:30 msgid "Level &2 TOC (XPath expression):" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/toc.py:31 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/toc.py:31 msgid "Level &3 TOC (XPath expression):" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/toc_ui.py:63 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/toc_ui.py:63 msgid "Do not add &detected chapters to the Table of Contents" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/toc_ui.py:64 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/toc_ui.py:64 msgid "Number of &links to add to Table of Contents" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/toc_ui.py:65 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/toc_ui.py:65 msgid "Chapter &threshold" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/toc_ui.py:66 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/toc_ui.py:66 msgid "&Force use of auto-generated Table of Contents" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/toc_ui.py:67 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/toc_ui.py:67 msgid "TOC &Filter:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/txt_input.py:12 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_input.py:12 msgid "TXT Input" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/txt_input_ui.py:49 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_input_ui.py:49 msgid "Process using markdown" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/txt_input_ui.py:50 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_input_ui.py:50 msgid "

Markdown is a simple markup language for text files, that allows for advanced formatting. To learn more visit markdown." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/txt_input_ui.py:51 +#: /home/kovid/work/calibre/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/trunk/src/calibre/gui2/convert/txt_input_ui.py:52 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_input_ui.py:52 msgid "Preserve &spaces" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/txt_output.py:16 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output.py:16 msgid "TXT Output" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/txt_output_ui.py:46 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output_ui.py:46 msgid "&Line ending style:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/txt_output_ui.py:48 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output_ui.py:48 msgid "&Maximum line length:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/txt_output_ui.py:49 -msgid "Force maximum line lenght" +#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output_ui.py:49 +msgid "Force maximum line length" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/xexp_edit_ui.py:51 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/book_info_ui.py:65 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/book_info_ui.py:66 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_format_ui.py:41 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/confirm_delete_ui.py:49 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/password_ui.py:57 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/progress_ui.py:49 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/progress_ui.py:50 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xexp_edit_ui.py:51 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info_ui.py:65 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info_ui.py:66 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_format_ui.py:41 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/confirm_delete_ui.py:49 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/password_ui.py:57 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/progress_ui.py:49 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/progress_ui.py:50 msgid "TextLabel" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/xexp_edit_ui.py:52 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xexp_edit_ui.py:52 msgid "Use a wizard to help construct the XPath expression" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:68 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:68 msgid "Match HTML &tags with tag name:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:69 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:69 msgid "*" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:70 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:70 msgid "a" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:71 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:71 msgid "br" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:72 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:72 msgid "div" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:73 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:73 msgid "h1" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:74 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:74 msgid "h2" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:75 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:75 msgid "h3" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:76 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:76 msgid "h4" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:77 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:77 msgid "h5" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:78 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:78 msgid "h6" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:79 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:79 msgid "hr" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:80 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:80 msgid "span" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:81 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:81 msgid "Having the &attribute:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:82 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:82 msgid "With &value:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:83 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:83 msgid "(A regular expression)" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/convert/xpath_wizard_ui.py:84 +#: /home/kovid/work/calibre/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/trunk/src/calibre/gui2/cover_flow.py:127 -msgid "Cover browser could not be loaded" -msgstr "" - -#: /home/kovid/work/trunk/src/calibre/gui2/cover_flow.py:179 +#: /home/kovid/work/calibre/src/calibre/gui2/cover_flow.py:118 msgid "Browse by covers" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:53 -#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:78 -#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:102 -#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:139 -#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:158 -#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:264 -#: /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 +#: /home/kovid/work/calibre/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:53 +#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:78 +#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:102 +#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:139 +#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:158 +#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:264 +#: /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 msgid "Undefined" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:53 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:131 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:133 +#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:53 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:131 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:133 msgid "Yes" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:53 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:132 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:134 +#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:53 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:132 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:134 msgid "No" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:116 +#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:116 msgid "star(s)" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:117 +#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:117 msgid "Unrated" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:150 +#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:150 msgid "Set '%s' to today" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:260 +#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:260 msgid " index:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:443 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:183 +#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:443 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:183 msgid "Automatically number books in this series" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:486 +#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:486 msgid "Remove all tags" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:507 +#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:507 msgid "tags to add" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/custom_column_widgets.py:512 +#: /home/kovid/work/calibre/src/calibre/gui2/custom_column_widgets.py:512 msgid "tags to remove" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:49 -#: /home/kovid/work/trunk/src/calibre/utils/ipc/job.py:135 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:49 +#: /home/kovid/work/calibre/src/calibre/utils/ipc/job.py:135 msgid "No details available." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:166 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:166 msgid "Device no longer connected." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:284 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:284 msgid "Get device information" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:295 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:295 msgid "Get list of books on device" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:305 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:305 msgid "Get annotations from device" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:314 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:314 msgid "Send metadata to device" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:319 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:319 msgid "Send collections to device" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:343 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:343 msgid "Upload %d books to device" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:358 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:358 msgid "Delete books from device" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:375 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:375 msgid "Download books from device" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:385 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:385 msgid "View book on device" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:419 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:419 msgid "Set default send to device action" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:425 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:425 msgid "Send to main memory" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:427 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:427 msgid "Send to storage card A" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:429 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:429 msgid "Send to storage card B" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:434 -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:443 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:434 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:443 msgid "Main Memory" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:454 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:454 msgid "Send and delete from library" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:455 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:455 msgid "Send specific format" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:491 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:491 msgid "Eject device" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:499 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:499 msgid "Fetch annotations (experimental)" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:609 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:609 msgid "Error communicating with device" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:631 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:631 msgid "Select folder to open as device" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:675 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:675 msgid "Failed" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:681 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:681 msgid "Error talking to device" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:682 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:682 msgid "There was a temporary error talking to the device. Please unplug and reconnect the device and or reboot." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:724 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:724 msgid "Device: " msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:726 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:726 msgid " detected." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:811 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:811 msgid "selected to send" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:816 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:816 msgid "Choose format to send to device" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:825 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:825 msgid "No device" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:826 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:826 msgid "Cannot send: No device is connected" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:829 -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:833 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:829 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:833 msgid "No card" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:830 -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:834 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:830 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:834 msgid "Cannot send: Device has no storage card" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:875 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:875 msgid "E-book:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:878 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:878 msgid "Attached, you will find the e-book" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:879 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:181 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:879 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:181 msgid "by" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:880 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:880 msgid "in the %s format." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:893 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:893 msgid "Sending email to" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:923 -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:931 -#: /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 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:923 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:931 +#: /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 msgid "No suitable formats" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:924 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:924 msgid "Auto convert the following books before sending via email?" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:932 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:932 msgid "Could not email the following books as no suitable formats were found:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:950 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:950 msgid "Failed to email books" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:951 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:951 msgid "Failed to email the following books:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:955 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:955 msgid "Sent by email:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:984 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:984 msgid "News:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:985 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:985 msgid "Attached is the" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:996 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:996 msgid "Sent news to" msgstr "" -#: /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 +#: /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 msgid "Auto convert the following books before uploading to the device?" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:1056 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:1056 msgid "Sending catalogs to device." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:1120 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:1120 msgid "Sending news to device." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:1173 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:1173 msgid "Sending books to device." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:1215 +#: /home/kovid/work/calibre/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/trunk/src/calibre/gui2/device.py:1277 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:1277 msgid "No space on device" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/device.py:1278 +#: /home/kovid/work/calibre/src/calibre/gui2/device.py:1278 msgid "

Cannot upload books to device there is no more free space available " msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/device_drivers/configwidget_ui.py:78 +#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/configwidget_ui.py:78 msgid "Select available formats and their order for this device" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/device_drivers/configwidget_ui.py:82 +#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/configwidget_ui.py:82 msgid "Use sub directories" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/device_drivers/configwidget_ui.py:83 +#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/configwidget_ui.py:83 msgid "Use author sort for author" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/device_drivers/configwidget_ui.py:85 +#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/configwidget_ui.py:85 msgid "Save &template:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/book_info_ui.py:68 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/add_from_isbn_ui.py:43 +msgid "Add books by ISBN" +msgstr "" + +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/add_from_isbn_ui.py:44 +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:45 +msgid "&Paste from clipboard" +msgstr "" + +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info_ui.py:68 msgid "Fit &cover to view" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/book_info_ui.py:69 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info_ui.py:69 msgid "&Previous" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/book_info_ui.py:70 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info_ui.py:70 msgid "&Next" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/catalog.py:38 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/catalog.py:38 msgid "My Books" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/catalog_ui.py:69 -#: /home/kovid/work/trunk/src/calibre/gui2/tools.py:289 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/catalog_ui.py:69 +#: /home/kovid/work/calibre/src/calibre/gui2/tools.py:289 msgid "Generate catalog" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/catalog_ui.py:70 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/catalog_ui.py:70 msgid "Generate catalog for {0} books" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/catalog_ui.py:71 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/catalog_ui.py:71 msgid "Catalog &format:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/catalog_ui.py:72 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/catalog_ui.py:72 msgid "Catalog &title (existing catalog with the same title will be replaced):" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/catalog_ui.py:73 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/catalog_ui.py:73 msgid "&Send catalog to device automatically" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/catalog_ui.py:74 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/catalog_ui.py:74 msgid "Catalog options" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_format_ui.py:40 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_format_ui.py:40 msgid "Choose Format" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library.py:38 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library.py:38 msgid "Choose location for calibre library" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library.py:45 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library.py:45 msgid "Same as current" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library.py:46 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library.py:46 msgid "The location %s contains the current calibre library" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library.py:51 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library.py:51 msgid "No existing library found" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library.py:52 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library.py:52 msgid "There is no existing calibre library at %s" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library.py:56 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library.py:56 msgid "Not empty" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library.py:57 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library.py:57 msgid "The folder %s is not empty. Please choose an empty folder" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library.py:80 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library.py:80 msgid "No location" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library.py:80 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library.py:80 msgid "No location selected" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library_ui.py:66 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library_ui.py:66 msgid "Choose your calibre library" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library_ui.py:67 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library_ui.py:67 msgid "Your calibre library is currently located at {0}" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library_ui.py:68 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library_ui.py:68 msgid "New &Location:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library_ui.py:69 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library_ui.py:69 msgid "Use &existing library at the new location" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library_ui.py:70 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library_ui.py:70 msgid "&Create an empty library at the new location" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/choose_library_ui.py:71 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/choose_library_ui.py:71 msgid "&Move current library to new location" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/comicconf.py:33 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comicconf.py:33 msgid "Set defaults for conversion of comics (CBR/CBZ files)" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/comicconf.py:48 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comicconf.py:48 msgid "Set options for converting %s" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/comicconf_ui.py:92 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comicconf_ui.py:92 msgid "&Title:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/comicconf_ui.py:93 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comicconf_ui.py:93 msgid "&Author(s):" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/comicconf_ui.py:95 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comicconf_ui.py:95 msgid "&Profile:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/comments_dialog_ui.py:41 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comments_dialog_ui.py:41 msgid "Edit Comments" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:174 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:174 msgid "%(plugin_type)s %(plugins)s" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:175 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:175 msgid "plugins" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:184 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:184 msgid "" "\n" "Customization: " msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:199 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:199 msgid "General" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:200 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:200 msgid "Interface" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:201 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:201 msgid "Conversion" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:202 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:202 msgid "" "Email\n" "Delivery" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:203 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:203 msgid "Add/Save" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:204 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:204 msgid "Advanced" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:205 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:205 msgid "" "Content\n" "Server" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:206 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:206 msgid "Plugins" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:230 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:230 msgid "Auto send" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:230 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:230 msgid "Email" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:235 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:235 msgid "Formats to email. The first matching format will be sent." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:236 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:236 msgid "If checked, downloaded news will be automatically mailed
to this email address (provided it is in one of the listed formats)." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:310 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:310 msgid "new email address" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:492 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:492 msgid "Wide" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:493 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:493 msgid "Narrow" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:502 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:502 msgid "Medium" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:502 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:502 msgid "Small" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:503 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:503 msgid "Large" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:509 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:509 msgid "Always" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:509 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:509 msgid "Automatic" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:510 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:510 msgid "Never" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:534 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:534 msgid "Done" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:535 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:535 msgid "Confirmation dialogs have all been reset" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:540 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:540 msgid "System port selected" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:541 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:541 msgid "The value %d you have chosen for the content server port is a system port. Your operating system may not allow the server to run on this port. To be safe choose a port number larger than 1024." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:561 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:561 msgid "Failed to install command line tools." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:564 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:564 msgid "Command line tools installed" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:565 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:565 msgid "Command line tools installed in" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:566 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:566 msgid "If you move calibre.app, you have to re-install the command line tools." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:617 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:617 msgid "No valid plugin path" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:618 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:618 msgid "%s is not a valid plugin path" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:621 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:621 msgid "Choose plugin" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:633 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:633 msgid "Plugin cannot be disabled" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:634 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:634 msgid "The plugin: %s cannot be disabled" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:643 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:643 msgid "Plugin not customizable" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:644 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:644 msgid "Plugin: %s does not need customization" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:652 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:652 msgid "Customize" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:690 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:690 msgid "Cannot remove builtin plugin" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:691 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:691 msgid " cannot be removed. It is a builtin plugin. Try disabling it instead." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:707 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:706 msgid "Invalid tweaks" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:708 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:707 msgid "The tweaks you entered are invalid, try resetting the tweaks to default and changing them one by one until you find the invalid setting." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:738 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:737 msgid "You must select a column to delete it" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:743 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:742 msgid "The selected column is not a custom column" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:744 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/confirm_delete_ui.py:48 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:743 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/confirm_delete_ui.py:48 msgid "Are you sure?" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:745 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:744 msgid "Do you really want to delete column %s and all its data?" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:812 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:811 msgid "Error log:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:819 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:818 msgid "Access log:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:847 -#: /home/kovid/work/trunk/src/calibre/gui2/ui.py:318 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:846 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:318 msgid "Failed to start content server" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:872 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:871 msgid "Invalid size" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:873 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:872 msgid "The size %s is invalid. must be of the form widthxheight" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:936 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:935 msgid "Must restart" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:937 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:936 msgid "The changes you made require that Calibre be restarted. Please restart as soon as practical." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:971 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:970 msgid "Checking database integrity" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:991 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:990 msgid "Failed to check database integrity" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:996 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:995 msgid "Some inconsistencies found" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/__init__.py:997 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:996 msgid "The following books had formats listed in the database that are not actually available. The entries for the formats have been removed. You should check them manually. This can happen if you manipulate the files in the library folder directly." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/add_save_ui.py:133 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/add_save_ui.py:133 msgid "TabWidget" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/add_save_ui.py:134 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/add_save_ui.py:134 msgid "Here you can control how calibre will read metadata from the files you add to it. calibre can either read metadata from the contents of the file, or from the filename." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/add_save_ui.py:135 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/add_save_ui.py:135 msgid "Read metadata only from &file name" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/add_save_ui.py:136 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/add_save_ui.py:136 msgid "Swap the firstname and lastname of the author. This affects only metadata read from file names." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/add_save_ui.py:137 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/add_save_ui.py:137 msgid "&Swap author firstname and lastname" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/add_save_ui.py:138 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/add_save_ui.py:138 msgid "" "If an existing book with a similar title and author is found that does not have the format being added, the format is added\n" "to the existing book, instead of creating a new entry. If the existing book already has the format, then it is silently ignored.\n" @@ -4853,599 +4873,594 @@ msgid "" "Title match ignores leading indefinite articles (\"the\", \"a\", \"an\"), punctuation, case, etc. Author match is exact." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/add_save_ui.py:142 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/add_save_ui.py:142 msgid "If books with similar titles and authors found, &merge the new files automatically" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/add_save_ui.py:143 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/add_save_ui.py:143 msgid "&Configure metadata from file name" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/add_save_ui.py:144 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/add_save_ui.py:144 msgid "&Adding books" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/add_save_ui.py:145 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/add_save_ui.py:145 msgid "Here you can control how calibre will save your books when you click the Save to Disk button:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/add_save_ui.py:146 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/add_save_ui.py:146 msgid "Save &cover separately" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/add_save_ui.py:147 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/add_save_ui.py:147 msgid "Update &metadata in saved copies" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/add_save_ui.py:148 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/add_save_ui.py:148 msgid "Save metadata in &OPF file" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/add_save_ui.py:149 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/add_save_ui.py:149 msgid "Convert non-English characters to &English equivalents" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/add_save_ui.py:150 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/add_save_ui.py:150 msgid "Format &dates as:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/add_save_ui.py:151 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/add_save_ui.py:151 msgid "File &formats to save:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/add_save_ui.py:152 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/add_save_ui.py:152 msgid "Replace space with &underscores" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/add_save_ui.py:153 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/add_save_ui.py:153 msgid "Change paths to &lowercase" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/add_save_ui.py:154 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/add_save_ui.py:154 msgid "&Saving books" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/add_save_ui.py:155 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/add_save_ui.py:155 msgid "Metadata &management:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/add_save_ui.py:156 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/add_save_ui.py:156 msgid "Manual management" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/add_save_ui.py:157 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/add_save_ui.py:157 msgid "Only on send" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/add_save_ui.py:158 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/add_save_ui.py:158 msgid "Automatic management" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/add_save_ui.py:159 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/add_save_ui.py:159 msgid "" "

  • Manual Management: Calibre updates the metadata and adds collections only when a book is sent. With this option, calibre will never remove a collection.
  • \n" "
  • Only on send: Calibre updates metadata and adds/removes collections for a book only when it is sent to the device.
  • \n" "
  • Automatic management: Calibre automatically keeps metadata on the device in sync with the calibre library, on every connect
  • " msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/add_save_ui.py:162 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/add_save_ui.py:162 msgid "Here you can control how calibre will save your books when you click the Send to Device button. This setting can be overriden for individual devices by customizing the device interface plugins in Preferences->Plugins" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/add_save_ui.py:163 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/add_save_ui.py:163 msgid "Sending to &device" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:584 -#: /home/kovid/work/trunk/src/calibre/gui2/layout.py:474 -#: /home/kovid/work/trunk/src/calibre/gui2/layout.py:616 -#: /home/kovid/work/trunk/src/calibre/gui2/viewer/main_ui.py:201 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:584 +#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:474 +#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:618 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main_ui.py:201 msgid "Preferences" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:585 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:585 msgid "Show notification when &new version is available" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:586 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:586 msgid "Download &social metadata (tags/ratings/etc.) by default" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:587 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:587 msgid "&Overwrite author and title by default when fetching metadata" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:588 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:588 msgid "Default network &timeout:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:589 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:589 msgid "Set the default timeout for network fetches (i.e. anytime we go out to the internet to get information)" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:590 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:590 msgid " seconds" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:591 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:591 msgid "Choose &language (requires restart):" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:592 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:592 msgid "Normal" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:593 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:593 msgid "High" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:594 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:594 msgid "Low" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:595 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:595 msgid "Job &priority:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:596 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:596 msgid "Preferred &output format:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:597 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:597 msgid "Reset all disabled &confirmation dialogs" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:598 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:598 msgid "Preferred &input format order:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:601 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:601 msgid "Use &Roman numerals for series number" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:602 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:602 msgid "Enable system &tray icon (needs restart)" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:603 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:603 msgid "Show ¬ifications in system tray" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:604 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:604 msgid "Show &splash screen at startup" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:605 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:605 msgid "Show cover &browser in a separate window (needs restart)" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:606 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:606 msgid "Show &average ratings in the tags browser" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:607 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:607 msgid "Search as you type" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:608 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:608 msgid "Automatically send downloaded &news to ebook reader" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:609 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:609 msgid "&Delete news from library when it is automatically sent to reader" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:610 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:610 msgid "&Number of covers to show in browse mode (needs restart):" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:611 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:611 msgid "Select visible &columns in library view" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:613 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:613 msgid "Remove a user-defined column" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:615 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:615 msgid "Add a user-defined column" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:617 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:617 msgid "Edit settings of a user-defined column" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:620 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:620 msgid "Use internal &viewer for:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:621 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:621 msgid "User Interface &layout (needs restart):" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:622 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:622 msgid "Disable all animations. Useful if you have a slow/old computer." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:623 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:623 msgid "Disable &animations" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:624 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:624 msgid "Show &donate button (restart)" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:625 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:625 msgid "&Toolbar" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:626 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:626 msgid "&Icon size:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:627 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:627 msgid "Show &text under icons:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:628 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:628 msgid "Add an email address to which to send books" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:629 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:629 msgid "&Add email" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:630 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:630 msgid "Make &default" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:631 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:631 msgid "&Remove email" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:632 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:632 msgid "calibre can send your books to you (or your reader) by email. Emails will be automatically sent for downloaded news to all email addresses that have Auto-send checked." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:633 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:633 msgid "&Maximum number of waiting worker processes (needs restart):" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:634 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:634 msgid "Limit the max. simultaneous jobs to the available CPU &cores" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:635 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:635 msgid "Debug &device detection" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:636 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:636 msgid "&Check database integrity" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:637 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:637 msgid "Open calibre &configuration directory" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:638 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:638 msgid "&Install command line tools" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:639 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:639 msgid "&Miscellaneous" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:640 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:640 msgid "Values for the tweaks are shown below. Edit them to change the behavior of calibre" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:641 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:641 msgid "All available tweaks" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:642 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:642 msgid "&Current tweaks" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:643 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:643 msgid "&Restore to defaults" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:644 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:644 msgid "&Tweaks" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:645 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:645 msgid "calibre contains a network server that allows you to access your book collection using a browser from anywhere in the world. Any changes to the settings will only take effect after a server restart." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:646 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:646 msgid "Server &port:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:647 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/password_ui.py:58 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:212 -#: /home/kovid/work/trunk/src/calibre/gui2/wizard/send_email_ui.py:117 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:647 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/password_ui.py:58 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:212 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/send_email_ui.py:117 msgid "&Username:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:648 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/password_ui.py:59 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:213 -#: /home/kovid/work/trunk/src/calibre/gui2/wizard/send_email_ui.py:119 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:648 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/password_ui.py:59 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:213 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/send_email_ui.py:119 msgid "&Password:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:649 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:649 msgid "If you leave the password blank, anyone will be able to access your book collection using the web interface." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:650 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:650 msgid "The maximum size (widthxheight) for displayed covers. Larger covers are resized. " msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:651 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:651 msgid "Max. &cover size:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:652 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/password_ui.py:60 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:214 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:652 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/password_ui.py:60 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:214 msgid "&Show password" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:653 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:653 msgid "Max. &OPDS items per query:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:654 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:654 msgid "Max. OPDS &ungrouped items:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:655 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:655 msgid "&Start Server" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:656 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:656 msgid "St&op Server" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:657 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:657 msgid "&Test Server" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:658 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:658 msgid "Run server &automatically on startup" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:659 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:659 msgid "View &server logs" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:660 -#: /home/kovid/work/trunk/src/calibre/gui2/wizard/stanza_ui.py:46 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:660 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/stanza_ui.py:46 msgid "" "

    Remember to leave calibre running as the server only runs as long as calibre is running.\n" "

    Stanza should see your calibre collection automatically. If not, try adding the URL http://myhostname:8080 as a new catalog in the Stanza reader on your iPhone. Here myhostname should be the fully qualified hostname or the IP address of the computer calibre is running on." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:662 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:662 msgid "Here you can customize the behavior of Calibre by controlling what plugins it uses." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:663 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:663 msgid "Enable/&Disable plugin" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:664 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:664 msgid "&Customize plugin" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:665 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:665 msgid "&Remove plugin" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:666 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:666 msgid "Add new plugin" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:667 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:667 msgid "Plugin &file:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/config_ui.py:669 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/config_ui.py:669 msgid "&Add" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:125 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:125 msgid "Create Tag-based Column" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:126 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:126 msgid "Lookup name" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:127 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:127 msgid "Column heading" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:128 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:128 msgid "Column type" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:129 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:129 msgid "Use brackets" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:130 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:130 msgid "Values can be edited" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:135 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:135 msgid "Text" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:136 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:136 msgid "Number" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:137 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_custom_column.py:31 -#: /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:889 -#: /home/kovid/work/trunk/src/calibre/library/server/opds.py:549 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:137 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_custom_column.py:31 +#: /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:889 +#: /home/kovid/work/calibre/src/calibre/library/server/opds.py:549 msgid "Date" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:138 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:138 msgid "Tag on book" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:139 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:139 msgid "Explanation text added in create_ct_column.py" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:140 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_ct_column_ui.py:140 msgid "Create and edit tag-based columns" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_custom_column.py:19 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_custom_column.py:19 msgid "Text, column shown in the tag browser" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_custom_column.py:22 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_custom_column.py:22 msgid "Comma separated text, like tags, shown in the tag browser" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_custom_column.py:25 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_custom_column.py:25 msgid "Long text, like comments, not shown in the tag browser" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_custom_column.py:28 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_custom_column.py:28 msgid "Text column for keeping series-like information" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_custom_column.py:33 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_custom_column.py:33 msgid "Floating point numbers" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_custom_column.py:35 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_custom_column.py:35 msgid "Integers" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_custom_column.py:37 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_custom_column.py:37 msgid "Ratings, shown with stars" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_custom_column.py:40 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_custom_column.py:40 msgid "Yes/No" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_custom_column.py:69 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_custom_column.py:69 msgid "No column selected" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_custom_column.py:70 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_custom_column.py:70 msgid "No column has been selected" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_custom_column.py:74 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_custom_column.py:74 msgid "Selected column is not a user-defined column" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_custom_column.py:105 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_custom_column.py:105 msgid "No lookup name was provided" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_custom_column.py:107 -msgid "The label must contain only letters, digits and underscores, and start with a letter" +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_custom_column.py:107 +msgid "The lookup name must contain only lower case letters, digits and underscores, and start with a letter" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_custom_column.py:116 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_custom_column.py:116 msgid "No column heading was provided" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_custom_column.py:122 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_custom_column.py:122 msgid "The lookup name %s is already used" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_custom_column.py:132 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_custom_column.py:132 msgid "The heading %s is already used" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_custom_column.py:134 -msgid "The lookup name must be lower case and cannot contain \":\"s or spaces" -msgstr "" - -#: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_custom_column_ui.py:101 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_custom_column_ui.py:117 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_custom_column_ui.py:101 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_custom_column_ui.py:117 msgid "Create or edit custom columns" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_custom_column_ui.py:102 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_custom_column_ui.py:102 msgid "&Lookup name" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_custom_column_ui.py:103 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_custom_column_ui.py:103 msgid "Column &heading" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_custom_column_ui.py:104 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_custom_column_ui.py:104 msgid "Used for searching the column. Must contain only digits and lower case letters." msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_custom_column_ui.py:105 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_custom_column_ui.py:105 msgid "Column heading in the library view and category name in the tag browser" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_custom_column_ui.py:106 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_custom_column_ui.py:106 msgid "Column &type" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_custom_column_ui.py:107 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_custom_column_ui.py:107 msgid "What kind of information will be kept in the column." msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_custom_column_ui.py:108 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_custom_column_ui.py:108 msgid "" "

    Date format. Use 1-4 'd's for day, 1-4 'M's for month, and 2 or 4 'y's for year.

    \n" "

    For example:\n" @@ -5456,275 +5471,277 @@ msgid "" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_custom_column_ui.py:114 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_custom_column_ui.py:114 msgid "Use MMM yyyy for month + year, yyyy for year only" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_custom_column_ui.py:115 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_custom_column_ui.py:115 msgid "Default: dd MMM yyyy." msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/create_custom_column_ui.py:116 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/create_custom_column_ui.py:116 msgid "Format for &dates" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/device_debug.py:21 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/device_debug.py:21 msgid "Getting debug information" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/device_debug.py:22 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/device_debug.py:22 msgid "Copy to &clipboard" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/device_debug.py:24 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/device_debug.py:24 msgid "Debug device detection" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/save_template.py:44 +#: +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/save_template.py:44 msgid "Invalid template" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/save_template.py:45 +#: +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/save_template.py:45 msgid "The template %s is invalid:" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/save_template_ui.py:42 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/save_template_ui.py:42 msgid "Save &template" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/save_template_ui.py:43 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/save_template_ui.py:43 msgid "By adjusting the template below, you can control what folders the files are saved in and what filenames they are given. You can use the / character to indicate sub-folders. Available metadata variables are described below. If a particular book does not have some metadata, the variable will be replaced by the empty string." msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/save_template_ui.py:44 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/save_template_ui.py:44 msgid "Available variables:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/config/social.py:34 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/social.py:34 msgid "Downloading social metadata, please wait..." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/confirm_delete_ui.py:50 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/confirm_delete_ui.py:50 msgid "&Show this warning again" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/conversion_error_ui.py:42 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/conversion_error_ui.py:42 msgid "ERROR" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/delete_matching_from_device.py:67 +#: /home/kovid/work/calibre/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/trunk/src/calibre/gui2/dialogs/delete_matching_from_device.py:75 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/delete_matching_from_device.py:75 msgid "Location" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/delete_matching_from_device.py:76 -#: /home/kovid/work/trunk/src/calibre/gui2/library/models.py:1064 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/delete_matching_from_device.py:76 +#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1064 msgid "Format" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/delete_matching_from_device_ui.py:50 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/delete_matching_from_device_ui.py:50 msgid "Delete from device" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/edit_authors_dialog.py:33 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/edit_authors_dialog.py:33 msgid "Author sort" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/edit_authors_dialog_ui.py:66 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/edit_authors_dialog_ui.py:66 msgid "Manage authors" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/edit_authors_dialog_ui.py:67 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/edit_authors_dialog_ui.py:67 msgid "Sort by author" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/edit_authors_dialog_ui.py:68 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/edit_authors_dialog_ui.py:68 msgid "Sort by author sort" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/edit_authors_dialog_ui.py:69 +#: /home/kovid/work/calibre/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/trunk/src/calibre/gui2/dialogs/edit_authors_dialog_ui.py:70 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/edit_authors_dialog_ui.py:70 msgid "Recalculate all author sort values" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata.py:60 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:60 msgid "Author Sort" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata.py:62 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:62 msgid "ISBN" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata.py:162 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:162 msgid "Finding metadata..." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata.py:176 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:176 msgid "Could not find metadata" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata.py:177 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:177 msgid "The metadata download seems to have stalled. Try again later." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata.py:186 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:186 msgid "Warning" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata.py:187 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:187 msgid "Could not fetch metadata from:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata.py:191 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:191 msgid "No metadata found" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata.py:192 +#: /home/kovid/work/calibre/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/trunk/src/calibre/gui2/dialogs/fetch_metadata_ui.py:85 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata_ui.py:85 msgid "Fetch metadata" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata_ui.py:86 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata_ui.py:86 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/trunk/src/calibre/gui2/dialogs/fetch_metadata_ui.py:87 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata_ui.py:87 msgid "&Access Key:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata_ui.py:88 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata_ui.py:88 msgid "Fetch" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata_ui.py:89 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata_ui.py:89 msgid "Matches" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata_ui.py:90 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata_ui.py:90 msgid "Select the book that most closely matches your copy from the list below" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata_ui.py:91 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata_ui.py:91 msgid "Download &social metadata (tags/rating/etc.) for the selected book" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/fetch_metadata_ui.py:92 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata_ui.py:92 msgid "Overwrite author and title with author and title of selected book" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/job_view_ui.py:37 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/job_view_ui.py:37 msgid "Details of job" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/jobs_ui.py:44 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/jobs_ui.py:44 msgid "Active Jobs" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/jobs_ui.py:45 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/jobs_ui.py:45 msgid "&Stop selected job" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/jobs_ui.py:46 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/jobs_ui.py:46 msgid "Show job &details" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/jobs_ui.py:47 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/jobs_ui.py:47 msgid "Stop &all non device jobs" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk.py:24 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:24 msgid "Editing meta information for %d books" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:157 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:157 msgid "Edit Meta information" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:159 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:159 msgid "A&utomatically set author sort" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:160 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:160 msgid "Author s&ort: " msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:161 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:368 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:161 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:368 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/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:162 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:371 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:162 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:371 msgid "&Rating:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:163 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:164 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:372 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:373 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:163 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:164 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:372 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:373 msgid "Rating of this book. 0-5 stars" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:165 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:165 msgid "No change" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:166 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:374 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:166 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:374 msgid " stars" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:168 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:168 msgid "Add ta&gs: " msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:170 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:171 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:378 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:379 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:170 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:171 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:378 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:379 msgid "Open Tag Editor" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:172 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:172 msgid "&Remove tags:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:173 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:173 msgid "Comma separated list of tags to remove from the books. " msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:177 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:177 msgid "Remove &format:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:178 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:178 msgid "&Swap title and author" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:179 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:179 msgid "" "Selected books will be automatically numbered,\n" "in the order you selected them.\n" @@ -5732,809 +5749,809 @@ msgid "" "Book A will have series number 1 and Book B series number 2." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:184 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:184 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/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:187 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:187 msgid "Remove &stored conversion settings for the selected books" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:188 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:410 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:188 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:410 msgid "&Basic metadata" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_bulk_ui.py:189 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:411 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:189 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:411 msgid "&Custom metadata" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:94 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:94 msgid "Last modified: %s" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:135 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:135 msgid "Not a valid picture" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:150 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:150 msgid "Specify title and author" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:151 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:151 msgid "You must specify a title and author before generating a cover" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:163 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:163 msgid "Choose formats for " msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:194 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:194 msgid "No permission" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:195 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:195 msgid "You do not have permission to read the following files:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:222 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:223 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:222 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:223 msgid "No format selected" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:234 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:234 msgid "Could not read metadata" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:235 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:235 msgid "Could not read metadata from %s format" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:283 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:289 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:283 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:289 msgid "Could not read cover" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:284 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:284 msgid "Could not read cover from %s format" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:290 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:290 msgid "The cover in the %s format is invalid" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:327 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:327 msgid "Abort the editing of all remaining books" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:465 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:470 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:465 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:470 msgid "This ISBN number is valid" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:473 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:473 msgid "This ISBN number is invalid" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:552 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:552 msgid "Cannot use tag editor" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:553 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:553 msgid "The tags editor cannot be used if you have modified the tags" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:573 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:573 msgid "Downloading cover..." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:585 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:590 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:596 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:601 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:585 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:590 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:596 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:601 msgid "Cannot fetch cover" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:586 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:597 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:602 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:586 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:597 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:602 msgid "Could not fetch cover.
    " msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:587 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:587 msgid "The download timed out." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:591 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:591 msgid "Could not find cover for this book. Try specifying the ISBN first." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:603 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:603 msgid "For the error message from each cover source, click Show details below." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:610 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:610 msgid "Bad cover" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:611 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:611 msgid "The cover is not a valid picture" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:644 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:644 msgid "There were errors" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:645 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:645 msgid "There were errors downloading social metadata" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:674 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:674 msgid "Cannot fetch metadata" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:675 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:675 msgid "You must specify at least one of ISBN, Title, Authors or Publisher" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:750 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:750 msgid "Permission denied" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single.py:751 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:751 msgid "Could not open %s. Is it being used by another program?" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:360 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:360 msgid "Edit Meta Information" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:361 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:361 msgid "Meta information" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:364 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:364 msgid "Swap the author and title" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:367 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:367 msgid "Author S&ort: " msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:369 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:369 msgid "Automatically create the author sort entry based on the current author entry" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:383 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:383 msgid "Remove unused series (Series that have no books)" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:385 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:385 msgid "IS&BN:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:386 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:386 msgid "Publishe&d:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:389 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:389 msgid "dd MMM yyyy" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:390 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:390 msgid "&Date:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:391 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:391 msgid "&Comments" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:392 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:392 msgid "&Fetch metadata from server" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:393 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:393 msgid "Available Formats" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:394 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:394 msgid "Add a new format for this book to the database" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:396 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:396 msgid "Remove the selected formats for this book from the database." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:398 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:398 msgid "Set the cover for the book from the selected format" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:400 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:400 msgid "Update metadata from the metadata in the selected format" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:405 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:405 msgid "Reset cover to default" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:407 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:407 msgid "Download &cover" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:408 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:408 msgid "Generate a default cover based on the title and author" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/metadata_single_ui.py:409 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:409 msgid "&Generate cover" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/password_ui.py:56 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/password_ui.py:56 msgid "Password needed" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/progress.py:52 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/progress.py:52 msgid "Aborting..." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/saved_search_editor.py:54 +#: /home/kovid/work/calibre/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/trunk/src/calibre/gui2/dialogs/saved_search_editor_ui.py:83 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/saved_search_editor_ui.py:83 msgid "Saved Search Editor" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/saved_search_editor_ui.py:84 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/saved_search_editor_ui.py:84 msgid "Saved Search: " msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/saved_search_editor_ui.py:85 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/saved_search_editor_ui.py:85 msgid "Select a saved search to edit" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/saved_search_editor_ui.py:86 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/saved_search_editor_ui.py:86 msgid "Delete this selected saved search" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/saved_search_editor_ui.py:88 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/saved_search_editor_ui.py:88 msgid "Enter a new saved search name." msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/saved_search_editor_ui.py:89 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/saved_search_editor_ui.py:89 msgid "Add the new saved search" msgstr "" #: -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/saved_search_editor_ui.py:91 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/saved_search_editor_ui.py:91 msgid "Change the contents of the saved search" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler.py:120 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:120 msgid "Need username and password" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler.py:121 +#: /home/kovid/work/calibre/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/trunk/src/calibre/gui2/dialogs/scheduler.py:172 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:172 msgid "Created by: " msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler.py:179 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:179 msgid "Last downloaded: never" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler.py:194 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:194 msgid "%d days, %d hours and %d minutes ago" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler.py:196 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:196 msgid "Last downloaded" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler.py:220 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:192 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:220 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:192 msgid "Schedule news download" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler.py:223 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:223 msgid "Add a custom news source" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler.py:228 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:228 msgid "Download all scheduled new sources" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler.py:328 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:328 msgid "No internet connection" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler.py:329 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:329 msgid "Cannot download news as no internet connection is active" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:193 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:278 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:193 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:278 msgid "Recipes" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:194 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:194 msgid "Download all scheduled recipes at once" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:195 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:195 msgid "Download &all scheduled" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:196 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:196 msgid "blurb" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:197 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:197 msgid "&Schedule for download:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:198 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:208 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:198 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:208 msgid "Every " msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:199 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:199 msgid "day" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:200 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:200 msgid "Monday" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:201 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:201 msgid "Tuesday" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:202 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:202 msgid "Wednesday" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:203 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:203 msgid "Thursday" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:204 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:204 msgid "Friday" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:205 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:205 msgid "Saturday" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:206 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:206 msgid "Sunday" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:207 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:207 msgid "at" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:209 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:209 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/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:210 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:222 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles_ui.py:263 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:210 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:222 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles_ui.py:263 msgid " days" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:211 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:211 msgid "&Account" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:215 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:215 msgid "For the scheduling to work, you must leave calibre running." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:216 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:216 msgid "&Schedule" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:217 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:217 msgid "Add &title as tag" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:218 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:218 msgid "&Extra tags:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:219 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:219 msgid "&Advanced" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:220 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:220 msgid "&Download now" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:221 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:221 msgid "Delete downloaded news older than the specified number of days. Set to zero to disable." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/scheduler_ui.py:223 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler_ui.py:223 msgid "Delete downloaded news older than " msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_item_ui.py:36 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_item_ui.py:36 msgid "contains" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_item_ui.py:37 +#: /home/kovid/work/calibre/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/trunk/src/calibre/gui2/dialogs/search_item_ui.py:38 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_item_ui.py:38 msgid "

    Negate this match. That is, only return results that do not match this query." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_item_ui.py:39 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_item_ui.py:39 msgid "Negate" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_ui.py:113 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_ui.py:113 msgid "Advanced Search" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_ui.py:114 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_ui.py:114 msgid "Find entries that have..." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_ui.py:115 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_ui.py:115 msgid "&All these words:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_ui.py:116 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_ui.py:116 msgid "This exact &phrase:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_ui.py:117 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_ui.py:117 msgid "&One or more of these words:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_ui.py:118 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_ui.py:118 msgid "But dont show entries that have..." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_ui.py:119 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_ui.py:119 msgid "Any of these &unwanted words:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_ui.py:120 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_ui.py:120 msgid "What kind of match to use:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_ui.py:121 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_ui.py:121 msgid "Contains: the word or phrase matches anywhere in the metadata" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_ui.py:122 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_ui.py:122 msgid "Equals: the word or phrase must match an entire metadata field" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_ui.py:123 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_ui.py:123 msgid "Regular expression: the expression must match anywhere in the metadata" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_ui.py:124 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_ui.py:124 msgid " " msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/search_ui.py:125 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_ui.py:125 msgid "See the User Manual for more help" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/select_formats.py:45 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/select_formats.py:45 msgid "Choose formats" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories.py:50 -#: /home/kovid/work/trunk/src/calibre/library/field_metadata.py:80 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories.py:50 +#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:80 msgid "Authors" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories.py:50 -#: /home/kovid/work/trunk/src/calibre/library/field_metadata.py:111 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories.py:50 +#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:111 msgid "Publishers" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories.py:114 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories.py:114 msgid " (not on any book)" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories.py:166 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories.py:166 msgid "The current tag category will be permanently deleted. Are you sure?" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories_ui.py:153 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories_ui.py:153 msgid "User Categories Editor" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories_ui.py:154 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories_ui.py:154 msgid "A&vailable items" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories_ui.py:155 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories_ui.py:155 msgid "Apply tags to current tag category" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories_ui.py:157 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories_ui.py:157 msgid "A&pplied items" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories_ui.py:158 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories_ui.py:158 msgid "Unapply (remove) tag from current tag category" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories_ui.py:160 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories_ui.py:160 msgid "Category name: " msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories_ui.py:161 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories_ui.py:161 msgid "Select a category to edit" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories_ui.py:162 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories_ui.py:162 msgid "Delete this selected tag category" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories_ui.py:164 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories_ui.py:164 msgid "Enter a new category name. Select the kind before adding it." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories_ui.py:165 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories_ui.py:165 msgid "Add the new category" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories_ui.py:167 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories_ui.py:167 msgid "Category filter: " msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_categories_ui.py:168 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories_ui.py:168 msgid "Select the content kind of the new category" msgstr "" -#: /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 +#: /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 msgid "Are your sure?" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_editor.py:69 +#: /home/kovid/work/calibre/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/trunk/src/calibre/gui2/dialogs/tag_editor_ui.py:123 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_editor_ui.py:123 msgid "Tag Editor" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_editor_ui.py:124 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_editor_ui.py:124 msgid "A&vailable tags" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_editor_ui.py:125 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_editor_ui.py:125 msgid "Delete tag from database. This will unapply the tag from all books and then remove it from the database." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_editor_ui.py:127 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_editor_ui.py:127 msgid "Apply tag to current book" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_editor_ui.py:129 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_editor_ui.py:129 msgid "A&pplied tags" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_editor_ui.py:130 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_editor_ui.py:130 msgid "Unapply (remove) tag from current book" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_editor_ui.py:132 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_editor_ui.py:132 msgid "&Add tag:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_editor_ui.py:133 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_editor_ui.py:133 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/trunk/src/calibre/gui2/dialogs/tag_editor_ui.py:134 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_editor_ui.py:134 msgid "Add tag to available tags and apply it to current book" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_list_editor.py:20 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor.py:20 msgid "%s (was %s)" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_list_editor.py:74 -#: /home/kovid/work/trunk/src/calibre/gui2/tag_view.py:500 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor.py:74 +#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:500 msgid "Item is blank" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_list_editor.py:75 -#: /home/kovid/work/trunk/src/calibre/gui2/tag_view.py:501 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor.py:75 +#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:501 msgid "An item cannot be set to nothing. Delete it instead." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_list_editor.py:91 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor.py:91 msgid "No item selected" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_list_editor.py:92 +#: /home/kovid/work/calibre/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/trunk/src/calibre/gui2/dialogs/tag_list_editor.py:101 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor.py:101 msgid "No items selected" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_list_editor.py:102 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor.py:102 msgid "You must select at least one items from the list." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_list_editor.py:106 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor.py:106 msgid "Are you certain you want to delete the following items?" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_list_editor_ui.py:72 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor_ui.py:72 msgid "Category Editor" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_list_editor_ui.py:73 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor_ui.py:73 msgid "Items in use" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_list_editor_ui.py:74 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor_ui.py:74 msgid "Delete item from database. This will unapply the item from all books and then remove it from the database." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_list_editor_ui.py:76 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor_ui.py:76 msgid "Rename the item in every book where it is used." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/tag_list_editor_ui.py:78 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor_ui.py:78 msgid "Ctrl+S" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/test_email_ui.py:51 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/test_email_ui.py:51 msgid "Test email settings" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/test_email_ui.py:52 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/test_email_ui.py:52 msgid "Send test mail from %s to:" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/test_email_ui.py:53 -#: /home/kovid/work/trunk/src/calibre/gui2/filename_pattern_ui.py:115 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/test_email_ui.py:53 +#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:115 msgid "&Test" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:127 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:127 msgid "No recipe selected" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:132 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:132 msgid "The attached file: %s is a recipe to download %s." msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:133 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:133 msgid "Recipe for " msgstr "" -#: /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:255 +#: /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:255 msgid "Switch to Advanced mode" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:156 -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:164 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:156 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:164 msgid "Switch to Basic mode" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:174 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:174 msgid "Feed must have a title" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:175 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:175 msgid "The feed must have a title" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:179 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:179 msgid "Feed must have a URL" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:180 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:180 msgid "The feed %s must have a URL" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:185 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:185 msgid "Already exists" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:186 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:186 msgid "This feed has already been added to the recipe" msgstr "" -#: /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 +#: /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 msgid "Invalid input" msgstr "" -#: /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 +#: /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 msgid "

    Could not create recipe. Error:
    %s" msgstr "" -#: /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 +#: /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 msgid "Replace recipe?" msgstr "" -#: /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 +#: /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 msgid "A custom recipe named %s already exists. Do you want to replace it?" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:257 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:257 msgid "Pick recipe" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:257 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:257 msgid "Pick the recipe to customize" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles.py:277 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles.py:277 msgid "Choose a recipe file" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles_ui.py:248 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles_ui.py:248 msgid "Add custom news source" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles_ui.py:249 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles_ui.py:249 msgid "Available user recipes" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles_ui.py:250 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles_ui.py:250 msgid "Add/Update &recipe" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles_ui.py:251 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles_ui.py:251 msgid "&Remove recipe" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles_ui.py:252 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles_ui.py:252 msgid "&Share recipe" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles_ui.py:253 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles_ui.py:253 msgid "Customize &builtin recipe" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles_ui.py:254 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles_ui.py:254 msgid "&Load recipe from file" msgstr "" -#: /home/kovid/work/trunk/src/calibre/gui2/dialogs/user_profiles_ui.py:256 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles_ui.py:256 msgid "" "