Пример #1
0
    def process_duplicates(self, db, duplicates):
        ta = _('%(title)s by %(author)s')
        bf = QFont(self.dup_list.font())
        bf.setBold(True)
        itf = QFont(self.dup_list.font())
        itf.setItalic(True)

        for mi, cover, formats in duplicates:
            item = QTreeWidgetItem([ta%dict(
                title=mi.title, author=mi.format_field('authors')[1])] , 0)
            item.setCheckState(0, Qt.Checked)
            item.setFlags(Qt.ItemIsEnabled|Qt.ItemIsUserCheckable)
            item.setData(0, Qt.FontRole, bf)
            item.setData(0, Qt.UserRole, (mi, cover, formats))
            matching_books = db.books_with_same_title(mi)

            def add_child(text):
                c = QTreeWidgetItem([text], 1)
                c.setFlags(Qt.ItemIsEnabled)
                item.addChild(c)
                return c

            add_child(_('Already in calibre:')).setData(0, Qt.FontRole, itf)

            for book_id in matching_books:
                aut = [a.replace('|', ',') for a in (db.authors(book_id,
                    index_is_id=True) or '').split(',')]
                add_child(ta%dict(
                    title=db.title(book_id, index_is_id=True),
                    author=authors_to_string(aut)))
            add_child('')

            yield item
Пример #2
0
def create_book(mi, path, fmt='epub', opf_name='metadata.opf', html_name='start.xhtml', toc_name='toc.ncx'):
    ''' Create an empty book in the specified format at the specified location. '''
    path = os.path.abspath(path)
    lang = 'und'
    opf = metadata_to_opf(mi, as_string=False)
    for l in opf.xpath('//*[local-name()="language"]'):
        if l.text:
            lang = l.text
            break
    lang = lang_as_iso639_1(lang) or lang

    opfns = OPF_NAMESPACES['opf']
    m = opf.makeelement('{%s}manifest' % opfns)
    opf.insert(1, m)
    i = m.makeelement('{%s}item' % opfns, href=html_name, id='start')
    i.set('media-type', guess_type('a.xhtml'))
    m.append(i)
    i = m.makeelement('{%s}item' % opfns, href=toc_name, id='ncx')
    i.set('media-type', guess_type(toc_name))
    m.append(i)
    s = opf.makeelement('{%s}spine' % opfns, toc="ncx")
    opf.insert(2, s)
    i = s.makeelement('{%s}itemref' % opfns, idref='start')
    s.append(i)
    CONTAINER = '''\
<?xml version="1.0"?>
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
   <rootfiles>
      <rootfile full-path="{0}" media-type="application/oebps-package+xml"/>
   </rootfiles>
</container>
    '''.format(prepare_string_for_xml(opf_name, True)).encode('utf-8')
    HTML = P('templates/new_book.html', data=True).decode('utf-8').replace(
        '_LANGUAGE_', prepare_string_for_xml(lang, True)
    ).replace(
        '_TITLE_', prepare_string_for_xml(mi.title)
    ).replace(
        '_AUTHORS_', prepare_string_for_xml(authors_to_string(mi.authors))
    ).encode('utf-8')
    h = parse(HTML)
    pretty_html_tree(None, h)
    HTML = serialize(h, 'text/html')
    ncx = etree.tostring(create_toc(mi, opf, html_name, lang), encoding='utf-8', xml_declaration=True, pretty_print=True)
    pretty_xml_tree(opf)
    opf = etree.tostring(opf, encoding='utf-8', xml_declaration=True, pretty_print=True)
    if fmt == 'azw3':
        with TemporaryDirectory('create-azw3') as tdir, CurrentDir(tdir):
            for name, data in ((opf_name, opf), (html_name, HTML), (toc_name, ncx)):
                with open(name, 'wb') as f:
                    f.write(data)
            c = Container(os.path.dirname(os.path.abspath(opf_name)), opf_name, DevNull())
            opf_to_azw3(opf_name, path, c)
    else:
        with ZipFile(path, 'w', compression=ZIP_STORED) as zf:
            zf.writestr('mimetype', b'application/epub+zip', compression=ZIP_STORED)
            zf.writestr('META-INF/', b'', 0755)
            zf.writestr('META-INF/container.xml', CONTAINER)
            zf.writestr(opf_name, opf)
            zf.writestr(html_name, HTML)
            zf.writestr(toc_name, ncx)
Пример #3
0
def stringify(data, metadata, for_machine):
    for field, m in iteritems(metadata):
        if field == 'authors':
            data[field] = {
                k: authors_to_string(v)
                for k, v in iteritems(data[field])
            }
        else:
            dt = m['datatype']
            if dt == 'datetime':
                data[field] = {
                    k: isoformat(v, as_utc=for_machine) if v else 'None'
                    for k, v in iteritems(data[field])
                }
            elif not for_machine:
                ism = m['is_multiple']
                if ism:
                    data[field] = {
                        k: ism['list_to_ui'].join(v)
                        for k, v in iteritems(data[field])
                    }
                    if field == 'formats':
                        data[field] = {
                            k: '[' + v + ']'
                            for k, v in iteritems(data[field])
                        }
Пример #4
0
    def _metadata(self, metadata):
        '''
        Metadata takes the form:
        title\x00
        author\x00
        copyright\x00
        publisher\x00
        isbn\x00
        '''

        title = _('Unknown')
        author = _('Unknown')
        copyright = ''
        publisher = ''
        isbn = ''

        if metadata:
            if len(metadata.title) >= 1:
                title = metadata.title[0].value
            if len(metadata.creator) >= 1:
                from calibre.ebooks.metadata import authors_to_string
                author = authors_to_string([x.value for x in metadata.creator])
            if len(metadata.rights) >= 1:
                copyright = metadata.rights[0].value
            if len(metadata.publisher) >= 1:
                publisher = metadata.publisher[0].value

        return '%s\x00%s\x00%s\x00%s\x00%s\x00' % (title, author, copyright, publisher, isbn)
Пример #5
0
    def format_report(self):
        report = []
        a = report.append

        def indent(text):
            text = force_unicode(text)
            return '\xa0\xa0\xa0\xa0' + '\n\xa0\xa0\xa0\xa0'.join(text.splitlines())

        for book_id, errors in iteritems(self.errors):
            types = {t for t, data in errors}
            title, authors = self.book_id_data(book_id).title, authors_to_string(self.book_id_data(book_id).authors[:1])
            if report:
                a('\n' + ('_'*70) + '\n')
            if 'critical' in types:
                a(_('Failed to save: {0} by {1} to disk, with error:').format(title, authors))
                for t, tb in errors:
                    if t == 'critical':
                        a(indent(tb))
            else:
                errs = defaultdict(list)
                for t, data in errors:
                    errs[t].append(data)
                for fmt, tb in errs['fmt']:
                    a(_('Failed to save the {2} format of: {0} by {1} to disk, with error:').format(title, authors, fmt.upper()))
                    a(indent(tb)), a('')
                for fmt, tb in errs['metadata']:
                    if fmt:
                        a(_('Failed to update the metadata in the {2} format of: {0} by {1}, with error:').format(title, authors, fmt.upper()))
                    else:
                        a(_('Failed to update the metadata in all formats of: {0} by {1}, with error:').format(title, authors))
                    a(indent(tb)), a('')
        return '\n'.join(report)
Пример #6
0
def set_metadata_(path, opath, title, authors, bkp, tags):
    p = podofo.PDFDoc()
    p.open(path)
    title = prep(title)
    touched = False
    if title and title != p.title:
        p.title = title
        touched = True

    author = prep(authors_to_string(authors))
    if author and author != p.author:
        p.author = author
        touched = True

    bkp = prep(bkp)
    if bkp and bkp != p.creator:
        p.creator = bkp
        touched = True

    try:
        tags = prep(u', '.join([x.strip() for x in tags if x.strip()]))
        if tags != p.keywords:
            p.keywords = tags
            touched = True
    except:
        pass

    if touched:
        p.save(opath)
        return True
    return False
Пример #7
0
def read_metadata(root):
    ans = Metadata(_('Unknown'), [_('Unknown')])
    prefixes, refines = read_prefixes(root), read_refines(root)
    identifiers = read_identifiers(root, prefixes, refines)
    ids = {}
    for key, vals in identifiers.iteritems():
        if key == 'calibre':
            ans.application_id = vals[0]
        elif key != 'uuid':
            ids[key] = vals[0]
    ans.set_identifiers(ids)
    ans.title = read_title(root, prefixes, refines) or ans.title
    ans.title_sort = read_title_sort(root, prefixes, refines) or ans.title_sort
    ans.languages = read_languages(root, prefixes, refines) or ans.languages
    auts, aus = [], []
    for a in read_authors(root, prefixes, refines):
        auts.append(a.name), aus.append(a.sort)
    ans.authors = auts or ans.authors
    ans.author_sort = authors_to_string(aus) or ans.author_sort
    bkp = read_book_producers(root, prefixes, refines)
    if bkp:
        ans.book_producer = bkp[0]
    pd = read_pubdate(root, prefixes, refines)
    if not is_date_undefined(pd):
        ans.pubdate = pd
    ts = read_timestamp(root, prefixes, refines)
    if not is_date_undefined(ts):
        ans.timestamp = ts
    lm = read_last_modified(root, prefixes, refines)
    if not is_date_undefined(lm):
        ans.last_modified = lm
    return ans
Пример #8
0
def set_metadata_(tdir, title, authors, bkp, tags):
    podofo = get_podofo()
    os.chdir(tdir)
    p = podofo.PDFDoc()
    p.open(u'input.pdf')
    title = prep(title)
    touched = False
    if title and title != p.title:
        p.title = title
        touched = True

    author = prep(authors_to_string(authors))
    if author and author != p.author:
        p.author = author
        touched = True

    bkp = prep(bkp)
    if bkp and bkp != p.creator:
        p.creator = bkp
        touched = True

    try:
        tags = prep(u', '.join([x.strip() for x in tags if x.strip()]))
        if tags != p.keywords:
            p.keywords = tags
            touched = True
    except:
        pass

    if touched:
        p.save(u'output.pdf')

    return touched
