mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Merge from trunk
This commit is contained in:
commit
e2038a71dd
@ -29,6 +29,10 @@ class WashingtonPost(BasicNewsRecipe):
|
||||
('Technology', 'http://www.washingtonpost.com/wp-dyn/rss/technology/index.xml'),
|
||||
('Health', 'http://www.washingtonpost.com/wp-dyn/rss/health/index.xml'),
|
||||
('Education', 'http://www.washingtonpost.com/wp-dyn/rss/education/index.xml'),
|
||||
('Style',
|
||||
'http://www.washingtonpost.com/wp-dyn/rss/print/style/index.xml'),
|
||||
('Sports',
|
||||
'http://feeds.washingtonpost.com/wp-dyn/rss/linkset/2010/08/19/LI2010081904067_xml'),
|
||||
('Editorials', 'http://www.washingtonpost.com/wp-dyn/rss/linkset/2005/05/30/LI2005053000331.xml'),
|
||||
]
|
||||
|
||||
|
@ -455,6 +455,24 @@ def prepare_string_for_xml(raw, attribute=False):
|
||||
def isbytestring(obj):
|
||||
return isinstance(obj, (str, bytes))
|
||||
|
||||
def force_unicode(obj, enc=preferred_encoding):
|
||||
if isbytestring(obj):
|
||||
try:
|
||||
obj = obj.decode(enc)
|
||||
except:
|
||||
try:
|
||||
obj = obj.decode(filesystem_encoding if enc ==
|
||||
preferred_encoding else preferred_encoding)
|
||||
except:
|
||||
try:
|
||||
obj = obj.decode('utf-8')
|
||||
except:
|
||||
obj = repr(obj)
|
||||
if isbytestring(obj):
|
||||
obj = obj.decode('utf-8')
|
||||
return obj
|
||||
|
||||
|
||||
def human_readable(size):
|
||||
""" Convert a size in bytes into a human readable form """
|
||||
divisor, suffix = 1, "B"
|
||||
|
@ -707,7 +707,7 @@ OptionRecommendation(name='timestamp',
|
||||
if mi.cover.startswith('http:') or mi.cover.startswith('https:'):
|
||||
mi.cover = self.download_cover(mi.cover)
|
||||
ext = mi.cover.rpartition('.')[-1].lower().strip()
|
||||
if ext not in ('png', 'jpg', 'jpeg'):
|
||||
if ext not in ('png', 'jpg', 'jpeg', 'gif'):
|
||||
ext = 'jpg'
|
||||
mi.cover_data = (ext, open(mi.cover, 'rb').read())
|
||||
mi.cover = None
|
||||
|
@ -654,8 +654,6 @@ class Metadata(object):
|
||||
if predicate(x):
|
||||
l.remove(x)
|
||||
|
||||
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self.items[key]
|
||||
|
||||
|
@ -132,17 +132,23 @@ class OEBReader(object):
|
||||
if not mi.language:
|
||||
mi.language = get_lang().replace('_', '-')
|
||||
self.oeb.metadata.add('language', mi.language)
|
||||
if not mi.title:
|
||||
mi.title = self.oeb.translate(__('Unknown'))
|
||||
if not mi.authors:
|
||||
mi.authors = [self.oeb.translate(__('Unknown'))]
|
||||
if not mi.book_producer:
|
||||
mi.book_producer = '%(a)s (%(v)s) [http://%(a)s.kovidgoyal.net]'%\
|
||||
mi.book_producer = '%(a)s (%(v)s) [http://%(a)s-ebook.com]'%\
|
||||
dict(a=__appname__, v=__version__)
|
||||
meta_info_to_oeb_metadata(mi, self.oeb.metadata, self.logger)
|
||||
self.oeb.metadata.add('identifier', str(uuid.uuid4()), id='uuid_id',
|
||||
scheme='uuid')
|
||||
m = self.oeb.metadata
|
||||
m.add('identifier', str(uuid.uuid4()), id='uuid_id', scheme='uuid')
|
||||
self.oeb.uid = self.oeb.metadata.identifier[-1]
|
||||
if not m.title:
|
||||
m.add('title', self.oeb.translate(__('Unknown')))
|
||||
has_aut = False
|
||||
for x in m.creator:
|
||||
if getattr(x, 'role', '').lower() in ('', 'aut'):
|
||||
has_aut = True
|
||||
break
|
||||
if not has_aut:
|
||||
m.add('creator', self.oeb.translate(__('Unknown')), role='aut')
|
||||
|
||||
|
||||
def _manifest_prune_invalid(self):
|
||||
'''
|
||||
|
@ -3,6 +3,7 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
""" The GUI """
|
||||
import os, sys, Queue, threading
|
||||
from threading import RLock
|
||||
from urllib import unquote
|
||||
|
||||
from PyQt4.Qt import QVariant, QFileInfo, QObject, SIGNAL, QBuffer, Qt, \
|
||||
QByteArray, QTranslator, QCoreApplication, QThread, \
|
||||
@ -505,6 +506,11 @@ class FileDialog(QObject):
|
||||
fs = QFileDialog.getOpenFileNames(parent, title, initial_dir, ftext, "")
|
||||
for f in fs:
|
||||
f = unicode(f)
|
||||
if not f: continue
|
||||
if not os.path.exists(f):
|
||||
# QFileDialog for some reason quotes spaces
|
||||
# on linux if there is more than one space in a row
|
||||
f = unquote(f)
|
||||
if f and os.path.exists(f):
|
||||
self.selected_files.append(f)
|
||||
else:
|
||||
|
@ -234,13 +234,14 @@ class AddAction(InterfaceAction):
|
||||
self.gui.set_books_in_library(booklists=[model.db], reset=True)
|
||||
self.gui.refresh_ondevice()
|
||||
|
||||
def add_books_from_device(self, view):
|
||||
def add_books_from_device(self, view, paths=None):
|
||||
if paths is None:
|
||||
rows = view.selectionModel().selectedRows()
|
||||
if not rows or len(rows) == 0:
|
||||
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]
|
||||
paths = [p for p in view.model().paths(rows) if p is not None]
|
||||
ve = self.gui.device_manager.device.VIRTUAL_BOOK_EXTENSIONS
|
||||
def ext(x):
|
||||
ans = os.path.splitext(x)[1]
|
||||
@ -261,7 +262,7 @@ class AddAction(InterfaceAction):
|
||||
return
|
||||
from calibre.gui2.add import Adder
|
||||
self.__adder_func = partial(self._add_from_device_adder, on_card=None,
|
||||
model=view._model)
|
||||
model=view.model())
|
||||
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)
|
||||
|
@ -21,7 +21,10 @@ from calibre.gui2.convert import Widget
|
||||
def create_opf_file(db, book_id):
|
||||
mi = db.get_metadata(book_id, index_is_id=True)
|
||||
mi.application_id = uuid.uuid4()
|
||||
old_cover = mi.cover
|
||||
mi.cover = None
|
||||
raw = metadata_to_opf(mi)
|
||||
mi.cover = old_cover
|
||||
opf_file = PersistentTemporaryFile('.opf')
|
||||
opf_file.write(raw)
|
||||
opf_file.close()
|
||||
|
@ -23,7 +23,7 @@ from calibre.gui2 import config, error_dialog, Dispatcher, dynamic, \
|
||||
warning_dialog, \
|
||||
question_dialog, info_dialog, choose_dir
|
||||
from calibre.ebooks.metadata import authors_to_string
|
||||
from calibre import preferred_encoding, prints
|
||||
from calibre import preferred_encoding, prints, force_unicode
|
||||
from calibre.utils.filenames import ascii_filename
|
||||
from calibre.devices.errors import FreeSpaceError
|
||||
from calibre.utils.smtp import compose_mail, sendmail, extract_email_address, \
|
||||
@ -964,12 +964,12 @@ class DeviceMixin(object): # {{{
|
||||
for jobname, exception, tb in results:
|
||||
title = jobname.partition(':')[-1]
|
||||
if exception is not None:
|
||||
errors.append([title, exception, tb])
|
||||
errors.append(list(map(force_unicode, [title, exception, tb])))
|
||||
else:
|
||||
good.append(title)
|
||||
if errors:
|
||||
errors = '\n'.join([
|
||||
'%s\n\n%s\n%s\n' %
|
||||
errors = u'\n'.join([
|
||||
u'%s\n\n%s\n%s\n' %
|
||||
(title, e, tb) for \
|
||||
title, e, tb in errors
|
||||
])
|
||||
|
@ -375,7 +375,7 @@ p, li { white-space: pre-wrap; }
|
||||
<item>
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>For help with writing advanced news recipes, please visit <a href="http://__appname__.kovidgoyal.net/user_manual/news.html">User Recipes</a></string>
|
||||
<string>For help with writing advanced news recipes, please visit <a href="http://__appname__-ebook.com/user_manual/news.html">User Recipes</a></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
|
@ -56,6 +56,7 @@ class LocationManager(QObject): # {{{
|
||||
self._mem.append(a)
|
||||
else:
|
||||
ac.setToolTip(tooltip)
|
||||
ac.calibre_name = name
|
||||
|
||||
return ac
|
||||
|
||||
@ -112,7 +113,6 @@ class LocationManager(QObject): # {{{
|
||||
ac.setWhatsThis(t)
|
||||
ac.setStatusTip(t)
|
||||
|
||||
|
||||
@property
|
||||
def has_device(self):
|
||||
return max(self.free) > -1
|
||||
@ -228,6 +228,7 @@ class ToolBar(QToolBar): # {{{
|
||||
self.added_actions = []
|
||||
self.build_bar()
|
||||
self.preferred_width = self.sizeHint().width()
|
||||
self.setAcceptDrops(True)
|
||||
|
||||
def apply_settings(self):
|
||||
sz = gprefs['toolbar_icon_size']
|
||||
@ -317,6 +318,59 @@ class ToolBar(QToolBar): # {{{
|
||||
def database_changed(self, db):
|
||||
pass
|
||||
|
||||
#support drag&drop from/to library from/to reader/card
|
||||
def dragEnterEvent(self, event):
|
||||
md = event.mimeData()
|
||||
if md.hasFormat("application/calibre+from_library") or \
|
||||
md.hasFormat("application/calibre+from_device"):
|
||||
event.setDropAction(Qt.CopyAction)
|
||||
event.accept()
|
||||
else:
|
||||
event.ignore()
|
||||
|
||||
def dragMoveEvent(self, event):
|
||||
allowed = False
|
||||
md = event.mimeData()
|
||||
#Drop is only allowed in the location manager widget's different from the selected one
|
||||
for ac in self.location_manager.available_actions:
|
||||
w = self.widgetForAction(ac)
|
||||
if w is not None:
|
||||
if ( md.hasFormat("application/calibre+from_library") or \
|
||||
md.hasFormat("application/calibre+from_device") ) and \
|
||||
w.geometry().contains(event.pos()) and \
|
||||
isinstance(w, QToolButton) and not w.isChecked():
|
||||
allowed = True
|
||||
break
|
||||
if allowed:
|
||||
event.acceptProposedAction()
|
||||
else:
|
||||
event.ignore()
|
||||
|
||||
def dropEvent(self, event):
|
||||
data = event.mimeData()
|
||||
|
||||
mime = 'application/calibre+from_library'
|
||||
if data.hasFormat(mime):
|
||||
ids = list(map(int, str(data.data(mime)).split()))
|
||||
tgt = None
|
||||
for ac in self.location_manager.available_actions:
|
||||
w = self.widgetForAction(ac)
|
||||
if w is not None and w.geometry().contains(event.pos()):
|
||||
tgt = ac.calibre_name
|
||||
if tgt is not None:
|
||||
if tgt == 'main':
|
||||
tgt = None
|
||||
self.gui.sync_to_device(tgt, False, send_ids=ids)
|
||||
event.accept()
|
||||
|
||||
mime = 'application/calibre+from_device'
|
||||
if data.hasFormat(mime):
|
||||
paths = [unicode(u.toLocalFile()) for u in data.urls()]
|
||||
if paths:
|
||||
self.gui.iactions['Add Books'].add_books_from_device(
|
||||
self.gui.current_view(), paths=paths)
|
||||
event.accept()
|
||||
|
||||
# }}}
|
||||
|
||||
class MainWindowMixin(object): # {{{
|
||||
|
@ -1081,12 +1081,11 @@ class DeviceBooksModel(BooksModel): # {{{
|
||||
self.db = db
|
||||
self.map = list(range(0, len(db)))
|
||||
|
||||
def current_changed(self, current, previous):
|
||||
data = {}
|
||||
item = self.db[self.map[current.row()]]
|
||||
def cover(self, row):
|
||||
item = self.db[self.map[row]]
|
||||
cdata = item.thumbnail
|
||||
if cdata is not None:
|
||||
img = QImage()
|
||||
if cdata is not None:
|
||||
if hasattr(cdata, 'image_path'):
|
||||
img.load(cdata.image_path)
|
||||
elif cdata:
|
||||
@ -1096,7 +1095,14 @@ class DeviceBooksModel(BooksModel): # {{{
|
||||
img.loadFromData(cdata)
|
||||
if img.isNull():
|
||||
img = self.default_image
|
||||
data['cover'] = img
|
||||
return img
|
||||
|
||||
def current_changed(self, current, previous):
|
||||
data = {}
|
||||
item = self.db[self.map[current.row()]]
|
||||
cover = self.cover(current.row())
|
||||
if cover is not self.default_image:
|
||||
data['cover'] = cover
|
||||
type = _('Unknown')
|
||||
ext = os.path.splitext(item.path)[1]
|
||||
if ext:
|
||||
|
@ -9,7 +9,8 @@ import os
|
||||
from functools import partial
|
||||
|
||||
from PyQt4.Qt import QTableView, Qt, QAbstractItemView, QMenu, pyqtSignal, \
|
||||
QModelIndex, QIcon, QItemSelection
|
||||
QModelIndex, QIcon, QItemSelection, QMimeData, QDrag, QApplication, \
|
||||
QPoint, QPixmap, QUrl, QImage, QPainter, QColor, QRect
|
||||
|
||||
from calibre.gui2.library.delegates import RatingDelegate, PubDateDelegate, \
|
||||
TextDelegate, DateDelegate, TagsDelegate, CcTextDelegate, \
|
||||
@ -18,7 +19,8 @@ from calibre.gui2.library.models import BooksModel, DeviceBooksModel
|
||||
from calibre.utils.config import tweaks, prefs
|
||||
from calibre.gui2 import error_dialog, gprefs
|
||||
from calibre.gui2.library import DEFAULT_SORT
|
||||
|
||||
from calibre.constants import filesystem_encoding
|
||||
from calibre import force_unicode
|
||||
|
||||
class BooksView(QTableView): # {{{
|
||||
|
||||
@ -31,6 +33,7 @@ class BooksView(QTableView): # {{{
|
||||
self.setDragEnabled(True)
|
||||
self.setDragDropOverwriteMode(False)
|
||||
self.setDragDropMode(self.DragDrop)
|
||||
self.drag_start_pos = None
|
||||
self.setAlternatingRowColors(True)
|
||||
self.setSelectionBehavior(self.SelectRows)
|
||||
self.setShowGrid(False)
|
||||
@ -426,6 +429,69 @@ class BooksView(QTableView): # {{{
|
||||
urls = [unicode(u.toLocalFile()) for u in event.mimeData().urls()]
|
||||
return [u for u in urls if os.path.splitext(u)[1] and os.access(u, os.R_OK)]
|
||||
|
||||
def drag_icon(self, cover, multiple):
|
||||
cover = cover.scaledToHeight(120, Qt.SmoothTransformation)
|
||||
if multiple:
|
||||
base_width = cover.width()
|
||||
base_height = cover.height()
|
||||
base = QImage(base_width+21, base_height+21,
|
||||
QImage.Format_ARGB32_Premultiplied)
|
||||
base.fill(QColor(255, 255, 255, 0).rgba())
|
||||
p = QPainter(base)
|
||||
rect = QRect(20, 0, base_width, base_height)
|
||||
p.fillRect(rect, QColor('white'))
|
||||
p.drawRect(rect)
|
||||
rect.moveLeft(10)
|
||||
rect.moveTop(10)
|
||||
p.fillRect(rect, QColor('white'))
|
||||
p.drawRect(rect)
|
||||
rect.moveLeft(0)
|
||||
rect.moveTop(20)
|
||||
p.fillRect(rect, QColor('white'))
|
||||
p.save()
|
||||
p.setCompositionMode(p.CompositionMode_SourceAtop)
|
||||
p.drawImage(rect.topLeft(), cover)
|
||||
p.restore()
|
||||
p.drawRect(rect)
|
||||
p.end()
|
||||
cover = base
|
||||
return QPixmap.fromImage(cover)
|
||||
|
||||
def drag_data(self):
|
||||
m = self.model()
|
||||
db = m.db
|
||||
rows = self.selectionModel().selectedRows()
|
||||
selected = map(m.id, rows)
|
||||
ids = ' '.join(map(str, selected))
|
||||
md = QMimeData()
|
||||
md.setData('application/calibre+from_library', ids)
|
||||
md.setUrls([QUrl.fromLocalFile(db.abspath(i, index_is_id=True))
|
||||
for i in selected])
|
||||
drag = QDrag(self)
|
||||
drag.setMimeData(md)
|
||||
cover = self.drag_icon(m.cover(self.currentIndex().row()),
|
||||
len(selected) > 1)
|
||||
drag.setHotSpot(QPoint(cover.width()//3, cover.height()//3))
|
||||
drag.setPixmap(cover)
|
||||
return drag
|
||||
|
||||
def mousePressEvent(self, event):
|
||||
if event.button() == Qt.LeftButton:
|
||||
self.drag_start_pos = event.pos()
|
||||
return QTableView.mousePressEvent(self, event)
|
||||
|
||||
def mouseMoveEvent(self, event):
|
||||
if not (event.buttons() & Qt.LeftButton) or self.drag_start_pos is None:
|
||||
return
|
||||
if (event.pos() - self.drag_start_pos).manhattanLength() \
|
||||
< QApplication.startDragDistance():
|
||||
return
|
||||
index = self.indexAt(event.pos())
|
||||
if not index.isValid():
|
||||
return
|
||||
drag = self.drag_data()
|
||||
drag.exec_(Qt.CopyAction)
|
||||
|
||||
def dragEnterEvent(self, event):
|
||||
if int(event.possibleActions() & Qt.CopyAction) + \
|
||||
int(event.possibleActions() & Qt.MoveAction) == 0:
|
||||
@ -547,6 +613,21 @@ class DeviceBooksView(BooksView): # {{{
|
||||
self.setDragDropMode(self.NoDragDrop)
|
||||
self.setAcceptDrops(False)
|
||||
|
||||
def drag_data(self):
|
||||
m = self.model()
|
||||
rows = self.selectionModel().selectedRows()
|
||||
paths = [force_unicode(p, enc=filesystem_encoding) for p in m.paths(rows) if p]
|
||||
md = QMimeData()
|
||||
md.setData('application/calibre+from_device', 'dummy')
|
||||
md.setUrls([QUrl.fromLocalFile(p) for p in paths])
|
||||
drag = QDrag(self)
|
||||
drag.setMimeData(md)
|
||||
cover = self.drag_icon(m.cover(self.currentIndex().row()), len(paths) >
|
||||
1)
|
||||
drag.setHotSpot(QPoint(cover.width()//3, cover.height()//3))
|
||||
drag.setPixmap(cover)
|
||||
return drag
|
||||
|
||||
def contextMenuEvent(self, event):
|
||||
edit_collections = callable(getattr(self._model.db, 'supports_collections', None)) and \
|
||||
self._model.db.supports_collections() and \
|
||||
|
@ -302,7 +302,7 @@ def do_add_empty(db, title, authors, isbn):
|
||||
if isbn:
|
||||
mi.isbn = isbn
|
||||
db.import_book(mi, [])
|
||||
write_dirtied()
|
||||
write_dirtied(db)
|
||||
send_message()
|
||||
|
||||
def command_add(args, dbpath):
|
||||
@ -456,7 +456,7 @@ def do_set_metadata(db, id, stream):
|
||||
db.set_metadata(id, mi)
|
||||
db.clean()
|
||||
do_show_metadata(db, id, False)
|
||||
write_dirtied()
|
||||
write_dirtied(db)
|
||||
send_message()
|
||||
|
||||
def set_metadata_option_parser():
|
||||
|
@ -19,7 +19,7 @@ from calibre.ebooks.metadata.meta import set_metadata
|
||||
from calibre.constants import preferred_encoding, filesystem_encoding
|
||||
from calibre.ebooks.metadata import fmt_sidx
|
||||
from calibre.ebooks.metadata import title_sort
|
||||
from calibre import strftime
|
||||
from calibre import strftime, prints
|
||||
|
||||
plugboard_any_device_value = 'any device'
|
||||
plugboard_any_format_value = 'any format'
|
||||
|
@ -18,7 +18,7 @@ Editing the metadata of one book at a time
|
||||
|
||||
Click the book you want to edit and then click the :guilabel:`Edit metadata` button or press the ``E`` key. A dialog opens that allows you to edit all aspects of the metadata. It has various features to make editing faster and more efficient. A list of the commonly used tips:
|
||||
|
||||
* You can click the button in between title and authors to swap them automatically. Or
|
||||
* You can click the button in between title and authors to swap them automatically.
|
||||
* You can click the button next to author sort to automatically to have |app| automatically fill it from the author name.
|
||||
* You can click the button next to tags to use the Tag Editor to manage the tags associated with the book.
|
||||
* The ISBN box will have a red background if you enter an invalid ISBN. It will be green for valid ISBNs
|
||||
|
@ -6,7 +6,7 @@ __docformat__ = 'restructuredtext en'
|
||||
Perform various initialization tasks.
|
||||
'''
|
||||
|
||||
import locale, sys, os
|
||||
import locale, sys, os, re
|
||||
|
||||
# Default translation is NOOP
|
||||
import __builtin__
|
||||
@ -114,6 +114,34 @@ if not _run_once:
|
||||
r, w, a, rb, wb, ab, r+, w+, a+, r+b, w+b, a+b
|
||||
'''
|
||||
if iswindows:
|
||||
class fwrapper(object):
|
||||
def __init__(self, name, fobject):
|
||||
object.__setattr__(self, 'fobject', fobject)
|
||||
object.__setattr__(self, 'name', name)
|
||||
|
||||
def __getattribute__(self, attr):
|
||||
if attr == 'name':
|
||||
return object.__getattribute__(self, attr)
|
||||
fobject = object.__getattribute__(self, 'fobject')
|
||||
return getattr(fobject, attr)
|
||||
|
||||
def __setattr__(self, attr, val):
|
||||
fobject = object.__getattribute__(self, 'fobject')
|
||||
return setattr(fobject, attr, val)
|
||||
|
||||
def __repr__(self):
|
||||
fobject = object.__getattribute__(self, 'fobject')
|
||||
name = object.__getattribute__(self, 'name')
|
||||
return re.sub(r'''['"]<fdopen>['"]''', repr(name),
|
||||
repr(fobject))
|
||||
|
||||
def __str__(self):
|
||||
return repr(self)
|
||||
|
||||
def __unicode__(self):
|
||||
return repr(self).decode('utf-8')
|
||||
|
||||
|
||||
m = mode[0]
|
||||
random = len(mode) > 1 and mode[1] == '+'
|
||||
binary = mode[-1] == 'b'
|
||||
@ -139,6 +167,7 @@ if not _run_once:
|
||||
flags |= os.O_NOINHERIT
|
||||
fd = os.open(name, flags)
|
||||
ans = os.fdopen(fd, mode, bufsize)
|
||||
ans = fwrapper(name, ans)
|
||||
else:
|
||||
import fcntl
|
||||
try:
|
||||
|
@ -5,8 +5,8 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: calibre 0.7.21\n"
|
||||
"POT-Creation-Date: 2010-10-01 14:42+MDT\n"
|
||||
"PO-Revision-Date: 2010-10-01 14:42+MDT\n"
|
||||
"POT-Creation-Date: 2010-10-02 11:26+MDT\n"
|
||||
"PO-Revision-Date: 2010-10-02 11:26+MDT\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: LANGUAGE\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -10057,7 +10057,7 @@ msgid ""
|
||||
" files in each directory of the calibre library. This is\n"
|
||||
" useful if your metadata.db file has been corrupted.\n"
|
||||
"\n"
|
||||
" WARNING: This completely regenrates your datbase. You will\n"
|
||||
" WARNING: This completely regenerates your datbase. You will\n"
|
||||
" lose stored per-book conversion settings and custom recipes.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
Loading…
x
Reference in New Issue
Block a user