Sync to trunk.

This commit is contained in:
John Schember 2011-04-22 19:11:14 -04:00
commit 8c51a78c7f
17 changed files with 1697 additions and 1233 deletions

View File

@ -19,6 +19,60 @@
# new recipes:
# - title:
- version: 0.7.57
date: 2011-04-22
new features:
- title: "Launch worker processes on demand instead of keeping a pool of them in memory. Reduces memory footprint."
- title: "Use the visual formatting of the Table of Contents to try to automatically create a multi-level TOC when converting/viewing MOBI files."
tickets: [763681]
- title: "Add a new function booksize() to the template language to get the value of the size column in calibre."
- title: "Add support for using metadata plugboards with the content server (only with the epub format)"
- title: "Change default algorithm for automatically computing author sort to be more intelligent and handle the case when the author name has a comma in it"
- title: "Show cover size in the tooltips of the book details panel and book details popup window"
bug fixes:
- title: "Dragging and dropping a cover onto the book details panel did not change the cover size"
tickets: [768332]
- title: "Fix non-escaped '|' when searching for commas in authors using REGEXP_MATCH"
- title: "Fix ratings in templates being multiplied by 2"
- title: "Fix adding a comma to custom series values when using completion."
tickets: [763788]
- title: "CHM Input: Another workaround for a Microsoft mess."
tickets: [763336]
- title: "Fix job count in the spinner not always being updated when a job completes"
- title: "Changing case only of a title does not update title sort"
tickets: [768904]
improved recipes:
- ecuisine.ro, egirl.ro and tabu.ro
- Daily Telegraph
- Handelsblatt
- Il Sole 24 Ore
- Newsweek
- Arcamax
new recipes:
- title: BabyOnline.ro
author: Silviu Cotoara
- title: "The Journal.ie"
author: Phil Burns
- title: "Der Spiegel"
author: Nikolas Mangold
- version: 0.7.56
date: 2011-04-17

View File

@ -4,7 +4,7 @@ __license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
__docformat__ = 'restructuredtext en'
__appname__ = u'calibre'
numeric_version = (0, 7, 56)
numeric_version = (0, 7, 57)
__version__ = u'.'.join(map(unicode, numeric_version))
__author__ = u"Kovid Goyal <kovid@kovidgoyal.net>"

View File