Пример #9
0
    def default_cover(self):
        '''
        Create a generic cover for books that dont have a cover
        '''
        from calibre.ebooks.metadata import authors_to_string, fmt_sidx
        if self.no_default_cover:
            return None
        self.log('Generating default cover')
        m = self.oeb.metadata
        title = unicode(m.title[0])
        authors = [unicode(x) for x in m.creator if x.role == 'aut']
        series_string = None
        if m.series and m.series_index:
            series_string = _('Book %(sidx)s of %(series)s')%dict(
                    sidx=fmt_sidx(m.series_index[0], use_roman=True),
                    series=unicode(m.series[0]))

        try:
            from calibre.ebooks import calibre_cover
            img_data = calibre_cover(title, authors_to_string(authors),
                    series_string=series_string)
            id, href = self.oeb.manifest.generate('cover',
                    u'cover_image.jpg')
            item = self.oeb.manifest.add(id, href, guess_type('t.jpg')[0],
                        data=img_data)
            m.clear('cover')
            m.add('cover', item.id)

            return item.href
        except:
            self.log.exception('Failed to generate default cover')
        return None
Пример #10
0
 def to_html(self):
     '''
     A HTML representation of this object.
     '''
     from calibre.ebooks.metadata import authors_to_string
     from calibre.utils.date import isoformat
     ans = [(_('Title'), unicode(self.title))]
     ans += [(_('Author(s)'), (authors_to_string(self.authors) if self.authors else _('Unknown')))]
     ans += [(_('Publisher'), unicode(self.publisher))]
     ans += [(_('Producer'), unicode(self.book_producer))]
     ans += [(_('Comments'), unicode(self.comments))]
     ans += [('ISBN', unicode(self.isbn))]
     ans += [(_('Tags'), u', '.join([unicode(t) for t in self.tags]))]
     if self.series:
         ans += [(_('Series'), unicode(self.series) + ' #%s'%self.format_series_index())]
     ans += [(_('Languages'), u', '.join(self.languages))]
     if self.timestamp is not None:
         ans += [(_('Timestamp'), unicode(isoformat(self.timestamp, as_utc=False, sep=' ')))]
     if self.pubdate is not None:
         ans += [(_('Published'), unicode(isoformat(self.pubdate, as_utc=False, sep=' ')))]
     if self.rights is not None:
         ans += [(_('Rights'), unicode(self.rights))]
     for key in self.custom_field_keys():
         val = self.get(key, None)
         if val:
             (name, val) = self.format_field(key)
             ans += [(name, val)]
     for i, x in enumerate(ans):
         ans[i] = u'<tr><td><b>%s</b></td><td>%s</td></tr>'%x
     return u'<table>%s</table>'%u'\n'.join(ans)
Пример #11
0
 def make_rdata(book_id=1, new_book_id=None, action='add'):
     return {
             'title': src_db.field_for('title', book_id),
             'authors': list(src_db.field_for('authors', book_id)),
             'author': authors_to_string(src_db.field_for('authors', book_id)),
             'book_id': book_id, 'new_book_id': new_book_id, 'action': action
     }
Пример #12
0
    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)
        changed_books = len(self.applied_ids or ())
        self.refresh_gui(self.applied_ids)

        self.apply_id_map = []
        self.apply_pd = None
        try:
            if callable(self.apply_callback):
                self.apply_callback(list(self.applied_ids))
        finally:
            self.apply_callback = None
        if changed_books:
            QApplication.alert(self.gui, 2000)
Пример #13
0
    def show_details(self, index):
        f = rating_font()
        book = self.model().data(index, Qt.UserRole)
        parts = [
            '<center>',
            '<h2>%s</h2>'%book.title,
            '<div><i>%s</i></div>'%authors_to_string(book.authors),
        ]
        if not book.is_null('series'):
            series = book.format_field('series')
            if series[1]:
                parts.append('<div>%s: %s</div>'%series)
        if not book.is_null('rating'):
            style = 'style=\'font-family:"%s"\''%f
            parts.append('<div %s>%s</div>'%(style, '\u2605'*int(book.rating)))
        parts.append('</center>')
        if book.identifiers:
            urls = urls_from_identifiers(book.identifiers)
            ids = ['<a href="%s">%s</a>'%(url, name) for name, ign, ign, url in urls]
            if ids:
                parts.append('<div><b>%s:</b> %s</div><br>'%(_('See at'), ', '.join(ids)))
        if book.tags:
            parts.append('<div>%s</div><div>\u00a0</div>'%', '.join(book.tags))
        if book.comments:
            parts.append(comments_to_html(book.comments))

        self.show_details_signal.emit(''.join(parts))
Пример #14
0
def ACQUISITION_ENTRY(book_id, updated, request_context):
    field_metadata = request_context.db.field_metadata
    mi = request_context.db.get_metadata(book_id)
    extra = []
    if mi.rating > 0:
        rating = rating_to_stars(mi.rating)
        extra.append(_('RATING: %s<br />')%rating)
    if mi.tags:
        extra.append(_('TAGS: %s<br />')%xml(format_tag_string(mi.tags, None)))
    if mi.series:
        extra.append(_('SERIES: %(series)s [%(sidx)s]<br />')%
                dict(series=xml(mi.series),
                sidx=fmt_sidx(float(mi.series_index))))
    for key in filter(request_context.ctx.is_field_displayable, field_metadata.ignorable_field_keys()):
        name, val = mi.format_field(key)
        if val:
            fm = field_metadata[key]
            datatype = fm['datatype']
            if datatype == 'text' and fm['is_multiple']:
                extra.append('%s: %s<br />'%
                             (xml(name),
                              xml(format_tag_string(val,
                                    fm['is_multiple']['ui_to_list'],
                                    joinval=fm['is_multiple']['list_to_ui']))))
            elif datatype == 'comments' or (fm['datatype'] == 'composite' and
                            fm['display'].get('contains_html', False)):
                extra.append('%s: %s<br />'%(xml(name), comments_to_html(unicode(val))))
            else:
                extra.append('%s: %s<br />'%(xml(name), xml(unicode(val))))
    if mi.comments:
        comments = comments_to_html(mi.comments)
        extra.append(comments)
    if extra:
        extra = html_to_lxml('\n'.join(extra))
    ans = E.entry(TITLE(mi.title), E.author(E.name(authors_to_string(mi.authors))), ID('urn:uuid:' + mi.uuid), UPDATED(mi.last_modified),
                  E.published(mi.timestamp.isoformat()))
    if mi.pubdate and not is_date_undefined(mi.pubdate):
        ans.append(ans.makeelement('{%s}date' % DC_NS))
        ans[-1].text = mi.pubdate.isoformat()
    if len(extra):
        ans.append(E.content(extra, type='xhtml'))
    get = partial(request_context.ctx.url_for, '/get', book_id=book_id, library_id=request_context.library_id)
    if mi.formats:
        fm = mi.format_metadata
        for fmt in mi.formats:
            fmt = fmt.lower()
            mt = guess_type('a.'+fmt)[0]
            if mt:
                link = E.link(type=mt, href=get(what=fmt), rel="http://opds-spec.org/acquisition")
                ffm = fm.get(fmt.upper())
                if ffm:
                    link.set('length', str(ffm['size']))
                    link.set('mtime', ffm['mtime'].isoformat())
                ans.append(link)
    ans.append(E.link(type='image/jpeg', href=get(what='cover'), rel="http://opds-spec.org/cover"))
    ans.append(E.link(type='image/jpeg', href=get(what='thumb'), rel="http://opds-spec.org/thumbnail"))

    return ans
Пример #15
0
def ACQUISITION_ENTRY(book_id, updated, request_context):
    field_metadata = request_context.db.field_metadata
    mi = request_context.db.get_metadata(book_id)
    extra = []
    if mi.rating > 0:
        rating = u"".join(repeat(u"\u2605", int(mi.rating / 2.0)))
        extra.append(_("RATING: %s<br />") % rating)
    if mi.tags:
        extra.append(_("TAGS: %s<br />") % xml(format_tag_string(mi.tags, None)))
    if mi.series:
        extra.append(
            _("SERIES: %(series)s [%(sidx)s]<br />")
            % dict(series=xml(mi.series), sidx=fmt_sidx(float(mi.series_index)))
        )
    for key in filter(request_context.ctx.is_field_displayable, field_metadata.ignorable_field_keys()):
        name, val = mi.format_field(key)
        if val:
            fm = field_metadata[key]
            datatype = fm["datatype"]
            if datatype == "text" and fm["is_multiple"]:
                extra.append(
                    "%s: %s<br />"
                    % (
                        xml(name),
                        xml(
                            format_tag_string(
                                val, fm["is_multiple"]["ui_to_list"], joinval=fm["is_multiple"]["list_to_ui"]
                            )
                        ),
                    )
                )
            elif datatype == "comments" or (
                fm["datatype"] == "composite" and fm["display"].get("contains_html", False)
            ):
                extra.append("%s: %s<br />" % (xml(name), comments_to_html(unicode(val))))
            else:
                extra.append("%s: %s<br />" % (xml(name), xml(unicode(val))))
    if mi.comments:
        comments = comments_to_html(mi.comments)
        extra.append(comments)
    if extra:
        extra = html_to_lxml("\n".join(extra))
    ans = E.entry(
        TITLE(mi.title), E.author(E.name(authors_to_string(mi.authors))), ID("urn:uuid:" + mi.uuid), UPDATED(updated)
    )
    if len(extra):
        ans.append(E.content(extra, type="xhtml"))
    get = partial(request_context.ctx.url_for, "/get", book_id=book_id, library_id=request_context.library_id)
    if mi.formats:
        for fmt in mi.formats:
            fmt = fmt.lower()
            mt = guess_type("a." + fmt)[0]
            if mt:
                ans.append(E.link(type=mt, href=get(what=fmt), rel="http://opds-spec.org/acquisition"))
    ans.append(E.link(type="image/jpeg", href=get(what="cover"), rel="http://opds-spec.org/cover"))
    ans.append(E.link(type="image/jpeg", href=get(what="thumb"), rel="http://opds-spec.org/thumbnail"))

    return ans
