%PDF- %PDF-
Direktori : /usr/lib/calibre/calibre/gui2/convert/ |
Current File : //usr/lib/calibre/calibre/gui2/convert/metadata.py |
#!/usr/bin/env python3 __license__ = 'GPL v3' __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>' __docformat__ = 'restructuredtext en' import os, re, errno from qt.core import QPixmap from calibre.gui2 import choose_images, error_dialog from calibre.gui2.convert.metadata_ui import Ui_Form from calibre.ebooks.metadata import (string_to_authors, MetaInformation, title_sort) from calibre.ebooks.metadata.opf2 import metadata_to_opf from calibre.ptempfile import PersistentTemporaryFile from calibre.gui2.convert import Widget from calibre.utils.icu import sort_key from calibre.library.comments import comments_to_html from calibre.utils.config import tweaks from calibre.ebooks.conversion.config import OPTIONS def create_opf_file(db, book_id, opf_file=None): mi = db.get_metadata(book_id, index_is_id=True) old_cover = mi.cover mi.cover = None mi.application_id = mi.uuid raw = metadata_to_opf(mi) mi.cover = old_cover if opf_file is None: opf_file = PersistentTemporaryFile('.opf') opf_file.write(raw) opf_file.close() return mi, opf_file def create_cover_file(db, book_id): cover = db.cover(book_id, index_is_id=True) cf = None if cover: cf = PersistentTemporaryFile('.jpeg') cf.write(cover) cf.close() return cf class MetadataWidget(Widget, Ui_Form): TITLE = _('Metadata') ICON = I('dialog_information.png') HELP = _('Set the metadata. The output file will contain as much of this ' 'metadata as possible.') COMMIT_NAME = 'metadata' def __init__(self, parent, get_option, get_help, db=None, book_id=None): Widget.__init__(self, parent, OPTIONS['pipe']['metadata']) self.db, self.book_id = db, book_id self.cover_changed = False self.cover_data = None if self.db is not None: self.initialize_metadata_options() self.initialize_options(get_option, get_help, db, book_id) self.cover_button.clicked.connect(self.select_cover) self.comment.hide_toolbars() self.cover.cover_changed.connect(self.change_cover) self.series.currentTextChanged.connect(self.series_changed) self.cover.draw_border = False def change_cover(self, data): self.cover_changed = True self.cover_data = data def deduce_author_sort(self, *args): au = str(self.author.currentText()) au = re.sub(r'\s+et al\.$', '', au) authors = string_to_authors(au) self.author_sort.setText(self.db.author_sort_from_authors(authors)) self.author_sort.home(False) def initialize_metadata_options(self): self.initialize_combos() self.author.editTextChanged.connect(self.deduce_author_sort) mi = self.db.get_metadata(self.book_id, index_is_id=True) self.title.setText(mi.title), self.title.home(False) self.publisher.show_initial_value(mi.publisher if mi.publisher else '') self.publisher.home(False) self.author_sort.setText(mi.author_sort if mi.author_sort else '') self.author_sort.home(False) self.tags.setText(', '.join(mi.tags if mi.tags else [])) self.tags.update_items_cache(self.db.new_api.all_field_names('tags')) self.tags.home(False) self.comment.html = comments_to_html(mi.comments) if mi.comments else '' self.series.show_initial_value(mi.series if mi.series else '') self.series.home(False) if mi.series_index is not None: try: self.series_index.setValue(mi.series_index) except: self.series_index.setValue(1.0) cover = self.db.cover(self.book_id, index_is_id=True) if cover: pm = QPixmap() pm.loadFromData(cover) if not pm.isNull(): pm.setDevicePixelRatio(getattr(self, 'devicePixelRatioF', self.devicePixelRatio)()) self.cover.setPixmap(pm) self.cover_data = cover self.set_cover_tooltip(pm) else: pm = QPixmap(I('default_cover.png')) pm.setDevicePixelRatio(getattr(self, 'devicePixelRatioF', self.devicePixelRatio)()) self.cover.setPixmap(pm) self.cover.setToolTip(_('This book has no cover')) for x in ('author', 'series', 'publisher'): x = getattr(self, x) x.lineEdit().deselect() self.series_changed() def series_changed(self): self.series_index.setEnabled(len(self.series.currentText().strip()) > 0) def set_cover_tooltip(self, pm): tt = _('Cover size: %(width)d x %(height)d pixels') % dict( width=pm.width(), height=pm.height()) self.cover.setToolTip(tt) def initialize_combos(self): self.initalize_authors() self.initialize_series() self.initialize_publisher() def initalize_authors(self): all_authors = self.db.all_authors() all_authors.sort(key=lambda x : sort_key(x[1])) self.author.set_separator('&') self.author.set_space_before_sep(True) self.author.set_add_separator(tweaks['authors_completer_append_separator']) self.author.update_items_cache(self.db.new_api.all_field_names('authors')) au = self.db.authors(self.book_id, True) if not au: au = _('Unknown') au = ' & '.join([a.strip().replace('|', ',') for a in au.split(',')]) self.author.show_initial_value(au) self.author.home(False) def initialize_series(self): self.series.set_separator(None) self.series.update_items_cache(self.db.new_api.all_field_names('series')) def initialize_publisher(self): self.publisher.set_separator(None) self.publisher.update_items_cache(self.db.new_api.all_field_names('publisher')) def get_title_and_authors(self): title = str(self.title.text()).strip() if not title: title = _('Unknown') authors = str(self.author.text()).strip() authors = string_to_authors(authors) if authors else [_('Unknown')] return title, authors def get_metadata(self): title, authors = self.get_title_and_authors() mi = MetaInformation(title, authors) publisher = str(self.publisher.text()).strip() if publisher: mi.publisher = publisher author_sort = str(self.author_sort.text()).strip() if author_sort: mi.author_sort = author_sort comments = self.comment.html if comments: mi.comments = comments mi.series_index = float(self.series_index.value()) series = str(self.series.currentText()).strip() if series: mi.series = series tags = [t.strip() for t in str(self.tags.text()).strip().split(',')] if tags: mi.tags = tags return mi def select_cover(self): files = choose_images(self, 'change cover dialog', _('Choose cover for ') + str(self.title.text())) if not files: return _file = files[0] if _file: _file = os.path.abspath(_file) if not os.access(_file, os.R_OK): d = error_dialog(self.parent(), _('Cannot read'), _('You do not have permission to read the file: ') + _file) d.exec() return cover = None try: with open(_file, "rb") as f: cover = f.read() except OSError as e: d = error_dialog(self.parent(), _('Error reading file'), _("<p>There was an error reading from file: <br /><b>") + _file + "</b></p><br />"+str(e)) d.exec() if cover: pix = QPixmap() pix.loadFromData(cover) pix.setDevicePixelRatio(getattr(self, 'devicePixelRatioF', self.devicePixelRatio)()) if pix.isNull(): d = error_dialog(self.parent(), _('Error reading file'), _file + _(" is not a valid picture")) d.exec() else: self.cover_path.setText(_file) self.set_cover_tooltip(pix) self.cover.setPixmap(pix) self.cover_changed = True self.cpixmap = pix self.cover_data = cover def get_recommendations(self): return { 'prefer_metadata_cover': bool(self.opt_prefer_metadata_cover.isChecked()), } def pre_commit_check(self): if self.db is None: return True db = self.db.new_api title, authors = self.get_title_and_authors() try: if title != db.field_for('title', self.book_id): db.set_field('title', {self.book_id:title}) langs = db.field_for('languages', self.book_id) if langs: db.set_field('sort', {self.book_id:title_sort(title, langs[0])}) if list(authors) != list(db.field_for('authors', self.book_id)): db.set_field('authors', {self.book_id:authors}) if self.cover_changed and self.cover_data is not None: self.db.set_cover(self.book_id, self.cover_data) except OSError as err: if getattr(err, 'errno', None) == errno.EACCES: # Permission denied import traceback fname = getattr(err, 'filename', None) or 'file' error_dialog(self, _('Permission denied'), _('Could not open %s. Is it being used by another' ' program?')%fname, det_msg=traceback.format_exc(), show=True) return False publisher = self.publisher.text().strip() if publisher != db.field_for('publisher', self.book_id): db.set_field('publisher', {self.book_id:publisher}) author_sort = self.author_sort.text().strip() if author_sort != db.field_for('author_sort', self.book_id): db.set_field('author_sort', {self.book_id:author_sort}) tags = [t.strip() for t in self.tags.text().strip().split(',')] if tags != list(db.field_for('tags', self.book_id)): db.set_field('tags', {self.book_id:tags}) series_index = float(self.series_index.value()) series = self.series.currentText().strip() if series != db.field_for('series', self.book_id): db.set_field('series', {self.book_id:series}) if series and series_index != db.field_for('series_index', self.book_id): db.set_field('series_index', {self.book_id:series_index}) return True def commit(self, save_defaults=False): ''' Settings are stored in two attributes: `opf_file` and `cover_file`. Both may be None. Also returns a recommendation dictionary. ''' recs = self.commit_options(save_defaults) self.user_mi = self.get_metadata() self.cover_file = self.opf_file = None if self.db is not None: self.mi, self.opf_file = create_opf_file(self.db, self.book_id) cover = self.db.cover(self.book_id, index_is_id=True) if cover: cf = PersistentTemporaryFile('.jpeg') cf.write(cover) cf.close() self.cover_file = cf return recs