@ -42,6 +42,10 @@ class Worker(Thread):
self.log.exception('Plugin', self.plugin.name, 'failed')
self.plugin.dl_time_spent = time.time() - start
@property
def name(self):
return self.plugin.name
def is_worker_alive(workers):
for w in workers:
if w.is_alive():
@ -348,7 +352,11 @@ def identify(log, abort, # {{{
if (first_result_at is not None and time.time() - first_result_at >
wait_time):
log('Not waiting any longer for more results')
log.warn('Not waiting any longer for more results. Still running'
' sources:')
for worker in workers:
if worker.is_alive():
log.debug('\t' + worker.name)
abort.set()
break

View File

@ -58,7 +58,7 @@ class OverDrive(Source):
isbn = identifiers.get('isbn', None)
br = self.browser
ovrdrv_data = self.to_ovrdrv_data(br, title, authors, ovrdrv_id)
ovrdrv_data = self.to_ovrdrv_data(br, log, title, authors, ovrdrv_id)
if ovrdrv_data:
title = ovrdrv_data[8]
authors = ovrdrv_data[6]
@ -113,7 +113,7 @@ class OverDrive(Source):
if ovrdrv_id is not None:
referer = self.get_base_referer()+'ContentDetails-Cover.htm?ID='+ovrdrv_id
req.add_header('referer', referer)
req.add_header('referer', referer)
log('Downloading cover from:', cached_url)
try:
cdata = br.open_novisit(req, timeout=timeout).read()
@ -186,7 +186,7 @@ class OverDrive(Source):
br.set_cookiejar(clean_cj)
def overdrive_search(self, br, q, title, author):
def overdrive_search(self, br, log, q, title, author):
# re-initialize the cookiejar to so that it's clean
clean_cj = mechanize.CookieJar()
br.set_cookiejar(clean_cj)
@ -204,7 +204,8 @@ class OverDrive(Source):
else:
initial_q = ' '.join(author_tokens)
xref_q = '+'.join(title_tokens)
#log.error('Initial query is %s'%initial_q)
#log.error('Cross reference query is %s'%xref_q)
q_xref = q+'SearchResults.svc/GetResults?iDisplayLength=50&sSearch='+xref_q
query = '{"szKeyword":"'+initial_q+'"}'
@ -313,16 +314,16 @@ class OverDrive(Source):
return self.sort_ovrdrv_results(raw, None, None, None, ovrdrv_id)
def find_ovrdrv_data(self, br, title, author, isbn, ovrdrv_id=None):
def find_ovrdrv_data(self, br, log, title, author, isbn, ovrdrv_id=None):
q = base_url
if ovrdrv_id is None:
return self.overdrive_search(br, q, title, author)
return self.overdrive_search(br, log, q, title, author)
else:
return self.overdrive_get_record(br, q, ovrdrv_id)
def to_ovrdrv_data(self, br, title=None, author=None, ovrdrv_id=None):
def to_ovrdrv_data(self, br, log, title=None, author=None, ovrdrv_id=None):
'''
Takes either a title/author combo or an Overdrive ID. One of these
two must be passed to this function.
@ -335,10 +336,10 @@ class OverDrive(Source):
elif ans is False:
return None
else:
ovrdrv_data = self.find_ovrdrv_data(br, title, author, ovrdrv_id)
ovrdrv_data = self.find_ovrdrv_data(br, log, title, author, ovrdrv_id)
else:
try:
ovrdrv_data = self.find_ovrdrv_data(br, title, author, ovrdrv_id)
ovrdrv_data = self.find_ovrdrv_data(br, log, title, author, ovrdrv_id)
except:
import traceback
traceback.print_exc()

View File

@ -8,14 +8,15 @@ __docformat__ = 'restructuredtext en'
import os
from functools import partial
from PyQt4.Qt import Qt, QMenu, QModelIndex
from PyQt4.Qt import Qt, QMenu, QModelIndex, QTimer
from calibre.gui2 import error_dialog, config, Dispatcher
from calibre.gui2 import error_dialog, config, Dispatcher, question_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
from calibre.ebooks.metadata import authors_to_string
from calibre.utils.icu import sort_key
from calibre.utils.config import test_eight_code
@ -78,6 +79,7 @@ class EditMetadataAction(InterfaceAction):
self.qaction.setEnabled(enabled)
self.action_merge.setEnabled(enabled)
# Download metadata {{{
def download_metadata(self, ids=None):
if ids is None:
rows = self.gui.library_view.selectionModel().selectedRows()
@ -88,14 +90,73 @@ class EditMetadataAction(InterfaceAction):
ids = [db.id(row.row()) for row in rows]
from calibre.gui2.metadata.bulk_download2 import start_download
start_download(self.gui, ids,
Dispatcher(self.bulk_metadata_downloaded))
Dispatcher(self.metadata_downloaded))
def bulk_metadata_downloaded(self, job):
def metadata_downloaded(self, job):
if job.failed:
self.gui.job_exception(job, dialog_title=_('Failed to download metadata'))
return
from calibre.gui2.metadata.bulk_download2 import proceed
proceed(self.gui, job)
from calibre.gui2.metadata.bulk_download2 import get_job_details
id_map, failed_ids, failed_covers, all_failed, det_msg = \
get_job_details(job)
if all_failed:
return error_dialog(self.gui, _('Download failed'),
_('Failed to download metadata or covers for any of the %d'
' book(s).') % len(id_map), det_msg=det_msg, show=True)
self.gui.status_bar.show_message(_('Metadata download completed'), 3000)
msg = '<p>' + _('Finished downloading metadata for <b>%d book(s)</b>. '
'Proceed with updating the metadata in your library?')%len(id_map)
show_copy_button = False
if failed_ids or failed_covers:
show_copy_button = True
msg += '<p>'+_('Could not download metadata and/or covers for %d of the books. Click'
' "Show details" to see which books.')%len(failed_ids)
payload = (id_map, failed_ids, failed_covers)
from calibre.gui2.dialogs.message_box import ProceedNotification
p = ProceedNotification(payload, job.html_details,
_('Download log'), _('Download complete'), msg,
det_msg=det_msg, show_copy_button=show_copy_button,
parent=self.gui)
p.proceed.connect(self.apply_downloaded_metadata)
p.show()
def apply_downloaded_metadata(self, payload):
id_map, failed_ids, failed_covers = payload
id_map = dict([(k, v) for k, v in id_map.iteritems() if k not in
failed_ids])
if not id_map:
return
modified = set()
db = self.gui.current_db
for i, mi in id_map.iteritems():
lm = db.metadata_last_modified(i, index_is_id=True)
if lm > mi.last_modified:
title = db.title(i, index_is_id=True)
authors = db.authors(i, index_is_id=True)
if authors:
authors = [x.replace('|', ',') for x in authors.split(',')]
title += ' - ' + authors_to_string(authors)
modified.add(title)
if modified:
from calibre.utils.icu import lower
modified = sorted(modified, key=lower)
if not question_dialog(self.gui, _('Some books changed'), '<p>'+
_('The metadata for some books in your library has'
' changed since you started the download. If you'
' proceed, some of those changes may be overwritten. '
'Click "Show details" to see the list of changed books. '
'Do you want to proceed?'), det_msg='\n'.join(modified)):
return
self.apply_metadata_changes(id_map)
def download_metadata_old(self, checked, covers=True, set_metadata=True,
set_social_metadata=None):
@ -140,6 +201,7 @@ class EditMetadataAction(InterfaceAction):
x.updated, cr)
if self.gui.cover_flow:
self.gui.cover_flow.dataChanged()
# }}}
def edit_metadata(self, checked, bulk=None):
'''
@ -466,4 +528,89 @@ class EditMetadataAction(InterfaceAction):
self.gui.upload_collections(model.db, view=view, oncard=oncard)
view.reset()
# Apply bulk metadata changes {{{
def apply_metadata_changes(self, id_map, title=None, msg=''):
'''
Apply the metadata changes in id_map to the database synchronously
id_map must be a mapping of ids to Metadata objects. Set any fields you
do not want updated in the Metadata object to null. An easy way to do
that is to create a metadata object as Metadata(_('Unknown')) and then
only set the fields you want changed on this object.
'''
if title is None:
title = _('Applying changed metadata')
self.apply_id_map = list(id_map.iteritems())
self.apply_current_idx = 0
self.apply_failures = []
self.applied_ids = []
self.apply_pd = None
if len(self.apply_id_map) > 1:
from calibre.gui2.dialogs.progress import ProgressDialog
self.apply_pd = ProgressDialog(title, msg, min=0,
max=len(self.apply_id_map)-1, parent=self.gui,
cancelable=False)
self.apply_pd.setModal(True)
self.apply_pd.show()
self.do_one_apply()
def do_one_apply(self):
if self.apply_current_idx >= len(self.apply_id_map):
return self.finalize_apply()
i, mi = self.apply_id_map[self.apply_current_idx]
db = self.gui.current_db
try:
set_title = not mi.is_null('title')
set_authors = not mi.is_null('authors')
db.set_metadata(i, mi, commit=False, set_title=set_title,
set_authors=set_authors, notify=False)
self.applied_ids.append(i)
except:
import traceback
self.apply_failures.append((i, traceback.format_exc()))
try:
if mi.cover:
os.remove(mi.cover)
except:
pass
self.apply_current_idx += 1
if self.apply_pd is not None:
self.apply_pd.value += 1
QTimer.singleShot(50, self.do_one_apply)
def finalize_apply(self):
db = self.gui.current_db
db.commit()
if self.apply_pd is not None:
self.apply_pd.hide()
if self.apply_failures:
msg = []
for i, tb in self.apply_failures:
title = db.title(i, index_is_id=True)
authors = db.authors(i, index_is_id=True)
if authors:
authors = [x.replace('|', ',') for x in authors.split(',')]
title += ' - ' + authors_to_string(authors)
msg.append(title+'\n\n'+tb+'\n'+('*'*80))
error_dialog(self.gui, _('Some failures'),
_('Failed to apply updated metadata for some books'
' in your library. Click "Show Details" to see '
'details.'), det_msg='\n\n'.join(msg), show=True)
if self.applied_ids:
cr = self.gui.library_view.currentIndex().row()
self.gui.library_view.model().refresh_ids(
self.applied_ids, cr)
if self.gui.cover_flow:
self.gui.cover_flow.dataChanged()
self.apply_id_map = []
self.apply_pd = None
# }}}

View File

@ -6,13 +6,13 @@ __copyright__ = '2011, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
from PyQt4.Qt import QDialog, QIcon, QApplication, QSize, QKeySequence, \
QAction, Qt
from PyQt4.Qt import (QDialog, QIcon, QApplication, QSize, QKeySequence,
QAction, Qt, pyqtSignal, QTextBrowser, QDialogButtonBox, QVBoxLayout)
from calibre.constants import __version__
from calibre.gui2.dialogs.message_box_ui import Ui_Dialog
class MessageBox(QDialog, Ui_Dialog):
class MessageBox(QDialog, Ui_Dialog): # {{{
ERROR = 0
WARNING = 1
@ -111,6 +111,81 @@ class MessageBox(QDialog, Ui_Dialog):
self.det_msg_toggle.setVisible(bool(msg))
self.det_msg.setVisible(False)
self.do_resize()
# }}}
class ViewLog(QDialog): # {{{
def __init__(self, title, html, parent=None):
QDialog.__init__(self, parent)
self.l = l = QVBoxLayout()
self.setLayout(l)
self.tb = QTextBrowser(self)
self.tb.setHtml('<pre style="font-family: monospace">%s</pre>' % html)
l.addWidget(self.tb)
self.bb = QDialogButtonBox(QDialogButtonBox.Ok)
self.bb.accepted.connect(self.accept)
self.bb.rejected.connect(self.reject)
self.copy_button = self.bb.addButton(_('Copy to clipboard'),
self.bb.ActionRole)
self.copy_button.setIcon(QIcon(I('edit-copy.png')))
self.copy_button.clicked.connect(self.copy_to_clipboard)
l.addWidget(self.bb)
self.setModal(False)
self.resize(QSize(700, 500))
self.setWindowTitle(title)
self.setWindowIcon(QIcon(I('debug.png')))
self.show()
def copy_to_clipboard(self):
txt = self.tb.toPlainText()
QApplication.clipboard().setText(txt)
# }}}
class ProceedNotification(MessageBox): # {{{
proceed = pyqtSignal(object)
def __init__(self, payload, html_log, log_viewer_title, title, msg, det_msg='', show_copy_button=False, parent=None):
'''
A non modal popup that notifies the user that a background task has
been completed. If they user clicks yes, the proceed signal is emitted
with payload as its argument.
:param payload: Arbitrary object, emitted in the proceed signal
:param html_log: An HTML or plain text log
:param log_viewer_title: The title for the log viewer window
:param title: The title fo rthis popup
:param msg: The msg to display
:param det_msg: Detailed message
'''
MessageBox.__init__(self, MessageBox.QUESTION, title, msg,
det_msg=det_msg, show_copy_button=show_copy_button,
parent=parent)
self.payload = payload
self.html_log = html_log
self.log_viewer_title = log_viewer_title
self.finished.connect(self.do_proceed)
self.vlb = self.bb.addButton(_('View log'), self.bb.ActionRole)
self.vlb.setIcon(QIcon(I('debug.png')))
self.vlb.clicked.connect(self.show_log)
self.det_msg_toggle.setVisible(bool(det_msg))
self.setModal(False)
def show_log(self):
self.log_viewer = ViewLog(self.log_viewer_title, self.html_log,
parent=self)
def do_proceed(self, result):
if result == self.Accepted:
self.proceed.emit(self.payload)
try:
self.proceed.disconnect()
except:
pass
# }}}
if __name__ == '__main__':
app = QApplication([])

View File

@ -169,11 +169,11 @@ class JobManager(QAbstractTableModel): # {{{
job.update()
if orig_state != job.run_state:
needs_reset = True
if job.is_finished:
self.job_done.emit(len(self.unfinished_jobs()))
if needs_reset:
self.jobs.sort()
self.reset()
if job.is_finished:
self.job_done.emit(len(self.unfinished_jobs()))
else:
for job in jobs:
idx = self.jobs.index(job)

View File

@ -7,19 +7,14 @@ __license__ = 'GPL v3'
__copyright__ = '2011, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
import os
from functools import partial
from itertools import izip
from threading import Event
from PyQt4.Qt import (QIcon, QDialog, QVBoxLayout, QTextBrowser, QSize,
QDialogButtonBox, QApplication, QTimer, QLabel, QProgressBar,
QGridLayout, QPixmap, Qt)
from PyQt4.Qt import (QIcon, QDialog,
QDialogButtonBox, QLabel, QGridLayout, QPixmap, Qt)
from calibre.gui2.dialogs.message_box import MessageBox
from calibre.gui2.threaded_jobs import ThreadedJob
from calibre.utils.icu import lower
from calibre.ebooks.metadata import authors_to_string
from calibre.gui2 import question_dialog, error_dialog
from calibre.ebooks.metadata.sources.identify import identify, msprefs
from calibre.ebooks.metadata.sources.covers import download_cover
from calibre.ebooks.metadata.book.base import Metadata
@ -107,178 +102,7 @@ def start_download(gui, ids, callback):
gui.status_bar.show_message(_('Metadata download started'), 3000)
# }}}
class ViewLog(QDialog): # {{{
def __init__(self, html, parent=None):
QDialog.__init__(self, parent)
self.l = l = QVBoxLayout()
self.setLayout(l)
self.tb = QTextBrowser(self)
self.tb.setHtml('<pre style="font-family: monospace">%s</pre>' % html)
l.addWidget(self.tb)
self.bb = QDialogButtonBox(QDialogButtonBox.Ok)
self.bb.accepted.connect(self.accept)
self.bb.rejected.connect(self.reject)
self.copy_button = self.bb.addButton(_('Copy to clipboard'),
self.bb.ActionRole)
self.copy_button.setIcon(QIcon(I('edit-copy.png')))
self.copy_button.clicked.connect(self.copy_to_clipboard)
l.addWidget(self.bb)
self.setModal(False)
self.resize(QSize(700, 500))
self.setWindowTitle(_('Download log'))
self.setWindowIcon(QIcon(I('debug.png')))
self.show()
def copy_to_clipboard(self):
txt = self.tb.toPlainText()
QApplication.clipboard().setText(txt)
_vl = None
def view_log(job, parent):
global _vl
_vl = ViewLog(job.html_details, parent)
# }}}
# Apply downloaded metadata {{{
class ApplyDialog(QDialog):
def __init__(self, gui):
QDialog.__init__(self, gui)
self.l = l = QVBoxLayout()
self.setLayout(l)
l.addWidget(QLabel(_('Applying downloaded metadata to your library')))
self.pb = QProgressBar(self)
l.addWidget(self.pb)
self.bb = QDialogButtonBox(QDialogButtonBox.Cancel)
self.bb.rejected.connect(self.reject)
l.addWidget(self.bb)
self.gui = gui
self.timer = QTimer(self)
self.timer.timeout.connect(self.do_one)
def start(self, id_map):
self.id_map = list(id_map.iteritems())
self.current_idx = 0
self.failures = []
self.ids = []
self.canceled = False
self.pb.setMinimum(0)
self.pb.setMaximum(len(id_map))
self.timer.start(50)
def do_one(self):
if self.canceled:
return
if self.current_idx >= len(self.id_map):
self.timer.stop()
self.finalize()
return
i, mi = self.id_map[self.current_idx]
db = self.gui.current_db
try:
set_title = not mi.is_null('title')
set_authors = not mi.is_null('authors')
db.set_metadata(i, mi, commit=False, set_title=set_title,
set_authors=set_authors)
self.ids.append(i)
except:
import traceback
self.failures.append((i, traceback.format_exc()))
try:
if mi.cover:
os.remove(mi.cover)
except:
pass
self.pb.setValue(self.pb.value()+1)
self.current_idx += 1
def reject(self):
self.canceled = True
self.timer.stop()
QDialog.reject(self)
def finalize(self):
if self.canceled:
return
if self.failures:
msg = []
db = self.gui.current_db
for i, tb in self.failures:
title = db.title(i, index_is_id=True)
authors = db.authors(i, index_is_id=True)
if authors:
authors = [x.replace('|', ',') for x in authors.split(',')]
title += ' - ' + authors_to_string(authors)
msg.append(title+'\n\n'+tb+'\n'+('*'*80))
parent = self if self.isVisible() else self.parent()
error_dialog(parent, _('Some failures'),
_('Failed to apply updated metadata for some books'
' in your library. Click "Show Details" to see '
'details.'), det_msg='\n\n'.join(msg), show=True)
if self.ids:
cr = self.gui.library_view.currentIndex().row()
self.gui.library_view.model().refresh_ids(
self.ids, cr)
if self.gui.cover_flow:
self.gui.cover_flow.dataChanged()
self.accept()
_amd = None
def apply_metadata(job, gui, q, result):
global _amd
q.vlb.clicked.disconnect()
q.finished.disconnect()
if result != q.Accepted:
return
id_map, failed_ids, failed_covers, title_map, all_failed = job.result
id_map = dict([(k, v) for k, v in id_map.iteritems() if k not in
failed_ids])
if not id_map:
return
modified = set()
db = gui.current_db
for i, mi in id_map.iteritems():
lm = db.metadata_last_modified(i, index_is_id=True)
if lm > mi.last_modified:
title = db.title(i, index_is_id=True)
authors = db.authors(i, index_is_id=True)
if authors:
authors = [x.replace('|', ',') for x in authors.split(',')]
title += ' - ' + authors_to_string(authors)
modified.add(title)
if modified:
modified = sorted(modified, key=lower)
if not question_dialog(gui, _('Some books changed'), '<p>'+
_('The metadata for some books in your library has'
' changed since you started the download. If you'
' proceed, some of those changes may be overwritten. '
'Click "Show details" to see the list of changed books. '
'Do you want to proceed?'), det_msg='\n'.join(modified)):
return
if _amd is None:
_amd = ApplyDialog(gui)
_amd.start(id_map)
if len(id_map) > 3:
_amd.exec_()
def proceed(gui, job):
gui.status_bar.show_message(_('Metadata download completed'), 3000)
def get_job_details(job):
id_map, failed_ids, failed_covers, title_map, all_failed = job.result
det_msg = []
for i in failed_ids | failed_covers:
@ -289,31 +113,7 @@ def proceed(gui, job):
title += (' ' + _('(Failed cover)'))
det_msg.append(title)
det_msg = '\n'.join(det_msg)
if all_failed:
q = error_dialog(gui, _('Download failed'),
_('Failed to download metadata or covers for any of the %d'
' book(s).') % len(id_map), det_msg=det_msg)
else:
fmsg = ''
if failed_ids or failed_covers:
fmsg = '<p>'+_('Could not download metadata and/or covers for %d of the books. Click'
' "Show details" to see which books.')%len(failed_ids)
msg = '<p>' + _('Finished downloading metadata for <b>%d book(s)</b>. '
'Proceed with updating the metadata in your library?')%len(id_map)
q = MessageBox(MessageBox.QUESTION, _('Download complete'),
msg + fmsg, det_msg=det_msg, show_copy_button=bool(failed_ids),
parent=gui)
q.finished.connect(partial(apply_metadata, job, gui, q))
q.vlb = q.bb.addButton(_('View log'), q.bb.ActionRole)
q.vlb.setIcon(QIcon(I('debug.png')))
q.vlb.clicked.connect(partial(view_log, job, q))
q.det_msg_toggle.setVisible(bool(failed_ids | failed_covers))
q.setModal(False)
q.show()
# }}}
return id_map, failed_ids, failed_covers, all_failed, det_msg
def merge_result(oldmi, newmi):
dummy = Metadata(_('Unknown'))
@ -345,6 +145,10 @@ def download(ids, db, do_identify, covers,
ans = {}
count = 0
all_failed = True
'''
# Test apply dialog
all_failed = do_identify = covers = False
'''
for i, mi in izip(ids, metadata):
if abort.is_set():
log.error('Aborting...')
@ -354,7 +158,7 @@ def download(ids, db, do_identify, covers,
if do_identify:
results = []
try:
results = identify(log, abort, title=title, authors=authors,
results = identify(log, Event(), title=title, authors=authors,
identifiers=identifiers)
except:
pass

View File

@ -15,10 +15,10 @@ from operator import attrgetter
from Queue import Queue, Empty
from PyQt4.Qt import (QStyledItemDelegate, QTextDocument, QRectF, QIcon, Qt,
QStyle, QApplication, QDialog, QVBoxLayout, QLabel, QDialogButtonBox,
QApplication, QDialog, QVBoxLayout, QLabel, QDialogButtonBox,
QStackedWidget, QWidget, QTableView, QGridLayout, QFontInfo, QPalette,
QTimer, pyqtSignal, QAbstractTableModel, QVariant, QSize, QListView,
QPixmap, QAbstractListModel, QColor, QRect, QTextBrowser)
QPixmap, QAbstractListModel, QColor, QRect, QTextBrowser, QModelIndex)
from PyQt4.QtWebKit import QWebView
from calibre.customize.ui import metadata_plugins
@ -52,12 +52,9 @@ class RichTextDelegate(QStyledItemDelegate): # {{{
return ans
def paint(self, painter, option, index):
QStyledItemDelegate.paint(self, painter, option, QModelIndex())
painter.save()
painter.setClipRect(QRectF(option.rect))
if hasattr(QStyle, 'CE_ItemViewItem'):
QApplication.style().drawControl(QStyle.CE_ItemViewItem, option, painter)
elif option.state & QStyle.State_Selected:
painter.fillRect(option.rect, option.palette.highlight())
painter.translate(option.rect.topLeft())
self.to_doc(index).drawContents(painter)
painter.restore()
@ -116,14 +113,17 @@ class CoverDelegate(QStyledItemDelegate): # {{{
def paint(self, painter, option, index):
QStyledItemDelegate.paint(self, painter, option, index)
# Ensure the cover is rendered over any selection rect
style = QApplication.style()
style.drawItemPixmap(painter, option.rect, Qt.AlignTop|Qt.AlignHCenter,
QPixmap(index.data(Qt.DecorationRole)))
if self.timer.isActive() and index.data(Qt.UserRole).toBool():
waiting = self.timer.isActive() and index.data(Qt.UserRole).toBool()
if waiting:
rect = QRect(0, 0, self.spinner_width, self.spinner_width)
rect.moveCenter(option.rect.center())
self.draw_spinner(painter, rect)
else:
# Ensure the cover is rendered over any selection rect
style.drawItemPixmap(painter, option.rect, Qt.AlignTop|Qt.AlignHCenter,
QPixmap(index.data(Qt.DecorationRole)))
# }}}
class ResultsModel(QAbstractTableModel): # {{{
@ -949,7 +949,7 @@ class CoverFetch(QDialog): # {{{
# }}}
if __name__ == '__main__':
#DEBUG_DIALOG = True
DEBUG_DIALOG = True
app = QApplication([])
d = FullFetch()
d.start(title='great gatsby', authors=['fitzgerald'])

View File

@ -221,7 +221,12 @@ class Matches(QAbstractItemModel):
self.reset()
def reorder_matches(self):
self.matches = sorted(self.matches, key=lambda x: self.all_matches.index(x))
def keygen(x):
try:
return self.all_matches.index(x)
except:
return 100000
self.matches = sorted(self.matches, key=keygen)
class SearchFilter(SearchQueryParser):
@ -327,5 +332,6 @@ class SearchFilter(SearchQueryParser):
matches.add(sr)
break
except ValueError: # Unicode errors
import traceback
traceback.print_exc()
return matches

View File

@ -1756,7 +1756,8 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
return books_to_refresh
def set_metadata(self, id, mi, ignore_errors=False, set_title=True,
set_authors=True, commit=True, force_changes=False):
set_authors=True, commit=True, force_changes=False,
notify=True):
'''
Set metadata for the book `id` from the `Metadata` object `mi`
@ -1865,7 +1866,8 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
label=user_mi[key]['label'], commit=False)
if commit:
self.conn.commit()
self.notify('metadata', [id])
if notify:
self.notify('metadata', [id])
def authors_sort_strings(self, id, index_is_id=False):
'''
@ -2002,8 +2004,16 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
return False
if isbytestring(title):
title = title.decode(preferred_encoding, 'replace')
old_title = self.title(id, index_is_id=True)
# We cannot check if old_title == title as previous code might have
# already updated the cache
only_case_change = icu_lower(old_title) == icu_lower(title)
self.conn.execute('UPDATE books SET title=? WHERE id=?', (title, id))
self.data.set(id, self.FIELD_MAP['title'], title, row_is_id=True)
if only_case_change:
# SQLite update trigger will not update sort on a case change
self.conn.execute('UPDATE books SET sort=? WHERE id=?',
(title_sort(title), id))
ts = self.conn.get('SELECT sort FROM books WHERE id=?', (id,),
all=False)
if ts:

View File

@ -11,14 +11,14 @@ msgstr ""
"Project-Id-Version: ca\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-04-17 16:54+0000\n"
"PO-Revision-Date: 2011-04-17 19:55+0000\n"
"PO-Revision-Date: 2011-04-21 10:40+0000\n"
"Last-Translator: FerranRius <frius64@hotmail.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-04-18 04:49+0000\n"
"X-Generator: Launchpad (build 12735)\n"
"X-Launchpad-Export-Date: 2011-04-22 04:35+0000\n"
"X-Generator: Launchpad (build 12758)\n"
#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:56
msgid "Does absolutely nothing"
@ -18718,6 +18718,85 @@ msgid ""
"sony_collection_renaming_rules={'series':'Series', 'tags':'Tag'}\n"
"sony_collection_name_template='{category:||: }{value}'"
msgstr ""
"Especifica les regles de canvi de nom per a les col·leccions Sony. Aquest "
"ajustament\n"
"només saplica si sestableix la gestió de metadades a automàtica. Les "
"col·leccions\n"
"Sony sanomenen depenent de si el camp és estàndard o personalitzat. Una\n"
"col·lecció derivada dun camp estàndard rep el nom del valor del camp. Per "
"exemple,\n"
"si la columna estàndard «sèrie» conté el valor «Darkover», en nom de la "
"col·lecció\n"
"serà «Darkover». Una col·lecció derivada dun camp personalitzat tindrà el "
"nom del\n"
"camp afegit al valor. Per exemple, si una columna personalitzada de sèrie "
"anomenada\n"
"«Sèries meves» conté el nom «Darkover», la col·lecció es dirà per defecte "
"«Darkover \n"
"(Sèries meves)». Pel que fa a aquesta documentació, considerem que "
"«Darkover» és\n"
"el valor i «Sèries meves» la categoria. Si dos llibres tenen camps que "
"generen el\n"
"mateix nom de col·lecció, els dos llibres estaran a la col·lecció.\n"
"Aquest conjunt dajustaments us permet especificar com sanomenaran les \n"
"col·leccions per a camps estàndards o personalitzats. Es pot utilitzar per "
"afegir una\n"
"descripció a un camp estàndars, per exemple «Foo (Etiqueta)» en lloc de "
"«Foo».\n"
"També es pot utilitzar per forçar que múltiples camps acabin a una mateixa "
"col·lecció.\n"
"Per exemple, es pot forçar que els valors a «sèries», «#la_meva_sèrie_1» i \n"
"«#la_meva_sèrie_2» apareguin en col·leccions anomenades «algun_valor "
"(Sèrie)»,\n"
"fusionant els camps en un conjunt de col·leccions.\n"
"Hi ha dos ajustaments relacionats. El primer determina el nom de la "
"categoria que\n"
"sutilitza per a un camp de metadades. El segon és una plantilla que "
"sutilitza per\n"
"determinar com es combinen el valor i la categoria per crear el nom de la "
"col·lecció.\n"
"La sintaxi del primer ajustament, «sony_collection_renaming_rules», és:\n"
"{'nom_camp_de_cerca':'nom_categoria_a_utilitzar', 'nom_cerca':'nom', ...}\n"
"El segon ajustament «sony_collection_name_template», és una plantilla. "
"Utilitza el\n"
"mateix llenguatge que els quadres de connexions i les plantilles de desar. "
"Aquest\n"
"ajustament controla com es combinen el valor i la categoria per obtenir el "
"nom de la\n"
"col·lecció. Hi ha dos camps disponibles, {categoria} i {valor}. El camp "
"{valor} no\n"
"està mai buit. El camp {categoria} pot estar buit. Per defecte es posa el "
"valor primer\n"
"i després, si no està buida, la categoria entre parèntesis:\n"
"'{value} {category:|(|)}'\n"
"Exemples: Els primers tres exemples assumeixen que no sha canviat el segon\n"
"ajustament.\n"
"1: Es vol que tres columnes de sèries es fusionin en un conjunt de "
"col·leccions. El\n"
"nom de cerca de les columnes són «sèrie», «#sèrie_2» i «#sèrie_3». No es vol "
"res\n"
"entre parèntesis. El valor per a lajustament serà:\n"
"sony_collection_renaming_rules={'sèrie':'', '#sèrie_1':'', '#sèrie_2':''}\n"
"2: Es vol que la paraula «(Sèrie)» aparegui a les col·leccions obtingudes a "
"partir de\n"
"sèries i que la paraula «(Etiqueta)» aparegui a les col·leccions obtingudes "
"a partir\n"
"detiquetes. Serà:\n"
"sony_collection_renaming_rules={'series':'Sèrie', 'tags':'Etiqueta'}\n"
"3: Es vol fusionar «sèrie» i «#la_meva_sèrie» i que safegeixi al final del "
"nom de la\n"
"col lecció «(Sèrie)». La regla de canvi de nom serà:\n"
"sony_collection_renaming_rules={'series':'Sèrie', "
"'#la_meva_sèrie':'Series'}\n"
"4: Igual que a lexemple 2, però en lloc de tenir el nom de la categoria "
"entre\n"
"parèntesis i afegit al final del valor, es vol abans del valor i separat per "
"dos punts,\n"
"com a «Sèrie: Darkover». Sha de canviar la plantilla utilitzada per donar "
"format al\n"
"nom de categoria. Els dos ajustaments resultants seran:\n"
"sony_collection_renaming_rules={'series':'Sèrie', 'tags':'Etiqueta'}\n"
"sony_collection_name_template='{category:||: }{value}'"
#: /home/kovid/work/calibre/resources/default_tweaks.py:221
msgid "Specify how SONY collections are sorted"

File diff suppressed because it is too large Load Diff

View File

@ -8,13 +8,13 @@ msgstr ""
"Project-Id-Version: de\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-04-17 16:54+0000\n"
"PO-Revision-Date: 2011-04-20 15:20+0000\n"
"Last-Translator: Armin Geller <Unknown>\n"
"PO-Revision-Date: 2011-04-21 11:25+0000\n"
"Last-Translator: Christine Emrich <Unknown>\n"
"Language-Team: American English <kde-i18n-doc@lists.kde.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-04-21 04:37+0000\n"
"X-Launchpad-Export-Date: 2011-04-22 04:36+0000\n"
"X-Generator: Launchpad (build 12758)\n"
"Generated-By: pygettext.py 1.5\n"
@ -500,7 +500,7 @@ msgstr "Metadaten laden"
#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:1059
msgid "Control how calibre downloads ebook metadata from the net"
msgstr ""
"Kontrolle der calibre-Vorhehensweise beim Herunterladen von E-Book-Metadaten "
"Kontrolle der calibre-Vorhehensweise beim Herunterladen von eBook-Metadaten "
"aus dem Netz"
#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:1064
@ -4973,7 +4973,7 @@ msgstr "Fehlgeschlagen"
#: /home/kovid/work/calibre/src/calibre/gui2/actions/choose_library.py:317
msgid "Database integrity check failed, click Show details for details."
msgstr ""
"Die Überprüfung der Datenbankintegrität hat Fehler gefunden. Clicken Sie auf "
"Die Überprüfung der Datenbankintegrität hat Fehler gefunden. Klicken Sie auf "
"Details anzeigen für weitere Informationen."
#: /home/kovid/work/calibre/src/calibre/gui2/actions/choose_library.py:322
@ -9259,7 +9259,7 @@ msgstr "&Generate standard Cover"
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:579
msgid "&Remove cover"
msgstr "&Remove Cover"
msgstr "&Remove Umschlag"
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:580
msgid "Set from &ebook file(s)"
@ -10490,7 +10490,7 @@ msgstr "Neue Kategorie hinzufügen"
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories_ui.py:174
msgid "Rename the current category to the what is in the box"
msgstr ""
msgstr "Derzeitige Kategorie zum Inhalt der Eingabebox umbenennen"
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_categories_ui.py:176
msgid "Category filter: "
@ -11287,7 +11287,7 @@ msgstr "Schnellsuche durchführen (Sie können auch die Eingabetaste drücken)"
#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:197
msgid "Reset Quick Search"
msgstr "Quick Search löschen"
msgstr "Schnellsuche löschen"
#: /home/kovid/work/calibre/src/calibre/gui2/layout.py:213
msgid "Copy current search text (instead of search name)"
@ -11789,10 +11789,13 @@ msgid ""
"Failed to apply updated metadata for some books in your library. Click "
"\"Show Details\" to see details."
msgstr ""
"Die aktualisieren Metadaten konnten für einige Bücher Ihrer Bibliothek nicht "
"übernommen werden. Klicken Sie auf \"Zeige Details\" für weitere "
"Informationen."
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/bulk_download2.py:212
msgid "Some books changed"
msgstr ""
msgstr "Einige Bücher haben sich geändert"
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/bulk_download2.py:213
msgid ""
@ -11801,16 +11804,23 @@ msgid ""
"Click \"Show details\" to see the list of changed books. Do you want to "
"proceed?"
msgstr ""
"Die Metadaten einiger Bücher in Ihrer Bibliothek haben sich geändert seit "
"der Download gestartet wurde. Wenn Sie fortfahren, können diese Änderungen "
"verloren gehen. Klicken Sie auf \"Zeige Details\", um eine Liste aller "
"geändertern Bücher zu sehen. Möchten Sie fortfahren?"
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/bulk_download2.py:224
msgid "Metadata download completed"
msgstr ""
msgstr "Herunterladen der Metadaten abgeschlossen"
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/bulk_download2.py:228
msgid ""
"Could not download metadata and/or covers for %d of the books. Click \"Show "
"details\" to see which books."
msgstr ""
"Für %d der Bücher konnten Metadaten und/oder Umschlagbilder nicht "
"heruntergeladen werden. Klicken Sie auf \"Zeige Details\", um betroffene "
"Bücher anzuzeigen."
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/bulk_download2.py:234
msgid "(Failed metadata)"
@ -11825,30 +11835,32 @@ msgid ""
"Finished downloading metadata for <b>%d book(s)</b>. Proceed with updating "
"the metadata in your library?"
msgstr ""
"Erfolgreich Metadaten für <b>%d Buch/Bücher</b> heruntergeladen. Soll mit "
"dem Aktualisieren der Metadaten in Ihrer Bibliothek fortgefahren werden?"
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/bulk_download2.py:240
msgid "Download complete"
msgstr ""
msgstr "Herunterladen abgeschlossen"
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/bulk_download2.py:243
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single_download.py:827
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single_download.py:918
msgid "View log"
msgstr ""
msgstr "Log-Datei anschauen"
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/bulk_download2.py:315
msgid "Downloaded %d of %d"
msgstr ""
msgstr "%d von %d heruntergeladen"
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/config.py:58
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/metadata_sources_ui.py:106
msgid "Downloaded metadata fields"
msgstr ""
msgstr "Metadaten-Felder heruntergeladen"
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:75
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:237
msgid "Edit Metadata"
msgstr ""
msgstr "Metadaten bearbeiten"
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:112
msgid "Set author sort from author"
@ -11860,7 +11872,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:168
msgid "&Download metadata"
msgstr ""
msgstr "Metadaten &Herunterladen"
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:178
msgid "Change how calibre downloads metadata"
@ -11869,7 +11881,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:508
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:697
msgid "Change cover"
msgstr ""
msgstr "Umschlag ändern"
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:557
msgid "Co&mments"
@ -13823,7 +13835,7 @@ msgstr "Suche (Zur erweiterten Suche die Schaltfläche links klicken)"
#: /home/kovid/work/calibre/src/calibre/gui2/search_box.py:369
msgid "Enable or disable search highlighting."
msgstr ""
msgstr "Hervorhebung von Suchergebnissen an- oder ausschalten"
#: /home/kovid/work/calibre/src/calibre/gui2/search_box.py:424
msgid "Saved Searches"
@ -13838,7 +13850,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/search_restriction_mixin.py:34
#: /home/kovid/work/calibre/src/calibre/gui2/search_restriction_mixin.py:42
msgid "*Current search"
msgstr ""
msgstr "*Aktuelle Suche"
#: /home/kovid/work/calibre/src/calibre/gui2/search_restriction_mixin.py:12
msgid "Restrict to"
@ -14104,19 +14116,19 @@ msgstr "Der gespeicherte Such-Name %s wird schon verwendet."
#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1834
msgid "Manage Authors"
msgstr ""
msgstr "Autoren verwalten"
#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1836
msgid "Manage Series"
msgstr ""
msgstr "Reihen verwalten"
#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1838
msgid "Manage Publishers"
msgstr ""
msgstr "Herausgeber verwalten"
#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1840
msgid "Manage Tags"
msgstr ""
msgstr "Etiketten verwalten"
#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:1852
msgid "Invalid search restriction"
@ -14161,7 +14173,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:2089
msgid "Find item in tag browser"
msgstr ""
msgstr "Eintrag im Etiketten-Browser finden"
#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:2092
msgid ""
@ -14227,7 +14239,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:2171
msgid "Manage authors, tags, etc"
msgstr ""
msgstr "Autoren, Etiketten, etc. verwalten"
#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:2172
msgid ""

View File

@ -11,13 +11,13 @@ msgstr ""
"Project-Id-Version: es\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-04-17 16:54+0000\n"
"PO-Revision-Date: 2011-04-18 09:40+0000\n"
"PO-Revision-Date: 2011-04-21 15:39+0000\n"
"Last-Translator: Jellby <Unknown>\n"
"Language-Team: Spanish\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-04-19 04:39+0000\n"
"X-Launchpad-Export-Date: 2011-04-22 04:37+0000\n"
"X-Generator: Launchpad (build 12758)\n"
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:528
@ -18700,6 +18700,60 @@ msgid ""
"sony_collection_renaming_rules={'series':'Series', 'tags':'Tag'}\n"
"sony_collection_name_template='{category:||: }{value}'"
msgstr ""
"Especifica reglas para cambiar el nombre a las colecciones Sony. Este\n"
"ajuste sólo se aplica si la gestión de metadatos está establecida en\n"
"automática. Las colecciones en los lectores Sony se nombran según el campo\n"
"en que se basan sea predefinido o personalizado. Una colección derivada de\n"
"un campo predefinido se nombra con el valor contenido en dicho campo. Por\n"
"ejemplo, si el campo predefinido «series» contiene el valor «Darkover»,\n"
"entonces el nombre de la colección será «Darkover». Una colección derivada\n"
"de un campo personalizado tendrá el nombre del campo añadido al valor. Por\n"
"ejemplo, si un campo personalizado llamado «Mi serie» contiene el valor\n"
"«Darkover», entonces la colección se nombrará de manera predeterminada\n"
"«Darkover (Mi serie)». En lo que a esta documentación respecta, «Darkover»\n"
"se llamará el valor y «Mi serie» se llamará la categoría. Si dos libros\n"
"tienen campos que generan el mismo nombre de colección, ambos se incluirán\n"
"en la misma colección.\n"
"Este conjunto de ajustes le permite especificar, para un campo predefinido\n"
"o personalizado, cómo se nombrarán las colecciones. Puede usarlo para\n"
"añadir una descripción a una etiqueta, por ejemplo «Bla (etiqueta)» en\n"
"lugar de «Bla». También puede usarlo para hacer que distintos campos acaben\n"
"en la misma colección. Por ejemplo, puede hacer que los valores en\n"
"«series», «#mi_serie_1» y «#mi_serie_2» aparezcan en colecciones llamadas\n"
"«algún_valor (Serie)», uniendo todos los campos en un mismo grupo de\n"
"colecciones.\n"
"Hay dos ajustes relacionados. El primero determina el nombre de categoría\n"
"que se usará para un campo de metadatos. El segundo es una plantilla y se\n"
"usa para determinar cómo se combinarán el valor y la categoría para crear\n"
"el nombre de colección. La sintaxis del primer ajuste,\n"
"«sony_collection_renaming_rules», es:\n"
"{«nombre_de_búsqueda_del_campo»:«nombre_de_categoría»,\n"
"«nombre_de_búsqueda»:«categoría», ...}. El segundo ajuste,\n"
"«sony_collection_name_template», es una plantilla. Emplea el mismo lenguaje\n"
"de plantilla que los controles de metadatos y las plantillas de guardado.\n"
"Los únicos dos campos disponibles son «{category}» y «{value}». El campo\n"
"«{value}» nunca está vacío. El campo «{category}» puede estar vacío. El\n"
"comportamiento predeterminado es poner primero el valor y después la\n"
"categoría entre paréntesis si no está vacía: «{value} {category:|(|)}».\n"
"Ejemplos: Los dos primeros ejemplos suponen que el segundo ajuste no se ha\n"
"cambiado.\n"
"1: Quiero unir tres campos de serie en un solo conjunto de colecciones. Los\n"
"nombres de búsqueda de los campos son «series», «#serie_1» y «#serie_2». No\n"
"quiero nada entre paréntesis. El valor que se usaría para el ajuste es:\n"
"sony_collection_renaming_rules={'series':'', '#serie_1':'', '#serie_2':''}\n"
"2: Quiero que la palabra «(Serie)» aparezca en las colecciones creadas a\n"
"partir de series y la palabra «(Etiqueta)» en las creadas a partir de\n"
"etiquetas. Se usaría:\n"
"sony_collection_renaming_rules={'series':'Serie', 'tags':'Etiqueta'}\n"
"3: Quiero unir «series» y «#miserie» y añadir «(Serie)» al nombre de la\n"
"colección. Se usaría:\n"
"sony_collection_renaming_rules={'series':'Serie', '#myserie':'Serie'}\n"
"4: Como en el ejemplo 2, pero en lugar de añadir el nombre de categoría\n"
"entre paréntesis después del valor, lo quiero delante y separado por dos\n"
"puntos, como en «Serie: Darkover». Tengo que cambiar la plantilla usada\n"
"para dar formato al nombre de colección. Los ajustes resultantes son:\n"
"sony_collection_renaming_rules={'series':'Serie', 'tags':'Etiqueta'}\n"
"sony_collection_name_template='{category:||: }{value}'"
#: /home/kovid/work/calibre/resources/default_tweaks.py:221
msgid "Specify how SONY collections are sorted"
@ -18731,6 +18785,28 @@ msgid ""
"[ ( [list of fields], sort field ) , ( [ list of fields ] , sort field ) ]\n"
"Default: empty (no rules), so no collection attributes are named."
msgstr ""
"Especifica cómo se ordenan las colecciones Sony. Este ajuste sólo se\n"
"aplica si la gestión de metadatos está establecida en automática. Puede\n"
"definir qué campo de metadatos se usara para ordenar cada colección.\n"
"El formato del ajuste es una lista de campos de metadatos a partir de los\n"
"cuales se construyen las colecciones, seguida del nombre del campo que\n"
"contiene el valor de orden.\n"
"Ejemplo: Lo siguiente indica que las colecciones creadas a partir de "
"«pubdate»\n"
"y «tags» se ordenarán según el valor contenido en la columna personalizada\n"
"«#mifecha», que las colecciones creadas a partir de «series» se ordenan\n"
"según «series_index» y que el resto de las colecciones se ordenan por\n"
"título. Si un campo de colecciones no se nombra, entonces la colección\n"
"se ordenará por índice de serie si está basada en series y por título\n"
"en caso contrario.\n"
"[(['pubdate', 'tags'],'#mydate'), (['series'],'series_index'), (['*'], "
"'title')]\n"
"Tenga en cuenta que los corchetes y paréntesis son necesarios.\n"
"La sintaxis es:\n"
"[ ( [lista de campos], campo de orden ) , ( [ lista de campos ] , campo de "
"orden ) ]\n"
"Valor predeterminado: vacío (sin reglas), con lo que no se nombra\n"
"ningún atributo de colecciones."
#: /home/kovid/work/calibre/resources/default_tweaks.py:240
msgid "Control how tags are applied when copying books to another library"
@ -18777,6 +18853,22 @@ msgid ""
"content_server_will_display = ['*']\n"
"content_server_wont_display['#mycomments']"
msgstr ""
"«content_server_will_display» es una lista de campos personalizados que\n"
"se mostrarán, «content_server_wont_display» es una lista de campos\n"
"personalizados que no se mostrarán. El segundo tiene preferencia sobre\n"
"el primero.\n"
"El valor especial «*» indica todos los campos personalizados. El valor «[]»\n"
"indica que no hay entradas.\n"
"Valores predeterminados:\n"
"content_server_will_display = ['*']\n"
"content_server_wont_display = []\n"
"Ejemplos:\n"
"Para mostrar sólo los campos personalizados «#misetiquetas» y «#genero»:\n"
"content_server_will_display = ['#misetiquetas', '#genero']\n"
"content_server_wont_display = []\n"
"Para mostrar todos los campos excepto «#miscomentarios»:\n"
"content_server_will_display = ['*']\n"
"content_server_wont_display = ['#mycomments']"
#: /home/kovid/work/calibre/resources/default_tweaks.py:268
msgid ""
@ -18806,6 +18898,24 @@ msgid ""
"As above, this tweak affects only display of custom fields. The standard\n"
"fields are not affected"
msgstr ""
"«book_details_will_display» es una lista de campos personalizados que\n"
"se mostrarán, «book_details_wont_display» es una lista de campos\n"
"personalizados que no se mostrarán. El segundo tiene preferencia sobre\n"
"el primero.\n"
"El valor especial «*» indica todos los campos personalizados. El valor «[]»\n"
"indica que no hay entradas.\n"
"Valores predeterminados:\n"
"book_details_will_display = ['*']\n"
"book_details_wont_display = []\n"
"Ejemplos:\n"
"Para mostrar sólo los campos personalizados «#misetiquetas» y «#genero»:\n"
"book_details_will_display = ['#misetiquetas', '#genero']\n"
"book_details_wont_display = []\n"
"Para mostrar todos los campos excepto «#miscomentarios»:\n"
"book_details_will_display = ['*']\n"
"book_details_wont_display = ['#mycomments']\n"
"Este ajuste sólo afecta a los campos personalizados. Los campos\n"
"predefinidos no se ven afectados."
#: /home/kovid/work/calibre/resources/default_tweaks.py:288
msgid "Set the maximum number of sort 'levels'"

View File

@ -8,13 +8,13 @@ msgstr ""
"Project-Id-Version: calibre\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-04-17 16:54+0000\n"
"PO-Revision-Date: 2011-04-20 09:22+0000\n"
"PO-Revision-Date: 2011-04-21 07:36+0000\n"
"Last-Translator: Anca Stratulat <Unknown>\n"
"Language-Team: Romanian <ro@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-04-21 04:37+0000\n"
"X-Launchpad-Export-Date: 2011-04-22 04:36+0000\n"
"X-Generator: Launchpad (build 12758)\n"
#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:56
@ -2427,12 +2427,17 @@ msgid ""
"Left aligned scene break markers are center aligned. Replace soft scene "
"breaks that use multiple blank lines withhorizontal rules."
msgstr ""
"Marker-ii separatorilor de text aliniaţi la stanga sunt aliniaţi central. "
"Înlocuiţi separatorii fini ai textului care utilizează multiple linii goale "
"cu reguli orizontale."
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:547
msgid ""
"Replace scene breaks with the specified text. By default, the text from the "
"input document is used."
msgstr ""
"Înlocuieşte separatorii textului cu textul specificat. Împlicit, textul din "
"documentul iniţial este utilizat."
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:552
msgid ""
@ -2440,20 +2445,25 @@ msgid ""
"used as a dictionary to determine whether hyphens should be retained or "
"removed."
msgstr ""
"Analizaţi cuvintele despărţite în silabe din întregul document. Documentul "
"în sine este folosit ca un dicţionar pentru a determina dacă cratimele ar "
"trebui să fie păstrate sau eliminate."
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:558
msgid ""
"Looks for occurrences of sequential <h1> or <h2> tags. The tags are "
"renumbered to prevent splitting in the middle of chapter headings."
msgstr ""
"Caută evenimente secvenţale ale etichetelor <h1> sau <h2>. Etichetele sunt "
"renumerotate pentru a preveni scindarea în mijlocul capitolului."
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:564
msgid "Search pattern (regular expression) to be replaced with sr1-replace."
msgstr ""
msgstr "Model de cautare (expresie comună) înlocuit cu sr1."
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:569
msgid "Replacement to replace the text found with sr1-search."
msgstr ""
msgstr "Înlocuieste textul găsit cu o căutare sr1."
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:573
msgid "Search pattern (regular expression) to be replaced with sr2-replace."