Пример #16
0
def book_filename(rd, book_id, mi, fmt):
    au = authors_to_string(mi.authors or [_('Unknown')])
    title = mi.title or _('Unknown')
    ext = (fmt or '').lower()
    if ext == 'kepub' and 'Kobo Touch' in rd.inheaders.get('User-Agent', ''):
        ext = 'kepub.epub'
    fname = '%s - %s_%s.%s' % (title[:30], au[:30], book_id, ext)
    fname = ascii_filename(fname).replace('"', '_')
    return fname
Пример #17
0
def search_kobo(query, max_results=10, timeout=60, write_html_to=None):
    from css_selectors import Select
    url = 'http://www.kobobooks.com/search/search.html?q=' + urllib.quote_plus(query)

    br = browser()

    with closing(br.open(url, timeout=timeout)) as f:
        raw = f.read()
        if write_html_to is not None:
            with open(write_html_to, 'wb') as f:
                f.write(raw)
        doc = html.fromstring(raw)
        select = Select(doc)
        for i, item in enumerate(select('.result-items .item-wrapper.book')):
            if i == max_results:
                break
            for img in select('.item-image img[src]', item):
                cover_url = img.get('src')
                if cover_url.startswith('//'):
                    cover_url = 'http:' + cover_url
                break
            else:
                cover_url = None

            for p in select('p.title', item):
                title = etree.tostring(p, method='text', encoding=unicode).strip()
                for a in select('a[href]', p):
                    url = 'http://store.kobobooks.com' + a.get('href')
                    break
                else:
                    url = None
                break
            else:
                title = None

            authors = []
            for a in select('p.author a.contributor', item):
                authors.append(etree.tostring(a, method='text', encoding=unicode).strip())
            authors = authors_to_string(authors)

            for p in select('p.price', item):
                price = etree.tostring(p, method='text', encoding=unicode).strip()
                break
            else:
                price = None

            if title and authors and url:
                s = SearchResult()
                s.cover_url = cover_url
                s.title = title
                s.author = authors
                s.price = price
                s.detail_item = url
                s.formats = 'EPUB'
                s.drm = SearchResult.DRM_UNKNOWN

            yield s
Пример #18
0
def mi_to_info(mi):
    ans = []
    if mi.title:
        ans.extend(('InfoKey: Title', 'InfoValue: '+mi.title))
    if mi.authors:
        from calibre.ebooks.metadata import authors_to_string
        ans.extend(('InfoKey: Author', 'InfoValue: ' +
            authors_to_string(mi.authors)))
    return u'\n'.join(ans)
Пример #19
0
    def __init__(self, oeb_metadata=None):
        self.title = _('Unknown')
        self.author = _('Unknown')

        if oeb_metadata != None:
            if len(oeb_metadata.title) >= 1:
                self.title = oeb_metadata.title[0].value
            if len(oeb_metadata.creator) >= 1:
                self.author = authors_to_string([x.value for x in oeb_metadata.creator])
Пример #20
0
    def get_format(self, id, format):
        format = format.upper()
        fm = self.db.format_metadata(id, format, allow_cache=False)
        if not fm:
            raise cherrypy.HTTPError(404, 'book: %d does not have format: %s'%(id, format))
        update_metadata = format in {'MOBI', 'EPUB', 'AZW3'}
        mi = newmi = self.db.get_metadata(
            id, index_is_id=True, cover_as_data=True, get_cover=update_metadata)

        cherrypy.response.headers['Last-Modified'] = \
            self.last_modified(max(fm['mtime'], mi.last_modified))

        fmt = self.db.format(id, format, index_is_id=True, as_file=True,
                mode='rb')
        if fmt is None:
            raise cherrypy.HTTPError(404, 'book: %d does not have format: %s'%(id, format))
        mt = guess_type('dummy.'+format.lower())[0]
        if mt is None:
            mt = 'application/octet-stream'
        cherrypy.response.headers['Content-Type'] = mt

        if format.lower() in plugboard_content_server_formats:
            # Get any plugboards for the content server
            plugboards = self.db.prefs.get('plugboards', {})
            cpb = find_plugboard(plugboard_content_server_value,
                                 format.lower(), plugboards)
            if cpb:
                # Transform the metadata via the plugboard
                newmi = mi.deepcopy_metadata()
                newmi.template_to_attribute(mi, cpb)

        if update_metadata:
            # Write the updated file
            from calibre.ebooks.metadata.meta import set_metadata
            set_metadata(fmt, newmi, format.lower())
            fmt.seek(0)

        fmt.seek(0, 2)
        cherrypy.response.headers['Content-Length'] = fmt.tell()
        fmt.seek(0)

        ua = cherrypy.request.headers.get('User-Agent', '').strip()
        have_kobo_browser = self.is_kobo_browser(ua)
        file_extension = "kepub.epub" if have_kobo_browser and format.lower() == "kepub" else format

        au = authors_to_string(newmi.authors if newmi.authors else
                [_('Unknown')])
        title = newmi.title if newmi.title else _('Unknown')
        fname = u'%s - %s_%s.%s'%(title[:30], au[:30], id, file_extension.lower())
        fname = ascii_filename(fname).replace('"', '_')
        cherrypy.response.headers['Content-Disposition'] = \
                b'attachment; filename="%s"'%fname
        cherrypy.response.body = fmt
        cherrypy.response.timeout = 3600
        return fmt
Пример #21
0
 def data_as_text(self, book, col):
     if col == 0:
         return unicode(book.gui_rank + 1)
     if col == 1:
         t = book.title if book.title else _("Unknown")
         a = authors_to_string(book.authors) if book.authors else ""
         return "<b>%s</b><br><i>%s</i>" % (t, a)
     if col == 2:
         d = format_date(book.pubdate, "yyyy") if book.pubdate else _("Unknown")
         p = book.publisher if book.publisher else ""
         return "<b>%s</b><br><i>%s</i>" % (d, p)
Пример #22
0
 def data_as_text(self, book, col):
     if col == 0:
         return unicode(book.gui_rank+1)
     if col == 1:
         t = book.title if book.title else _('Unknown')
         a = authors_to_string(book.authors) if book.authors else ''
         return '<b>%s</b><br><i>%s</i>' % (t, a)
     if col == 2:
         d = format_date(book.pubdate, 'yyyy') if book.pubdate else _('Unknown')
         p = book.publisher if book.publisher else ''
         return '<b>%s</b><br><i>%s</i>' % (d, p)
Пример #23
0
def get_title_authors_text(db, book_id):

    def authors_to_list(db, book_id):
        authors = db.authors(book_id, index_is_id=True)
        if authors:
            return [a.strip().replace('|',',') for a in authors.split(',')]
        return []

    title = db.title(book_id, index_is_id=True)
    authors = authors_to_list(db, book_id)
    from calibre.ebooks.metadata import authors_to_string
    return '%s / %s'%(title, authors_to_string(authors))
Пример #24
0
 def header(self):
     header = u'{\\rtf1{\\info{\\title %s}{\\author %s}}\\ansi\\ansicpg1252\\deff0\\deflang1033\n' % (
         self.oeb_book.metadata.title[0].value, authors_to_string([x.value for x in self.oeb_book.metadata.creator]))
     return header + (
         '{\\fonttbl{\\f0\\froman\\fprq2\\fcharset128 Times New Roman;}{\\f1\\froman\\fprq2\\fcharset128 Times New Roman;}{\\f2\\fswiss\\fprq2\\fcharset128 Arial;}{\\f3\\fnil\\fprq2\\fcharset128 Arial;}{\\f4\\fnil\\fprq2\\fcharset128 MS Mincho;}{\\f5\\fnil\\fprq2\\fcharset128 Tahoma;}{\\f6\\fnil\\fprq0\\fcharset128 Tahoma;}}\n'  # noqa
         '{\\stylesheet{\\ql \\li0\\ri0\\nowidctlpar\\wrapdefault\\faauto\\rin0\\lin0\\itap0 \\rtlch\\fcs1 \\af25\\afs24\\alang1033 \\ltrch\\fcs0 \\fs24\\lang1033\\langfe255\\cgrid\\langnp1033\\langfenp255 \\snext0 Normal;}\n'  # noqa
         '{\\s1\\ql \\li0\\ri0\\sb240\\sa120\\keepn\\nowidctlpar\\wrapdefault\\faauto\\outlinelevel0\\rin0\\lin0\\itap0 \\rtlch\\fcs1 \\ab\\af0\\afs32\\alang1033 \\ltrch\\fcs0 \\b\\fs32\\lang1033\\langfe255\\loch\\f1\\hich\\af1\\dbch\\af26\\cgrid\\langnp1033\\langfenp255 \\sbasedon15 \\snext16 \\slink21 heading 1;}\n'  # noqa
         '{\\s2\\ql \\li0\\ri0\\sb240\\sa120\\keepn\\nowidctlpar\\wrapdefault\\faauto\\outlinelevel1\\rin0\\lin0\\itap0 \\rtlch\\fcs1 \\ab\\ai\\af0\\afs28\\alang1033 \\ltrch\\fcs0 \\b\\i\\fs28\\lang1033\\langfe255\\loch\\f1\\hich\\af1\\dbch\\af26\\cgrid\\langnp1033\\langfenp255 \\sbasedon15 \\snext16 \\slink22 heading 2;}\n'  # noqa
         '{\\s3\\ql \\li0\\ri0\\sb240\\sa120\\keepn\\nowidctlpar\\wrapdefault\\faauto\\outlinelevel2\\rin0\\lin0\\itap0 \\rtlch\\fcs1 \\ab\\af0\\afs28\\alang1033 \\ltrch\\fcs0 \\b\\fs28\\lang1033\\langfe255\\loch\\f1\\hich\\af1\\dbch\\af26\\cgrid\\langnp1033\\langfenp255 \\sbasedon15 \\snext16 \\slink23 heading 3;}\n'  # noqa
         '{\\s4\\ql \\li0\\ri0\\sb240\\sa120\\keepn\\nowidctlpar\\wrapdefault\\faauto\\outlinelevel3\\rin0\\lin0\\itap0 \\rtlch\\fcs1 \\ab\\ai\\af0\\afs23\\alang1033 \\ltrch\\fcs0\\b\\i\\fs23\\lang1033\\langfe255\\loch\\f1\\hich\\af1\\dbch\\af26\\cgrid\\langnp1033\\langfenp255 \\sbasedon15 \\snext16 \\slink24 heading 4;}\n'  # noqa
         '{\\s5\\ql \\li0\\ri0\\sb240\\sa120\\keepn\\nowidctlpar\\wrapdefault\\faauto\\outlinelevel4\\rin0\\lin0\\itap0 \\rtlch\\fcs1 \\ab\\af0\\afs23\\alang1033 \\ltrch\\fcs0 \\b\\fs23\\lang1033\\langfe255\\loch\\f1\\hich\\af1\\dbch\\af26\\cgrid\\langnp1033\\langfenp255 \\sbasedon15 \\snext16 \\slink25 heading 5;}\n'  # noqa
         '{\\s6\\ql \\li0\\ri0\\sb240\\sa120\\keepn\\nowidctlpar\\wrapdefault\\faauto\\outlinelevel5\\rin0\\lin0\\itap0 \\rtlch\\fcs1 \\ab\\af0\\afs21\\alang1033 \\ltrch\\fcs0 \\b\\fs21\\lang1033\\langfe255\\loch\\f1\\hich\\af1\\dbch\\af26\\cgrid\\langnp1033\\langfenp255 \\sbasedon15 \\snext16 \\slink26 heading 6;}}\n'  # noqa
     )
Пример #25
0
    def start(self, title=None, authors=None, identifiers={}):
        self.log.clear()
        self.log("Starting download")
        parts, simple_desc = [], ""
        if title:
            parts.append("title:" + title)
            simple_desc += _("Title: %s ") % title
        if authors:
            parts.append("authors:" + authors_to_string(authors))
            simple_desc += _("Authors: %s ") % authors_to_string(authors)
        if identifiers:
            x = ", ".join("%s:%s" % (k, v) for k, v in identifiers.iteritems())
            parts.append(x)
            if "isbn" in identifiers:
                simple_desc += " ISBN: %s" % identifiers["isbn"]
        self.query.setText(simple_desc)
        self.log(unicode(self.query.text()))

        self.worker = IdentifyWorker(self.log, self.abort, title, authors, identifiers, self.caches)

        self.worker.start()

        QTimer.singleShot(50, self.update)
Пример #26
0
def book_filename(rd, book_id, mi, fmt, as_encoded_unicode=False):
    au = authors_to_string(mi.authors or [_('Unknown')])
    title = mi.title or _('Unknown')
    ext = (fmt or '').lower()
    if ext == 'kepub' and 'Kobo Touch' in rd.inheaders.get('User-Agent', ''):
        ext = 'kepub.epub'
    fname = '%s - %s_%s.%s' % (title[:30], au[:30], book_id, ext)
    if as_encoded_unicode:
        # See https://tools.ietf.org/html/rfc6266
        fname = sanitize_file_name(fname).encode('utf-8')
        fname = unicode_type(quote(fname))
    else:
        fname = ascii_filename(fname).replace('"', '_')
    return fname
Пример #27
0
    def _info_section(self, metadata):
        text = 'TYPE=2\n'
        if metadata:
            if len(metadata.title) >= 1:
                text += 'TITLE=%s\n' % metadata.title[0].value
            if len(metadata.creator) >= 1:
                from calibre.ebooks.metadata import authors_to_string
                text += 'AUTHOR=%s\n' % authors_to_string([x.value for x in metadata.creator])
        text += 'GENERATOR=%s - %s\n' % (__appname__, __version__)
        text += 'PARSE=1\n'
        text += 'OUTPUT=1\n'
        text += 'BODY=index.html\n'

        return text
Пример #28
0
    def __unicode__representation__(self):
        '''
        A string representation of this object, suitable for printing to
        console
        '''
        from calibre.utils.date import isoformat
        from calibre.ebooks.metadata import authors_to_string
        ans = []

        def fmt(x, y):
            ans.append(u'%-20s: %s'%(unicode_type(x), unicode_type(y)))

        fmt('Title', self.title)
        if self.title_sort:
            fmt('Title sort', self.title_sort)
        if self.authors:
            fmt('Author(s)',  authors_to_string(self.authors) +
               ((' [' + self.author_sort + ']')
                if self.author_sort and self.author_sort != _('Unknown') else ''))
        if self.publisher:
            fmt('Publisher', self.publisher)
        if getattr(self, 'book_producer', False):
            fmt('Book Producer', self.book_producer)
        if self.tags:
            fmt('Tags', u', '.join([unicode_type(t) for t in self.tags]))
        if self.series:
            fmt('Series', self.series + ' #%s'%self.format_series_index())
        if not self.is_null('languages'):
            fmt('Languages', ', '.join(self.languages))
        if self.rating is not None:
            fmt('Rating', (u'%.2g'%(float(self.rating)/2.0)) if self.rating
                    else u'')
        if self.timestamp is not None:
            fmt('Timestamp', isoformat(self.timestamp))
        if self.pubdate is not None:
            fmt('Published', isoformat(self.pubdate))
        if self.rights is not None:
            fmt('Rights', unicode_type(self.rights))
        if self.identifiers:
            fmt('Identifiers', u', '.join(['%s:%s'%(k, v) for k, v in
                iteritems(self.identifiers)]))
        if self.comments:
            fmt('Comments', self.comments)

        for key in self.custom_field_keys():
            val = self.get(key, None)
            if val:
                (name, val) = self.format_field(key)
                fmt(name, unicode_type(val))
        return u'\n'.join(ans)
Пример #29
0
def ACQUISITION_ENTRY(book_id, updated, request_context):
    field_metadata = request_context.db.field_metadata
    mi = request_context.db.get_metadata(book_id)
    extra = []
    if mi.rating > 0:
        rating = u''.join(repeat(u'\u2605', int(mi.rating/2.)))
        extra.append(_('RATING: %s<br />')%rating)
    if mi.tags:
        extra.append(_('TAGS: %s<br />')%xml(format_tag_string(mi.tags, None, no_tag_count=True)))
    if mi.series:
        extra.append(_('SERIES: %(series)s [%(sidx)s]<br />')%
                dict(series=xml(mi.series),
                sidx=fmt_sidx(float(mi.series_index))))
    for key in field_metadata.ignorable_field_keys():
        name, val = mi.format_field(key)
        if val:
            fm = field_metadata[key]
            datatype = fm['datatype']
            if datatype == 'text' and fm['is_multiple']:
                extra.append('%s: %s<br />'%
                             (xml(name),
                              xml(format_tag_string(val,
                                    fm['is_multiple']['ui_to_list'],
                                    no_tag_count=True,
                                    joinval=fm['is_multiple']['list_to_ui']))))
            elif datatype == 'comments' or (fm['datatype'] == 'composite' and
                            fm['display'].get('contains_html', False)):
                extra.append('%s: %s<br />'%(xml(name), comments_to_html(unicode(val))))
            else:
                extra.append('%s: %s<br />'%(xml(name), xml(unicode(val))))
    if mi.comments:
        comments = comments_to_html(mi.comments)
        extra.append(comments)
    if extra:
        extra = html_to_lxml('\n'.join(extra))
    ans = E.entry(TITLE(mi.title), E.author(E.name(authors_to_string(mi.authors))), ID('urn:uuid:' + mi.uuid), UPDATED(updated))
    if len(extra):
        ans.append(E.content(extra, type='xhtml'))
    get = partial(request_context.ctx.url_for, '/get', book_id=book_id, library_id=request_context.library_id)
    if mi.formats:
        for fmt in mi.formats:
            fmt = fmt.lower()
            mt = guess_type('a.'+fmt)[0]
            if mt:
                ans.append(E.link(type=mt, href=get(what=fmt), rel="http://opds-spec.org/acquisition"))
    ans.append(E.link(type='image/jpeg', href=get(what='cover'), rel="http://opds-spec.org/cover"))
    ans.append(E.link(type='image/jpeg', href=get(what='thumb'), rel="http://opds-spec.org/thumbnail"))

    return ans
Пример #30
0
    def do_test(self):
        from calibre.ebooks.metadata import authors_to_string
        from calibre.ebooks.metadata.meta import metadata_from_filename
        fname = unicode_type(self.filename.text())
        ext = os.path.splitext(fname)[1][1:].lower()
        if ext not in BOOK_EXTENSIONS:
            return warning_dialog(self, _('Test file name invalid'),
                    _('The file name <b>%s</b> does not appear to end with a'
                        ' file extension. It must end with a file '
                        ' extension like .epub or .mobi')%fname, show=True)

        try:
            pat = self.pattern()
        except Exception as err:
            error_dialog(self, _('Invalid regular expression'),
                         _('Invalid regular expression: %s')%err).exec_()
            return
        mi = metadata_from_filename(fname, pat)
        if mi.title:
            self.title.setText(mi.title)
        else:
            self.title.setText(_('No match'))
        if mi.authors:
            self.authors.setText(authors_to_string(mi.authors))
        else:
            self.authors.setText(_('No match'))

        if mi.series:
            self.series.setText(mi.series)
        else:
            self.series.setText(_('No match'))

        if mi.series_index is not None:
            self.series_index.setText(str(mi.series_index))
        else:
            self.series_index.setText(_('No match'))

        if mi.publisher:
            self.publisher.setText(mi.publisher)
        else:
            self.publisher.setText(_('No match'))

        if mi.pubdate:
            self.pubdate.setText(strftime('%Y-%m-%d', mi.pubdate))
        else:
            self.pubdate.setText(_('No match'))

        self.isbn.setText(_('No match') if mi.isbn is None else str(mi.isbn))
        self.comments.setText(mi.comments if mi.comments else _('No match'))
Пример #31
0
    def start(self, title=None, authors=None, identifiers={}):
        self.log.clear()
        self.log('Starting download')
        parts, simple_desc = [], ''
        if title:
            parts.append('title:' + title)
            simple_desc += _('Title: %s ') % title
        if authors:
            parts.append('authors:' + authors_to_string(authors))
            simple_desc += _('Authors: %s ') % authors_to_string(authors)
        if identifiers:
            x = ', '.join('%s:%s' % (k, v) for k, v in iteritems(identifiers))
            parts.append(x)
            if 'isbn' in identifiers:
                simple_desc += 'ISBN: %s' % identifiers['isbn']
        self.query.setText(simple_desc)
        self.log(unicode_type(self.query.text()))

        self.worker = IdentifyWorker(self.log, self.abort, title, authors,
                                     identifiers, self.caches)

        self.worker.start()

        QTimer.singleShot(50, self.update)
Пример #32
0
 def header(self):
     header = '{\\rtf1{\\info{\\title %s}{\\author %s}}\\ansi\\ansicpg1252\\deff0\\deflang1033\n' % (
         self.oeb_book.metadata.title[0].value,
         authors_to_string(
             [x.value for x in self.oeb_book.metadata.creator]))
     return header + (
         '{\\fonttbl{\\f0\\froman\\fprq2\\fcharset128 Times New Roman;}{\\f1\\froman\\fprq2\\fcharset128 Times New Roman;}{\\f2\\fswiss\\fprq2\\fcharset128 Arial;}{\\f3\\fnil\\fprq2\\fcharset128 Arial;}{\\f4\\fnil\\fprq2\\fcharset128 MS Mincho;}{\\f5\\fnil\\fprq2\\fcharset128 Tahoma;}{\\f6\\fnil\\fprq0\\fcharset128 Tahoma;}}\n'  # noqa
         '{\\stylesheet{\\ql \\li0\\ri0\\nowidctlpar\\wrapdefault\\faauto\\rin0\\lin0\\itap0 \\rtlch\\fcs1 \\af25\\afs24\\alang1033 \\ltrch\\fcs0 \\fs24\\lang1033\\langfe255\\cgrid\\langnp1033\\langfenp255 \\snext0 Normal;}\n'  # noqa
         '{\\s1\\ql \\li0\\ri0\\sb240\\sa120\\keepn\\nowidctlpar\\wrapdefault\\faauto\\outlinelevel0\\rin0\\lin0\\itap0 \\rtlch\\fcs1 \\ab\\af0\\afs32\\alang1033 \\ltrch\\fcs0 \\b\\fs32\\lang1033\\langfe255\\loch\\f1\\hich\\af1\\dbch\\af26\\cgrid\\langnp1033\\langfenp255 \\sbasedon15 \\snext16 \\slink21 heading 1;}\n'  # noqa
         '{\\s2\\ql \\li0\\ri0\\sb240\\sa120\\keepn\\nowidctlpar\\wrapdefault\\faauto\\outlinelevel1\\rin0\\lin0\\itap0 \\rtlch\\fcs1 \\ab\\ai\\af0\\afs28\\alang1033 \\ltrch\\fcs0 \\b\\i\\fs28\\lang1033\\langfe255\\loch\\f1\\hich\\af1\\dbch\\af26\\cgrid\\langnp1033\\langfenp255 \\sbasedon15 \\snext16 \\slink22 heading 2;}\n'  # noqa
         '{\\s3\\ql \\li0\\ri0\\sb240\\sa120\\keepn\\nowidctlpar\\wrapdefault\\faauto\\outlinelevel2\\rin0\\lin0\\itap0 \\rtlch\\fcs1 \\ab\\af0\\afs28\\alang1033 \\ltrch\\fcs0 \\b\\fs28\\lang1033\\langfe255\\loch\\f1\\hich\\af1\\dbch\\af26\\cgrid\\langnp1033\\langfenp255 \\sbasedon15 \\snext16 \\slink23 heading 3;}\n'  # noqa
         '{\\s4\\ql \\li0\\ri0\\sb240\\sa120\\keepn\\nowidctlpar\\wrapdefault\\faauto\\outlinelevel3\\rin0\\lin0\\itap0 \\rtlch\\fcs1 \\ab\\ai\\af0\\afs23\\alang1033 \\ltrch\\fcs0\\b\\i\\fs23\\lang1033\\langfe255\\loch\\f1\\hich\\af1\\dbch\\af26\\cgrid\\langnp1033\\langfenp255 \\sbasedon15 \\snext16 \\slink24 heading 4;}\n'  # noqa
         '{\\s5\\ql \\li0\\ri0\\sb240\\sa120\\keepn\\nowidctlpar\\wrapdefault\\faauto\\outlinelevel4\\rin0\\lin0\\itap0 \\rtlch\\fcs1 \\ab\\af0\\afs23\\alang1033 \\ltrch\\fcs0 \\b\\fs23\\lang1033\\langfe255\\loch\\f1\\hich\\af1\\dbch\\af26\\cgrid\\langnp1033\\langfenp255 \\sbasedon15 \\snext16 \\slink25 heading 5;}\n'  # noqa
         '{\\s6\\ql \\li0\\ri0\\sb240\\sa120\\keepn\\nowidctlpar\\wrapdefault\\faauto\\outlinelevel5\\rin0\\lin0\\itap0 \\rtlch\\fcs1 \\ab\\af0\\afs21\\alang1033 \\ltrch\\fcs0 \\b\\fs21\\lang1033\\langfe255\\loch\\f1\\hich\\af1\\dbch\\af26\\cgrid\\langnp1033\\langfenp255 \\sbasedon15 \\snext16 \\slink26 heading 6;}}\n'  # noqa
     )
Пример #33
0
def book_filename(rd, book_id, mi, fmt, as_encoded_unicode=False):
    au = authors_to_string(mi.authors or [_('Unknown')])
    title = mi.title or _('Unknown')
    ext = (fmt or '').lower()
    fname = '%s - %s_%s.%s' % (title[:30], au[:30], book_id, ext)
    if as_encoded_unicode:
        # See https://tools.ietf.org/html/rfc6266
        fname = sanitize_file_name(fname).encode('utf-8')
        fname = unicode_type(quote(fname))
    else:
        fname = ascii_filename(fname).replace('"', '_')
    if ext == 'kepub' and 'Kobo Touch' in rd.inheaders.get('User-Agent', ''):
        fname = fname.replace('!', '_')
        fname += '.epub'
    return fname
Пример #34
0
    def _info_section(self, metadata):
        text = 'TYPE=2\n'
        if metadata:
            if len(metadata.title) >= 1:
                text += 'TITLE=%s\n' % metadata.title[0].value
            if len(metadata.creator) >= 1:
                from calibre.ebooks.metadata import authors_to_string
                text += 'AUTHOR=%s\n' % authors_to_string(
                    [x.value for x in metadata.creator])
        text += 'GENERATOR=%s - %s\n' % (__appname__, __version__)
        text += 'PARSE=1\n'
        text += 'OUTPUT=1\n'
        text += 'BODY=index.html\n'

        return text
Пример #35
0
def set_metadata(stream, mi):
    pheader = PdbHeaderReader(stream)

    # Only Dropbook produced 132 byte record0 files are supported
    if pheader.section_data(0) != 132:
        return

    sections = [
        pheader.section_data(x) for x in range(0, pheader.section_count())
    ]
    hr = HeaderRecord(sections[0])

    if hr.compression not in (2, 10):
        return

    # Create a metadata record for the file if one does not already exist
    if not hr.has_metadata:
        sections += [b'', b'MeTaInFo\x00']
        last_data = len(sections) - 1

        for i in range(0, 132, 2):
            val, = struct.unpack('>H', sections[0][i:i + 2])
            if val >= hr.last_data_offset:
                sections[0][i:i + 2] = struct.pack('>H', last_data)

        sections[0][24:26] = struct.pack('>H', 1)  # Set has metadata
        sections[0][44:46] = struct.pack('>H', last_data -
                                         1)  # Set location of metadata
        sections[0][52:54] = struct.pack(
            '>H', last_data)  # Ensure last data offset is updated

    # Merge the metadata into the file
    file_mi = get_metadata(stream, False)
    file_mi.smart_update(mi)
    sections[hr.metadata_offset] = ('{}\x00{}\x00{}\x00{}\x00{}\x00'.format(
        file_mi.title, authors_to_string(file_mi.authors), '',
        file_mi.publisher, file_mi.isbn)).encode('cp1252', 'replace')

    # Rebuild the PDB wrapper because the offsets have changed due to the
    # new metadata.
    pheader_builder = PdbHeaderBuilder(pheader.ident, pheader.title)
    stream.seek(0)
    stream.truncate(0)
    pheader_builder.build_header([len(x) for x in sections], stream)

    # Write the data back to the file
    for item in sections:
        stream.write(item)
Пример #36
0
def read_metadata(root, ver=None, return_extra_data=False):
    ans = Metadata(_('Unknown'), [_('Unknown')])
    prefixes, refines = read_prefixes(root), read_refines(root)
    identifiers = read_identifiers(root, prefixes, refines)
    ids = {}
    for key, vals in iteritems(identifiers):
        if key == 'calibre':
            ans.application_id = vals[0]
        elif key == 'uuid':
            ans.uuid = vals[0]
        else:
            ids[key] = vals[0]
    ans.set_identifiers(ids)
    ans.title = read_title(root, prefixes, refines) or ans.title
    ans.title_sort = read_title_sort(root, prefixes, refines) or ans.title_sort
    ans.languages = read_languages(root, prefixes, refines) or ans.languages
    auts, aus = [], []
    for a in read_authors(root, prefixes, refines):
        auts.append(a.name), aus.append(a.sort)
    ans.authors = auts or ans.authors
    ans.author_sort = authors_to_string(aus) or ans.author_sort
    bkp = read_book_producers(root, prefixes, refines)
    if bkp:
        if bkp[0]:
            ans.book_producer = bkp[0]
    pd = read_pubdate(root, prefixes, refines)
    if not is_date_undefined(pd):
        ans.pubdate = pd
    ts = read_timestamp(root, prefixes, refines)
    if not is_date_undefined(ts):
        ans.timestamp = ts
    lm = read_last_modified(root, prefixes, refines)
    if not is_date_undefined(lm):
        ans.last_modified = lm
    ans.comments = read_comments(root, prefixes, refines) or ans.comments
    ans.publisher = read_publisher(root, prefixes, refines) or ans.publisher
    ans.tags = read_tags(root, prefixes, refines) or ans.tags
    ans.rating = read_rating(root, prefixes, refines) or ans.rating
    s, si = read_series(root, prefixes, refines)
    if s:
        ans.series, ans.series_index = s, si
    ans.author_link_map = read_author_link_map(root, prefixes, refines) or ans.author_link_map
    ans.user_categories = read_user_categories(root, prefixes, refines) or ans.user_categories
    for name, fm in iteritems((read_user_metadata(root, prefixes, refines) or {})):
        ans.set_user_metadata(name, fm)
    if return_extra_data:
        ans = ans, ver, read_raster_cover(root, prefixes, refines), first_spine_item(root, prefixes, refines)
    return ans
Пример #37
0
def reverse(pdf_path, out_path, metadata=None):
    if metadata == None:
        title = _('Unknown')
        author = _('Unknown')
    else:
        title = metadata.title
        author = authors_to_string(metadata.authors)

    out_pdf = PdfFileWriter(title=title, author=author)

    pdf = PdfFileReader(open(os.path.abspath(pdf_path), 'rb'))
    for page in reversed(pdf.pages):
        out_pdf.addPage(page)

    with open(out_path, 'wb') as out_file:
        out_pdf.write(out_file)
Пример #38
0
def rotate(pdf_path, out_path, degrees, metadata=None):
    if metadata == None:
        title = _('Unknown')
        author = _('Unknown')
    else:
        title = metadata.title
        author = authors_to_string(metadata.authors)

    out_pdf = PdfFileWriter(title=title, author=author)

    pdf = PdfFileReader(open(os.path.abspath(pdf_path), 'rb'))
    for page in pdf.pages:
        out_pdf.addPage(page.rotateClockwise(int(degrees)))

    with open(out_path, 'wb') as out_file:
        out_pdf.write(out_file)
Пример #39
0
    def process_duplicates(self, db, duplicates):
        ta = _('%(title)s by %(author)s [%(formats)s]')
        bf = QFont(self.dup_list.font())
        bf.setBold(True)
        itf = QFont(self.dup_list.font())
        itf.setItalic(True)

        for mi, cover, formats in duplicates:
            # formats is a list of file paths
            # Grab just the extension and display to the user
            # Based only off the file name, no file type tests are done.
            incoming_formats = ', '.join(
                os.path.splitext(path)[-1].replace('.', '').upper()
                for path in formats)
            item = QTreeWidgetItem([
                ta % dict(title=mi.title,
                          author=mi.format_field('authors')[1],
                          formats=incoming_formats)
            ], 0)
            item.setCheckState(0, Qt.Checked)
            item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
            item.setData(0, Qt.FontRole, bf)
            item.setData(0, Qt.UserRole, (mi, cover, formats))
            matching_books = db.books_with_same_title(mi)

            def add_child(text):
                c = QTreeWidgetItem([text], 1)
                c.setFlags(Qt.ItemIsEnabled)
                item.addChild(c)
                return c

            add_child(_('Already in calibre:')).setData(0, Qt.FontRole, itf)

            for book_id in matching_books:
                aut = [
                    a.replace('|', ',') for a in (
                        db.authors(book_id, index_is_id=True) or '').split(',')
                ]
                add_child(
                    ta %
                    dict(title=db.title(book_id, index_is_id=True),
                         author=authors_to_string(aut),
                         formats=db.formats(
                             book_id, index_is_id=True, verify_formats=False)))
            add_child('')

            yield item
Пример #40
0
def search(query, max_results=10, timeout=60):
    url = 'http://www.baen.com/catalogsearch/result/?' + urlencode(
        {'q':query.lower(), 'dir':'desc', 'order':'relevance'})

    br = browser()

    counter = max_results
    with closing(br.open_novisit(url, timeout=timeout)) as f:
        raw = f.read()
        root = html.fromstring(raw)
        for data in root.xpath('//div[@id="productMatches"]//table[@id="authorTable"]//tr[contains(@class, "IDCell")]'):
            if counter <= 0:
                break

            try:
                book_url = data.xpath('./td[1]/a/@href[1]')[0]
            except IndexError:
                continue

            try:
                title = data.xpath('./td[2]/a[1]/text()')[0].strip()
            except IndexError:
                continue
            try:
                cover_url = data.xpath('./td[1]//img[1]/@src')[0]
            except IndexError:
                cover_url = ''

            tails = [(b.tail or '').strip() for b in data.xpath('./td[2]/br')]
            authors = [x[2:].strip() for x in tails if x.startswith('by ')]
            author = authors_to_string(authors)
            price = ''.join(data.xpath('.//span[@class="variantprice"]/text()'))
            a, b, price = price.partition('$')
            price = b + price

            counter -= 1

            s = SearchResult()
            s.cover_url = cover_url
            s.title = title.strip()
            s.author = author.strip()
            s.price = price
            s.detail_item = book_url.strip()
            s.drm = SearchResult.DRM_UNLOCKED
            s.formats = 'RB, MOBI, EPUB, LIT, LRF, RTF, HTML'

            yield s
Пример #41
0
    def apply_downloaded_metadata(self, payload):
        good_ids, tdir, log_file, lm_map = payload
        if not good_ids:
            return

        modified = set()
        db = self.gui.current_db

        for i in good_ids:
            lm = db.metadata_last_modified(i, index_is_id=True)
            if lm is not None and lm_map[i] is not None and lm > lm_map[i]:
                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

        id_map = {}
        for bid in good_ids:
            opf = os.path.join(tdir, '%d.mi' % bid)
            if not os.path.exists(opf):
                opf = None
            cov = os.path.join(tdir, '%d.cover' % bid)
            if not os.path.exists(cov):
                cov = None
            id_map[bid] = (opf, cov)

        self.apply_metadata_changes(
            id_map, callback=lambda x: self.cleanup_bulk_download(tdir))
Пример #42
0
    def setup_ui(self):
        self.l = l = QVBoxLayout(self)
        self.splitter = s = QSplitter(self)
        s.setChildrenCollapsible(False)
        l.addWidget(s), l.addWidget(self.bb)
        self.bb.setStandardButtons(self.bb.Yes | self.bb.No)

        self.left = w = QWidget(self)
        s.addWidget(w)
        w.l = l = QVBoxLayout(w)
        l.setContentsMargins(0, 0, 0, 0)
        self.la = la = QLabel(self.msg)
        la.setWordWrap(True)
        l.addWidget(la)
        self.confirm = c = QCheckBox(_('Show this confirmation again'), self)
        c.setChecked(True)
        c.stateChanged.connect(self.toggle)
        l.addWidget(c)

        self.right = r = QTextBrowser(self)
        series = ''
        mi, fm = self.mi, field_metadata
        if mi.series:
            series = _('{num} of {series}').format(
                num=mi.format_series_index(), series='<i>%s</i>' % mi.series)
        r.setHtml('''
<h3 style="text-align:center">{mb}</h3>
<p><b>{title}</b> - <i>{authors}</i><br></p>
<table>
<tr><td>{fm[timestamp][name]}:</td><td>{date}</td></tr>
<tr><td>{fm[pubdate][name]}:</td><td>{published}</td></tr>
<tr><td>{fm[formats][name]}:</td><td>{formats}</td></tr>
<tr><td>{fm[series][name]}:</td><td>{series}</td></tr>
</table>
        '''.format(mb=_('Target book'),
                   title=mi.title,
                   authors=authors_to_string(mi.authors),
                   date=format_date(mi.timestamp,
                                    tweaks['gui_timestamp_display_format']),
                   fm=fm,
                   published=(format_date(mi.pubdate,
                                          tweaks['gui_pubdate_display_format'])
                              if mi.pubdate else ''),
                   formats=', '.join(mi.formats or ()),
                   series=series))
        s.addWidget(r)
Пример #43
0
def book_fmt(ctx, rd, library_id, db, book_id, fmt):
    mdata = db.format_metadata(book_id, fmt)
    if not mdata:
        raise NoSuchFormat()
    mtime = mdata['mtime']
    update_metadata = fmt in update_metadata_in_fmts
    extra_etag_data = ''

    if update_metadata:
        mi = db.get_metadata(book_id)
        mtime = max(mtime, mi.last_modified)
        # Get any plugboards for the content server
        plugboards = db.pref('plugboards')
        if plugboards:
            cpb = find_plugboard(plugboard_content_server_value, fmt,
                                 plugboards)
            if cpb:
                # Transform the metadata via the plugboard
                newmi = mi.deepcopy_metadata()
                newmi.template_to_attribute(mi, cpb)
                mi = newmi
                extra_etag_data = repr(cpb)
    else:
        mi = db.get_proxy_metadata(book_id)

    def copy_func(dest):
        db.copy_format_to(book_id, fmt, dest)
        if update_metadata:
            set_metadata(dest, mi, fmt)
            dest.seek(0)

    au = authors_to_string(mi.authors or [_('Unknown')])
    title = mi.title or _('Unknown')
    fname = '%s - %s_%s.%s' % (title[:30], au[:30], book_id, fmt)
    fname = ascii_filename(fname).replace('"', '_')
    rd.outheaders['Content-Disposition'] = 'attachment; filename="%s"' % fname

    return create_file_copy(ctx,
                            rd,
                            'fmt',
                            library_id,
                            book_id,
                            fmt,
                            mtime,
                            copy_func,
                            extra_etag_data=extra_etag_data)
Пример #44
0
def update_doc_props(root, mi, namespace):
    def setm(name, text=None, ns='dc'):
        ans = root.makeelement('{%s}%s' % (namespace.namespaces[ns], name))
        for child in tuple(root):
            if child.tag == ans.tag:
                root.remove(child)
        ans.text = text
        root.append(ans)
        return ans
    setm('title', mi.title)
    setm('creator', authors_to_string(mi.authors))
    if mi.tags:
        setm('keywords', ', '.join(mi.tags), ns='cp')
    if mi.comments:
        setm('description', mi.comments)
    if mi.languages:
        l = canonicalize_lang(mi.languages[0])
        setm('language', lang_as_iso639_1(l) or l)
Пример #45
0
    def __init__(self, oeb_metadata=None):
        from calibre import force_unicode
        from calibre.ebooks.metadata import authors_to_string
        self.title = _(u'Unknown')
        self.author = _(u'Unknown')
        self.tags = u''

        if oeb_metadata is not None:
            if len(oeb_metadata.title) >= 1:
                self.title = oeb_metadata.title[0].value
            if len(oeb_metadata.creator) >= 1:
                self.author = authors_to_string(
                    [x.value for x in oeb_metadata.creator])
            if oeb_metadata.subject:
                self.tags = u', '.join(map(unicode, oeb_metadata.subject))

        self.title = force_unicode(self.title)
        self.author = force_unicode(self.author)
Пример #46
0
    def __init__(self, mi=None):
        from calibre import force_unicode
        from calibre.ebooks.metadata import authors_to_string
        self.title = _(u'Unknown')
        self.author = _(u'Unknown')
        self.tags = u''
        self.mi = mi

        if mi is not None:
            if mi.title:
                self.title = mi.title
            if mi.authors:
                self.author = authors_to_string(mi.authors)
            if mi.tags:
                self.tags = u', '.join(mi.tags)

        self.title = force_unicode(self.title)
        self.author = force_unicode(self.author)
Пример #47
0
    def do_send_mail(self, book, mail_to, fmt, fpath):
        body = open(fpath).read()

        # read meta info
        author = authors_to_string(
            book['authors'] if book['authors'] else [_('Unknown')])
        title = book['title'] if book['title'] else _("No Title")
        fname = u'%s - %s.%s' % (title, author, fmt)
        fname = ascii_filename(fname).replace('"', '_')

        # content type
        mt = guess_type('dummy.' + fmt)[0]
        if mt is None:
            mt = 'application/octet-stream'

        # send mail
        mail_from = '*****@*****.**'
        mail_subject = _('Book from Calibre: %(title)s') % vars()
        mail_body = _('We Send this book to your kindle.')
        status = msg = ""
        try:
            msg = create_mail(mail_from,
                              mail_to,
                              mail_subject,
                              text=mail_body,
                              attachment_data=body,
                              attachment_type=mt,
                              attachment_name=fname)
            sendmail(msg,
                     from_=mail_from,
                     to=[mail_to],
                     timeout=30,
                     username=tweaks['smtp_username'],
                     password=tweaks['smtp_password'])
            status = "success"
            msg = _('Send to kindle success!! email: %(mail_to)s') % vars()
        except:
            import traceback
            cherrypy.log.error('Failed to generate cover:')
            cherrypy.log.error(traceback.format_exc())
            status = "danger"
            msg = traceback.format_exc()
        messages.append({'status': status, 'msg': msg})
        return
Пример #48
0
def set_metadata_(tdir, title, authors, bkp, tags, xmp_packet):
    podofo = get_podofo()
    os.chdir(tdir)
    p = podofo.PDFDoc()
    p.open('input.pdf')
    title = prep(title)
    touched = False
    if title and title != p.title:
        p.title = title
        touched = True

    author = prep(authors_to_string(authors))
    if author and author != p.author:
        p.author = author
        touched = True

    bkp = prep(bkp)
    if bkp and bkp != p.creator:
        p.creator = bkp
        touched = True

    try:
        tags = prep(', '.join([x.strip() for x in tags if x.strip()]))
        if tags != p.keywords:
            p.keywords = tags
            touched = True
    except:
        pass

    try:
        current_xmp_packet = p.get_xmp_metadata()
        if current_xmp_packet:
            from calibre.ebooks.metadata.xmp import merge_xmp_packet
            xmp_packet = merge_xmp_packet(current_xmp_packet, xmp_packet)
        p.set_xmp_metadata(xmp_packet)
        touched = True
    except:
        pass

    if touched:
        p.save('output.pdf')

    return touched
Пример #49
0
    def format_report(self):
        report = []
        a = report.append

        def indent(text):
            text = force_unicode(text)
            return '\xa0\xa0\xa0\xa0' + '\n\xa0\xa0\xa0\xa0'.join(
                text.splitlines())

        for book_id, errors in self.errors.iteritems():
            types = {t for t, data in errors}
            title, authors = self.book_id_data(
                book_id).title, authors_to_string(
                    self.book_id_data(book_id).authors[:1])
            if report:
                a('\n' + ('_' * 70) + '\n')
            if 'critical' in types:
                a(
                    _('Failed to save: {0} by {1} to disk, with error:').
                    format(title, authors))
                for t, tb in errors:
                    if t == 'critical':
                        a(indent(tb))
            else:
                errs = defaultdict(list)
                for t, data in errors:
                    errs[t].append(data)
                for fmt, tb in errs['fmt']:
                    a(
                        _('Failed to save the {2} format of: {0} by {1} to disk, with error:'
                          ).format(title, authors, fmt.upper()))
                    a(indent(tb)), a('')
                for fmt, tb in errs['metadata']:
                    if fmt:
                        a(
                            _('Failed to update the metadata in the {2} format of: {0} by {1}, with error:'
                              ).format(title, authors, fmt.upper()))
                    else:
                        a(
                            _('Failed to update the metadata in all formats of: {0} by {1}, with error:'
                              ).format(title, authors))
                    a(indent(tb)), a('')
        return '\n'.join(report)
Пример #50
0
    def get_format(self, id, format):
        format = format.upper()
        fm = self.db.format_metadata(id, format, allow_cache=False)
        if not fm:
            raise web.HTTPError(404, 'book: %d does not have format: %s'%(id, format))
        mi = newmi = self.db.get_metadata(id, index_is_id=True)
        self.set_header( 'Last-Modified', self.last_modified(max(fm['mtime'], mi.last_modified)) )
        fmt = self.db.format(id, format, index_is_id=True, as_file=True, mode='rb')
        if fmt is None:
            raise web.HTTPError(404, 'book: %d does not have format: %s'%(id, format))
        mt = guess_type('dummy.'+format.lower())[0]
        if mt is None:
            mt = 'application/octet-stream'
        self.set_header( 'Content-Type', mt )

        if format == 'EPUB':
            # Get the original metadata
            # Get any EPUB plugboards for the content server
            plugboards = self.db.prefs.get('plugboards', {})
            cpb = find_plugboard(plugboard_content_server_value,
                                 'epub', plugboards)
            if cpb:
                # Transform the metadata via the plugboard
                newmi = mi.deepcopy_metadata()
                newmi.template_to_attribute(mi, cpb)

        if format in ('MOBI', 'EPUB'):
            # Write the updated file
            set_metadata(fmt, newmi, format.lower())
            fmt.seek(0)

        fmt.seek(0, 2)
        self.set_header( 'Content-Lenght', fmt.tell() )
        fmt.seek(0)

        au = authors_to_string(newmi.authors if newmi.authors else
                [_('Unknown')])
        title = newmi.title if newmi.title else _('Unknown')
        fname = u'%s - %s_%s.%s'%(title[:30], au[:30], id, format.lower())
        fname = ascii_filename(fname).replace('"', '_')
        self.set_header( 'Content-Disposition',
                b'attachment; filename="%s"'%fname )
        return fmt
Пример #51
0
    def start(self, title=None, authors=None, identifiers={}):
        self.log.clear()
        self.log('Starting download')
        parts = []
        if title:
            parts.append('title:'+title)
        if authors:
            parts.append('authors:'+authors_to_string(authors))
        if identifiers:
            x = ', '.join('%s:%s'%(k, v) for k, v in identifiers.iteritems())
            parts.append(x)
        self.query.setText(_('Query: ')+'; '.join(parts))
        self.log(unicode(self.query.text()))

        self.worker = IdentifyWorker(self.log, self.abort, title,
                authors, identifiers, self.caches)

        self.worker.start()

        QTimer.singleShot(50, self.update)
Пример #52
0
def crop_pdf(pdf_path, opts, metadata=None):
    if metadata == None:
        title = _('Unknown')
        author = _('Unknown')
    else:
        title = metadata.title
        author = authors_to_string(metadata.authors)

    input_pdf = PdfFileReader(open(pdf_path, 'rb'))

    bounding_lines = []
    if opts.bounding != None:
        try:
            bounding = open(opts.bounding , 'r')
            bounding_regex = re.compile('%%BoundingBox: (?P<bottom_x>\d+) (?P<bottom_y>\d+) (?P<top_x>\d+) (?P<top_y>\d+)')
        except:
            raise Exception('Error reading %s' % opts.bounding)

        lines = bounding.readlines()
        for line in lines:
            if line.startswith('%%BoundingBox:'):
                bounding_lines.append(line)
        if len(bounding_lines) != input_pdf.numPages:
            raise Exception('Error bounding file %s page count does not correspond to specified pdf' % opts.bounding)

    output_pdf = PdfFileWriter(title=title,author=author)
    blines = iter(bounding_lines)
    for page in input_pdf.pages:
        if bounding_lines != []:
            mo = bounding_regex.search(blines.next())
            if mo == None:
                raise Exception('Error in bounding file %s' % opts.bounding)
            page.mediaBox.upperRight = (float(mo.group('top_x')), Decimal(mo.group('top_y')))
            page.mediaBox.lowerLeft  = (float(mo.group('bottom_x')), Decimal(mo.group('bottom_y')))
        else:
            page.mediaBox.upperRight = (page.bleedBox.getUpperRight_x() - Decimal(opts.top_right_x), page.bleedBox.getUpperRight_y() - Decimal(opts.top_right_y))
            page.mediaBox.lowerLeft  = (page.bleedBox.getLowerLeft_x() + Decimal(opts.bottom_left_x), page.bleedBox.getLowerLeft_y() + Decimal(opts.bottom_left_y))
        output_pdf.addPage(page)

    with open(opts.output, 'wb') as output_file:
        output_pdf.write(output_file)
    def do_send_mail(self, book, mail_to, fmt, fpath):
        try:
            import local_settings
            settings.update(local_settings.settings)
        except Exception as e:
            logging.error("read local_settings fail")
            pass
        # read meta info
        author = authors_to_string(
            book['authors'] if book['authors'] else [_(u'佚名')])
        title = book['title'] if book['title'] else _(u"无名书籍")
        fname = u'%s - %s.%s' % (title, author, fmt)
        fdata = open(fpath).read()

        mail_from = settings['smtp_username']
        mail_subject = _('奇异书屋:推送给您一本书《%(title)s》') % vars()
        mail_body = _(
            u'为您奉上一本《%(title)s》, 欢迎常来访问奇异书屋!http://www.talebook.org' % vars())
        status = msg = ""
        try:
            logging.info('send %(title)s to %(mail_to)s' % vars())
            mail = self.create_mail(mail_from, mail_to, mail_subject,
                                    mail_body, fdata, fname)
            sendmail(mail,
                     from_=mail_from,
                     to=[mail_to],
                     timeout=30,
                     relay=settings['smtp_server'],
                     username=settings['smtp_username'],
                     password=settings['smtp_password'])
            status = "success"
            msg = _('[%(title)s] 已成功发送至Kindle邮箱 [%(mail_to)s] !!') % vars()
            logging.info(msg)
        except:
            import traceback
            logging.error('Failed to send to kindle:')
            logging.error(traceback.format_exc())
            status = "danger"
            msg = traceback.format_exc()
        self.add_msg(status, msg)
        return
Пример #54
0
 def to_html(self):
     '''
     A HTML representation of this object.
     '''
     from calibre.ebooks.metadata import authors_to_string
     from calibre.utils.date import isoformat
     ans = [(_('Title'), unicode_type(self.title))]
     ans += [(_('Author(s)'), (authors_to_string(self.authors)
                               if self.authors else _('Unknown')))]
     ans += [(_('Publisher'), unicode_type(self.publisher))]
     ans += [(_('Producer'), unicode_type(self.book_producer))]
     ans += [(_('Comments'), unicode_type(self.comments))]
     ans += [('ISBN', unicode_type(self.isbn))]
     ans += [(_('Tags'), ', '.join([unicode_type(t) for t in self.tags]))]
     if self.series:
         ans += [(ngettext('Series', 'Series',
                           1), unicode_type(self.series) +
                  ' #%s' % self.format_series_index())]
     ans += [(_('Languages'), ', '.join(self.languages))]
     if self.timestamp is not None:
         ans += [
             (_('Timestamp'),
              unicode_type(isoformat(self.timestamp, as_utc=False,
                                     sep=' ')))
         ]
     if self.pubdate is not None:
         ans += [
             (_('Published'),
              unicode_type(isoformat(self.pubdate, as_utc=False, sep=' ')))
         ]
     if self.rights is not None:
         ans += [(_('Rights'), unicode_type(self.rights))]
     for key in self.custom_field_keys():
         val = self.get(key, None)
         if val:
             (name, val) = self.format_field(key)
             ans += [(name, val)]
     for i, x in enumerate(ans):
         ans[i] = '<tr><td><b>%s</b></td><td>%s</td></tr>' % x
     return '<table>%s</table>' % '\n'.join(ans)
Пример #55
0
def get_title_author_series(mi, options=None):
    if not options:
        options = cfg.plugin_prefs[cfg.STORE_CURRENT]
    title = normalize(mi.title)
    authors = mi.authors
    if options.get(cfg.KEY_SWAP_AUTHOR, False):
        swapped_authors = []
        for author in authors:
            swapped_authors.append(swap_author_names(author))
        authors = swapped_authors
    author_string = normalize(authors_to_string(authors))

    series = None
    if mi.series:
        series_text = options.get(cfg.KEY_SERIES_TEXT, '')
        if not series_text:
            series_text = cfg.DEFAULT_SERIES_TEXT
        from calibre.ebooks.metadata.book.formatter import SafeFormat
        series = SafeFormat().safe_format(
            series_text, mi, 'GC template error', mi)
    series_string = normalize(series)
    return (title, author_string, series_string)
Пример #56
0
    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(list(self.applied_ids),
                                                      cr)
            if self.gui.cover_flow:
                self.gui.cover_flow.dataChanged()
            self.gui.tags_view.recount()

        self.apply_id_map = []
        self.apply_pd = None
        try:
            if callable(self.apply_callback):
                self.apply_callback(list(self.applied_ids))
        finally:
            self.apply_callback = None
Пример #57
0
def set_metadata_implementation(pdf_doc, title, authors, bkp, tags,
                                xmp_packet):
    title = prep(title)
    touched = False
    if title and title != pdf_doc.title:
        pdf_doc.title = title
        touched = True

    author = prep(authors_to_string(authors))
    if author and author != pdf_doc.author:
        pdf_doc.author = author
        touched = True

    bkp = prep(bkp)
    if bkp and bkp != pdf_doc.creator:
        pdf_doc.creator = bkp
        touched = True
    if bkp and bkp != pdf_doc.producer:
        pdf_doc.producer = bkp
        touched = True

    try:
        tags = prep(', '.join([x.strip() for x in tags if x.strip()]))
        if tags != pdf_doc.keywords:
            pdf_doc.keywords = tags
            touched = True
    except Exception:
        pass

    try:
        current_xmp_packet = pdf_doc.get_xmp_metadata()
        if current_xmp_packet:
            from calibre.ebooks.metadata.xmp import merge_xmp_packet
            xmp_packet = merge_xmp_packet(current_xmp_packet, xmp_packet)
        pdf_doc.set_xmp_metadata(xmp_packet)
        touched = True
    except Exception:
        pass
    return touched
Пример #58
0
    def _check_proceed_with_extracted_isbns(self, payload):
        extracted_ids, _same_isbn_ids, _failed_ids = payload
        modified = set()
        db = self.gui.current_db

        for i, title, last_modified, isbn in extracted_ids:
            lm = db.metadata_last_modified(i, index_is_id=True)
            if lm > 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
        # At this point we want to re-use code in edit_metadata to go ahead and
        # apply the changes. So we will replace the Metadata objects with some
        # empty ones with only the isbn field set so only that field gets updated
        id_map = {}
        for i, title, last_modified, isbn in extracted_ids:
            mi = Metadata(_('Unknown'))
            mi.isbn = isbn
            id_map[i] = mi
        edit_metadata_action = self.gui.iactions['Edit Metadata']
        edit_metadata_action.apply_metadata_changes(id_map,
                                                    callback=self._mark_and_display_results)
Пример #59
0
    def __init__(self, mi, parent=None):
        QTextBrowser.__init__(self, parent)
        series = ''
        fm = field_metadata
        if mi.series:
            series = _('{num} of {series}').format(num=mi.format_series_index(), series='<i>%s</i>' % mi.series)
        self.setHtml('''
<h3 style="text-align:center">{mb}</h3>
<p><b>{title}</b> - <i>{authors}</i><br></p>
<table>
<tr><td>{fm[timestamp][name]}:</td><td>{date}</td></tr>
<tr><td>{fm[pubdate][name]}:</td><td>{published}</td></tr>
<tr><td>{fm[formats][name]}:</td><td>{formats}</td></tr>
<tr><td>{fm[series][name]}:</td><td>{series}</td></tr>
</table>
        '''.format(
            mb=_('Target book'),
            title=mi.title,
            authors=authors_to_string(mi.authors),
            date=format_date(mi.timestamp, tweaks['gui_timestamp_display_format']), fm=fm,
            published=(format_date(mi.pubdate, tweaks['gui_pubdate_display_format']) if mi.pubdate else ''),
            formats=', '.join(mi.formats or ()),
            series=series
        ))
Пример #60
0
    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)
        changed_books = len(self.applied_ids or ())
        self.refresh_gui(self.applied_ids)

        self.apply_id_map = []
        self.apply_pd = None
        try:
            if callable(self.apply_callback):
                self.apply_callback(list(self.applied_ids))
        finally:
            self.apply_callback = None
        if changed_books:
            QApplication.alert(self.gui, 2000)