Esempio n. 1
0
def fetch_scheduled_recipe(arg):  # {{{
    fmt = prefs['output_format'].lower()
    pt = PersistentTemporaryFile(suffix='_recipe_out.%s' % fmt.lower())
    pt.close()
    recs = []
    ps = load_defaults('page_setup')
    if 'output_profile' in ps:
        recs.append(('output_profile', ps['output_profile'],
                     OptionRecommendation.HIGH))

    lf = load_defaults('look_and_feel')
    if lf.get('base_font_size', 0.0) != 0.0:
        recs.append(('base_font_size', lf['base_font_size'],
                     OptionRecommendation.HIGH))
        recs.append(
            ('keep_ligatures', lf.get('keep_ligatures',
                                      False), OptionRecommendation.HIGH))

    lr = load_defaults('lrf_output')
    if lr.get('header', False):
        recs.append(('header', True, OptionRecommendation.HIGH))
        recs.append(('header_format', '%t', OptionRecommendation.HIGH))

    epub = load_defaults('epub_output')
    if epub.get('epub_flatten', False):
        recs.append(('epub_flatten', True, OptionRecommendation.HIGH))

    args = [arg['recipe'], pt.name, recs]
    if arg['username'] is not None:
        recs.append(('username', arg['username'], OptionRecommendation.HIGH))
    if arg['password'] is not None:
        recs.append(('password', arg['password'], OptionRecommendation.HIGH))

    return 'gui_convert', args, _(
        'Fetch news from ') + arg['title'], fmt.upper(), [pt]
Esempio n. 2
0
def fetch_scheduled_recipe(arg): # {{{
    fmt = prefs['output_format'].lower()
    pt = PersistentTemporaryFile(suffix='_recipe_out.%s'%fmt.lower())
    pt.close()
    recs = []
    ps = load_defaults('page_setup')
    if 'output_profile' in ps:
        recs.append(('output_profile', ps['output_profile'],
            OptionRecommendation.HIGH))

    lf = load_defaults('look_and_feel')
    if lf.get('base_font_size', 0.0) != 0.0:
        recs.append(('base_font_size', lf['base_font_size'],
            OptionRecommendation.HIGH))
        recs.append(('keep_ligatures', lf.get('keep_ligatures', False),
            OptionRecommendation.HIGH))

    lr = load_defaults('lrf_output')
    if lr.get('header', False):
        recs.append(('header', True, OptionRecommendation.HIGH))
        recs.append(('header_format', '%t', OptionRecommendation.HIGH))

    epub = load_defaults('epub_output')
    if epub.get('epub_flatten', False):
        recs.append(('epub_flatten', True, OptionRecommendation.HIGH))

    args = [arg['recipe'], pt.name, recs]
    if arg['username'] is not None:
        recs.append(('username', arg['username'], OptionRecommendation.HIGH))
    if arg['password'] is not None:
        recs.append(('password', arg['password'], OptionRecommendation.HIGH))


    return 'gui_convert', args, _('Fetch news from ')+arg['title'], fmt.upper(), [pt]
Esempio n. 3
0
def fetch_scheduled_recipe(arg):  # {{{
    fmt = prefs['output_format'].lower()
    # Never use AZW3 for periodicals...
    if fmt == 'azw3':
        fmt = 'mobi'
    pt = PersistentTemporaryFile(suffix='_recipe_out.%s' % fmt.lower())
    pt.close()
    recs = []
    ps = load_defaults('page_setup')
    if 'output_profile' in ps:
        recs.append(('output_profile', ps['output_profile'],
                     OptionRecommendation.HIGH))
    for edge in ('left', 'top', 'bottom', 'right'):
        edge = 'margin_' + edge
        if edge in ps:
            recs.append((edge, ps[edge], OptionRecommendation.HIGH))

    lf = load_defaults('look_and_feel')
    if lf.get('base_font_size', 0.0) != 0.0:
        recs.append(('base_font_size', lf['base_font_size'],
                     OptionRecommendation.HIGH))
        recs.append(
            ('keep_ligatures', lf.get('keep_ligatures',
                                      False), OptionRecommendation.HIGH))

    lr = load_defaults('lrf_output')
    if lr.get('header', False):
        recs.append(('header', True, OptionRecommendation.HIGH))
        recs.append(('header_format', '%t', OptionRecommendation.HIGH))

    epub = load_defaults('epub_output')
    if epub.get('epub_flatten', False):
        recs.append(('epub_flatten', True, OptionRecommendation.HIGH))

    if fmt == 'pdf':
        pdf = load_defaults('pdf_output')
        from calibre.customize.ui import plugin_for_output_format
        p = plugin_for_output_format('pdf')
        for opt in p.options:
            recs.append(
                (opt.option.name,
                 pdf.get(opt.option.name,
                         opt.recommended_value), OptionRecommendation.HIGH))

    args = [arg['recipe'], pt.name, recs]
    if arg['username'] is not None:
        recs.append(('username', arg['username'], OptionRecommendation.HIGH))
    if arg['password'] is not None:
        recs.append(('password', arg['password'], OptionRecommendation.HIGH))

    return 'gui_convert', args, _(
        'Fetch news from %s') % arg['title'], fmt.upper(), [pt]
Esempio n. 4
0
def bulk_defaults_for_input_format(fmt):
    plugin = plugin_for_input_format(fmt)
    if plugin is not None:
        w = config_widget_for_input_plugin(plugin)
        if w is not None:
            return load_defaults(w.COMMIT_NAME)
    return {}
Esempio n. 5
0
    def initialize_options(self, get_option, get_help, db=None, book_id=None):
        '''
        :param get_option: A callable that takes one argument: the option name
        and returns the corresponding OptionRecommendation.
        :param get_help: A callable that takes the option name and return a help
        string.
        '''
        defaults = load_defaults(self._name)
        defaults.merge_recommendations(get_option, OptionRecommendation.LOW,
                self._options)

        if db is not None:
            specifics = load_specifics(db, book_id)
            specifics.merge_recommendations(get_option, OptionRecommendation.HIGH,
                    self._options, only_existing=True)
            defaults.update(specifics)

        self.apply_recommendations(defaults)
        self.setup_help(get_help)

        def process_child(child):
            for g in child.children():
                if isinstance(g, QLabel):
                    buddy = g.buddy()
                    if buddy is not None and hasattr(buddy, '_help'):
                        g._help = buddy._help
                        htext = unicode(buddy.toolTip()).strip()
                        g.setToolTip(htext)
                        g.setWhatsThis(htext)
                        g.__class__.enterEvent = lambda obj, event: self.set_help(getattr(obj, '_help', obj.toolTip()))
                else:
                    process_child(g)
        process_child(self)
    def options(self):
        # Save/return the current options
        # exclude_genre stores literally
        # Section switches store as True/False
        # others store as lists

        opts_dict = {}
        opt_value = unicode(self.library_url.text())
        opts_dict['library_url'] = opt_value
        gprefs.set(self.name + '_' + 'library_url', opt_value)
        opt_value = unicode(self.excluded_tags.text())
        opt_value = unicode([tag.strip() for tag in opt_value.split(',')])
        gprefs.set(self.name + '_' + 'exclusion_tags', opt_value)
        opts_dict['exclusion_tags'] = opt_value

        opts_dict['generate_series'] = True
        opts_dict['generate_recently_added'] = False
        try:
            opts_dict['output_profile'] = [load_defaults('page_setup')['output_profile']]
        except:
            opts_dict['output_profile'] = ['default']
        opts_dict['use_existing_cover'] = False
        opts_dict['thumb_width'] = 1.0

        if self.DEBUG:
            print "opts_dict"
            for opt in sorted(opts_dict.keys(), key=sort_key):
                print " %s: %s" % (opt, repr(opts_dict[opt]))
        return opts_dict
Esempio n. 7
0
    def initialize_options(self, get_option, get_help, db=None, book_id=None):
        '''
        :param get_option: A callable that takes one argument: the option name
        and returns the corresponding OptionRecommendation.
        :param get_help: A callable that takes the option name and return a help
        string.
        '''
        defaults = load_defaults(self._name)
        defaults.merge_recommendations(get_option, OptionRecommendation.LOW,
                self._options)

        if db is not None:
            specifics = load_specifics(db, book_id)
            specifics.merge_recommendations(get_option, OptionRecommendation.HIGH,
                    self._options, only_existing=True)
            defaults.update(specifics)

        self.apply_recommendations(defaults)
        self.setup_help(get_help)

        def process_child(child):
            for g in child.children():
                if isinstance(g, QLabel):
                    buddy = g.buddy()
                    if buddy is not None and hasattr(buddy, '_help'):
                        g._help = buddy._help
                        htext = unicode(buddy.toolTip()).strip()
                        g.setToolTip(htext)
                        g.setWhatsThis(htext)
                        g.__class__.enterEvent = lambda obj, event: self.set_help(getattr(obj, '_help', obj.toolTip()))
                else:
                    process_child(g)
        process_child(self)
Esempio n. 8
0
def bulk_defaults_for_input_format(fmt):
    plugin = plugin_for_input_format(fmt)
    if plugin is not None:
        w = config_widget_for_input_plugin(plugin)
        if w is not None:
            return load_defaults(w.COMMIT_NAME)
    return {}
Esempio n. 9
0
def fetch_scheduled_recipe(arg):  # {{{
    fmt = prefs['output_format'].lower()
    # Never use AZW3 for periodicals...
    if fmt == 'azw3':
        fmt = 'mobi'
    pt = PersistentTemporaryFile(suffix='_recipe_out.%s'%fmt.lower())
    pt.close()
    recs = []
    ps = load_defaults('page_setup')
    if 'output_profile' in ps:
        recs.append(('output_profile', ps['output_profile'],
            OptionRecommendation.HIGH))
    for edge in ('left', 'top', 'bottom', 'right'):
        edge = 'margin_' + edge
        if edge in ps:
            recs.append((edge, ps[edge], OptionRecommendation.HIGH))

    lf = load_defaults('look_and_feel')
    if lf.get('base_font_size', 0.0) != 0.0:
        recs.append(('base_font_size', lf['base_font_size'],
            OptionRecommendation.HIGH))
        recs.append(('keep_ligatures', lf.get('keep_ligatures', False),
            OptionRecommendation.HIGH))

    lr = load_defaults('lrf_output')
    if lr.get('header', False):
        recs.append(('header', True, OptionRecommendation.HIGH))
        recs.append(('header_format', '%t', OptionRecommendation.HIGH))

    epub = load_defaults('epub_output')
    if epub.get('epub_flatten', False):
        recs.append(('epub_flatten', True, OptionRecommendation.HIGH))

    if fmt == 'pdf':
        pdf = load_defaults('pdf_output')
        from calibre.customize.ui import plugin_for_output_format
        p = plugin_for_output_format('pdf')
        for opt in p.options:
            recs.append((opt.option.name, pdf.get(opt.option.name, opt.recommended_value), OptionRecommendation.HIGH))

    args = [arg['recipe'], pt.name, recs]
    if arg['username'] is not None:
        recs.append(('username', arg['username'], OptionRecommendation.HIGH))
    if arg['password'] is not None:
        recs.append(('password', arg['password'], OptionRecommendation.HIGH))

    return 'gui_convert', args, _('Fetch news from ')+arg['title'], fmt.upper(), [pt]
    def options(self):
        # Save/return the current options
        # exclude_genre stores literally
        # generate_titles, generate_recently_added store as True/False
        # others store as lists

        opts_dict = {}
        # Save values to gprefs
        for opt in self.OPTION_FIELDS:
            c_name, c_def, c_type = opt
            if c_type in ['check_box', 'radio_button']:
                opt_value = getattr(self, c_name).isChecked()
            elif c_type in ['combo_box']:
                opt_value = unicode(getattr(self,
                                            c_name).currentText()).strip()
            elif c_type in ['line_edit']:
                opt_value = unicode(getattr(self, c_name).text()).strip()
            elif c_type in ['spin_box']:
                opt_value = unicode(getattr(self, c_name).value())
            gprefs.set(self.name + '_' + c_name, opt_value)

            # Construct opts object
            if c_name == 'exclude_tags':
                # store as list
                opts_dict[c_name] = opt_value.split(',')
            else:
                opts_dict[c_name] = opt_value

        # Generate markers for hybrids
        opts_dict['read_book_marker'] = "%s:%s" % (self.read_source_field_name,
                                                   self.read_pattern.text())
        opts_dict['exclude_book_marker'] = "%s:%s" % (
            self.exclude_source_field_name, self.exclude_pattern.text())

        # Generate specs for merge_comments, header_note_source_field
        checked = ''
        if self.merge_before.isChecked():
            checked = 'before'
        elif self.merge_after.isChecked():
            checked = 'after'
        include_hr = self.include_hr.isChecked()
        opts_dict['merge_comments'] = "%s:%s:%s" % \
            (self.merge_source_field_name, checked, include_hr)

        opts_dict[
            'header_note_source_field'] = self.header_note_source_field_name

        # Append the output profile
        try:
            opts_dict['output_profile'] = [
                load_defaults('page_setup')['output_profile']
            ]
        except:
            opts_dict['output_profile'] = ['default']
        if False:
            print "opts_dict"
            for opt in sorted(opts_dict.keys()):
                print " %s: %s" % (opt, repr(opts_dict[opt]))
        return opts_dict
Esempio n. 11
0
def create_epub_cover(container, cover_path):
    from calibre.ebooks.conversion.config import load_defaults
    from calibre.ebooks.oeb.transforms.cover import CoverManager

    ext = cover_path.rpartition('.')[-1].lower()
    raster_cover_item = container.generate_item('cover.'+ext, id_prefix='cover')
    raster_cover = container.href_to_name(raster_cover_item.get('href'),
                                          container.opf_name)
    with open(cover_path, 'rb') as src, container.open(raster_cover, 'wb') as dest:
        shutil.copyfileobj(src, dest)
    opts = load_defaults('epub_output')
    keep_aspect = opts.get('preserve_cover_aspect_ratio', False)
    no_svg = opts.get('no_svg_cover', False)
    if no_svg:
        style = 'style="height: 100%%"'
        templ = CoverManager.NONSVG_TEMPLATE.replace('__style__', style)
    else:
        width, height = 600, 800
        try:
            width, height = identify(cover_path)[:2]
        except:
            container.log.exception("Failed to get width and height of cover")
        ar = 'xMidYMid meet' if keep_aspect else 'none'
        templ = CoverManager.SVG_TEMPLATE.replace('__ar__', ar)
        templ = templ.replace('__viewbox__', '0 0 %d %d'%(width, height))
        templ = templ.replace('__width__', str(width))
        templ = templ.replace('__height__', str(height))
    titlepage_item = container.generate_item('titlepage.xhtml',
                                             id_prefix='titlepage')
    titlepage = container.href_to_name(titlepage_item.get('href'),
                                          container.opf_name)
    raw = templ%container.name_to_href(raster_cover).encode('utf-8')
    with container.open(titlepage, 'wb') as f:
        f.write(raw)

    # We have to make sure the raster cover item has id="cover" for the moron
    # that wrote the Nook firmware
    if raster_cover_item.get('id') != 'cover':
        from calibre.ebooks.oeb.base import uuid_id
        newid = uuid_id()
        for item in container.opf_xpath('//*[@id="cover"]'):
            item.set('id', newid)
        for item in container.opf_xpath('//*[@idref="cover"]'):
            item.set('idref', newid)
        raster_cover_item.set('id', 'cover')

    spine = container.opf_xpath('//opf:spine')[0]
    ref = spine.makeelement(OPF('itemref'), idref=titlepage_item.get('id'))
    container.insert_into_xml(spine, ref, index=0)
    guide = container.opf_get_or_create('guide')
    container.insert_into_xml(guide, guide.makeelement(
        OPF('reference'), type='cover', title=_('Cover'),
        href=container.name_to_href(titlepage, base=container.opf_name)))
    metadata = container.opf_get_or_create('metadata')
    meta = metadata.makeelement(OPF('meta'), name='cover')
    meta.set('content', raster_cover_item.get('id'))
    container.insert_into_xml(metadata, meta)

    return raster_cover, titlepage
Esempio n. 12
0
def create_epub_cover(container, cover_path):
    from calibre.ebooks.conversion.config import load_defaults
    from calibre.ebooks.oeb.transforms.cover import CoverManager

    ext = cover_path.rpartition('.')[-1].lower()
    raster_cover_item = container.generate_item('cover.'+ext, id_prefix='cover')
    raster_cover = container.href_to_name(raster_cover_item.get('href'),
                                          container.opf_name)
    with open(cover_path, 'rb') as src, container.open(raster_cover, 'wb') as dest:
        shutil.copyfileobj(src, dest)
    opts = load_defaults('epub_output')
    keep_aspect = opts.get('preserve_cover_aspect_ratio', False)
    no_svg = opts.get('no_svg_cover', False)
    if no_svg:
        style = 'style="height: 100%%"'
        templ = CoverManager.NONSVG_TEMPLATE.replace('__style__', style)
    else:
        width, height = 600, 800
        try:
            width, height = identify(cover_path)[:2]
        except:
            container.log.exception("Failed to get width and height of cover")
        ar = 'xMidYMid meet' if keep_aspect else 'none'
        templ = CoverManager.SVG_TEMPLATE.replace('__ar__', ar)
        templ = templ.replace('__viewbox__', '0 0 %d %d'%(width, height))
        templ = templ.replace('__width__', str(width))
        templ = templ.replace('__height__', str(height))
    titlepage_item = container.generate_item('titlepage.xhtml',
                                             id_prefix='titlepage')
    titlepage = container.href_to_name(titlepage_item.get('href'),
                                          container.opf_name)
    raw = templ%container.name_to_href(raster_cover).encode('utf-8')
    with container.open(titlepage, 'wb') as f:
        f.write(raw)

    # We have to make sure the raster cover item has id="cover" for the moron
    # that wrote the Nook firmware
    if raster_cover_item.get('id') != 'cover':
        from calibre.ebooks.oeb.base import uuid_id
        newid = uuid_id()
        for item in container.opf_xpath('//*[@id="cover"]'):
            item.set('id', newid)
        for item in container.opf_xpath('//*[@idref="cover"]'):
            item.set('idref', newid)
        raster_cover_item.set('id', 'cover')

    spine = container.opf_xpath('//opf:spine')[0]
    ref = spine.makeelement(OPF('itemref'), idref=titlepage_item.get('id'))
    container.insert_into_xml(spine, ref, index=0)
    guide = container.opf_get_or_create('guide')
    container.insert_into_xml(guide, guide.makeelement(
        OPF('reference'), type='cover', title=_('Cover'),
        href=container.name_to_href(titlepage, base=container.opf_name)))
    metadata = container.opf_get_or_create('metadata')
    meta = metadata.makeelement(OPF('meta'), name='cover')
    meta.set('content', raster_cover_item.get('id'))
    container.insert_into_xml(metadata, meta)

    return raster_cover, titlepage
Esempio n. 13
0
def get_recipe(urls, title):
    fmt = cprefs['output_format'].lower()
    pt = PersistentTemporaryFile(suffix='_recipe_out.%s' % fmt.lower())
    pt.close()
    recs = []
    ps = load_defaults('page_setup')
    if 'output_profile' in ps:
        recs.append(('output_profile', ps['output_profile'],
                     OptionRecommendation.HIGH))

    lf = load_defaults('look_and_feel')
    if lf.get('base_font_size', 0.0) != 0.0:
        recs.append(('base_font_size', lf['base_font_size'],
                     OptionRecommendation.HIGH))
        recs.append(('keep_ligatures', lf.get('keep_ligatures', False),
                     OptionRecommendation.HIGH))

    lr = load_defaults('lrf_output')
    if lr.get('header', False):
        recs.append(('header', True, OptionRecommendation.HIGH))
        recs.append(('header_format', '%t', OptionRecommendation.HIGH))

    epub = load_defaults('epub_output')
    if epub.get('epub_flatten', False):
        recs.append(('epub_flatten', True, OptionRecommendation.HIGH))

    recipe = get_resources('wikipedia.recipe')
    url_line = bytes(repr(urls))
    recipe = re.sub(
        br'^(\s+urls = ).+?# REPLACE_ME_URLS', br'\1' + url_line, recipe,
        flags=re.M)
    if title.strip():
        title_line = bytes(repr(title))
        recipe = re.sub(
            br'^(\s+title\s+=\s+)DEFAULT_TITLE', br'\1' + title_line, recipe,
            flags=re.M)
    logo = get_resources('images/icon.png')
    lf = PersistentTemporaryFile('_wiki_logo.png')
    lf.write(logo)
    recipe = recipe.replace(b'LOGO = None', b'LOGO = %r' % lf.name)
    lf.close()
    rf = PersistentTemporaryFile(suffix='_wikipedia.recipe')
    rf.write(recipe)
    rf.close()
    args = [rf.name, pt.name, recs]
    return args, fmt.upper(), [pt, rf, lf]
Esempio n. 14
0
 def commit(cls):
     cls.set_output_profile()
     cls.set_output_format()
     if cls.supports_color:
         from calibre.ebooks.conversion.config import load_defaults, save_defaults
         recs = load_defaults('comic_input')
         recs['dont_grayscale'] = True
         save_defaults('comic_input', recs)
Esempio n. 15
0
 def commit(cls):
     cls.set_output_profile()
     cls.set_output_format()
     if cls.supports_color:
         from calibre.ebooks.conversion.config import load_defaults, save_defaults
         recs = load_defaults('comic_input')
         recs['dont_grayscale'] = True
         save_defaults('comic_input', recs)
Esempio n. 16
0
def generate_masthead(title, output_path=None, width=600, height=60):
    from calibre.ebooks.conversion.config import load_defaults
    recs = load_defaults('mobi_output')
    masthead_font_family = recs.get('masthead_font', None)
    from calibre.ebooks.covers import generate_masthead
    return generate_masthead(title,
                             output_path=output_path,
                             width=width,
                             height=height,
                             font_family=masthead_font_family)
Esempio n. 17
0
    def options(self):
        # Save/return the current options
        # exclude_genre stores literally
        # generate_titles, generate_recently_added store as True/False
        # others store as lists

        opts_dict = {}
        # Save values to gprefs
        for opt in self.OPTION_FIELDS:
            c_name, c_def, c_type = opt
            if c_type in ['check_box', 'radio_button']:
                opt_value = getattr(self, c_name).isChecked()
            elif c_type in ['combo_box']:
                opt_value = unicode(getattr(self,c_name).currentText()).strip()
            elif c_type in ['line_edit']:
                opt_value = unicode(getattr(self, c_name).text()).strip()
            elif c_type in ['spin_box']:
                opt_value = unicode(getattr(self, c_name).value())
            gprefs.set(self.name + '_' + c_name, opt_value)

            # Construct opts object
            if c_name == 'exclude_tags':
                # store as list
                opts_dict[c_name] = opt_value.split(',')
            else:
                opts_dict[c_name] = opt_value

        # Generate markers for hybrids
        opts_dict['read_book_marker'] = "%s:%s" % (self.read_source_field_name,
                                                   self.read_pattern.text())
        opts_dict['exclude_book_marker'] = "%s:%s" % (self.exclude_source_field_name,
                                                       self.exclude_pattern.text())

        # Generate specs for merge_comments, header_note_source_field
        checked = ''
        if self.merge_before.isChecked():
            checked = 'before'
        elif self.merge_after.isChecked():
            checked = 'after'
        include_hr = self.include_hr.isChecked()
        opts_dict['merge_comments'] = "%s:%s:%s" % \
            (self.merge_source_field_name, checked, include_hr)

        opts_dict['header_note_source_field'] = self.header_note_source_field_name

        # Append the output profile
        try:
            opts_dict['output_profile'] = [load_defaults('page_setup')['output_profile']]
        except:
            opts_dict['output_profile'] = ['default']
        if False:
            print "opts_dict"
            for opt in sorted(opts_dict.keys()):
                print " %s: %s" % (opt, repr(opts_dict[opt]))
        return opts_dict
Esempio n. 18
0
 def get_profile_values(self):
     from calibre.ebooks.conversion.config import load_defaults
     recs = load_defaults('page_setup')
     pfname = recs.get('output_profile', 'default')
     from calibre.customize.ui import output_profiles
     for profile in output_profiles():
         if profile.short_name == pfname:
             break
     dbase = profile.fbase
     fsizes = profile.fkey
     return dbase, fsizes
Esempio n. 19
0
 def get_profile_values(self):
     from calibre.ebooks.conversion.config import load_defaults
     recs = load_defaults('page_setup')
     pfname = recs.get('output_profile', 'default')
     from calibre.customize.ui import output_profiles
     for profile in output_profiles():
         if profile.short_name == pfname:
             break
     dbase = profile.fbase
     fsizes = profile.fkey
     return dbase, fsizes
Esempio n. 20
0
def generate_masthead(title, output_path=None, width=600, height=60):
    from calibre.ebooks.conversion.config import load_defaults
    from calibre.utils.config import tweaks

    fp = tweaks["generate_cover_title_font"]
    if not fp:
        fp = P("fonts/liberation/LiberationSerif-Bold.ttf")
    font_path = default_font = fp
    recs = load_defaults("mobi_output")
    masthead_font_family = recs.get("masthead_font", "Default")

    if masthead_font_family != "Default":
        from calibre.utils.fonts.scanner import font_scanner, NoFonts

        try:
            faces = font_scanner.fonts_for_family(masthead_font_family)
        except NoFonts:
            faces = []
        if faces:
            font_path = faces[0]["path"]

    if not font_path or not os.access(font_path, os.R_OK):
        font_path = default_font

    try:
        from PIL import Image, ImageDraw, ImageFont

        Image, ImageDraw, ImageFont
    except ImportError:
        import Image, ImageDraw, ImageFont

    img = Image.new("RGB", (width, height), "white")
    draw = ImageDraw.Draw(img)
    try:
        font = ImageFont.truetype(font_path, 48, encoding="unic")
    except:
        font = ImageFont.truetype(default_font, 48, encoding="unic")
    text = force_unicode(title)
    width, height = draw.textsize(text, font=font)
    left = max(int((width - width) / 2.0), 0)
    top = max(int((height - height) / 2.0), 0)
    draw.text((left, top), text, fill=(0, 0, 0), font=font)
    if output_path is None:
        f = StringIO()
        img.save(f, "JPEG")
        return f.getvalue()
    else:
        with open(output_path, "wb") as f:
            img.save(f, "JPEG")
Esempio n. 21
0
 def merge_group(group_name, option_names):
     if not group_name or group_name in ('debug', 'metadata'):
         return
     defs = load_defaults(group_name)
     defs.merge_recommendations(plumber.get_option_by_name,
                                OptionRecommendation.LOW, option_names)
     specifics.merge_recommendations(plumber.get_option_by_name,
                                     OptionRecommendation.HIGH,
                                     option_names,
                                     only_existing=True)
     for k in defs:
         if k in specifics:
             defs[k] = specifics[k]
     defs = defs.as_dict()
     ans['options'].update(defs['options'])
     ans['disabled'] |= set(defs['disabled'])
Esempio n. 22
0
 def merge_group(group_name, option_names):
     if not group_name or group_name in ('debug', 'metadata'):
         return
     defs = load_defaults(group_name)
     defs.merge_recommendations(
         plumber.get_option_by_name, OptionRecommendation.LOW, option_names)
     specifics.merge_recommendations(
         plumber.get_option_by_name, OptionRecommendation.HIGH, option_names, only_existing=True)
     defaults = defs.as_dict()['options']
     for k in defs:
         if k in specifics:
             defs[k] = specifics[k]
     defs = defs.as_dict()
     ans['options'].update(defs['options'])
     ans['disabled'] |= set(defs['disabled'])
     ans['defaults'].update(defaults)
     ans['help'] = plumber.get_all_help()
Esempio n. 23
0
def generate_masthead(title, output_path=None, width=600, height=60):
    from calibre.ebooks.conversion.config import load_defaults
    from calibre.utils.config import tweaks
    fp = tweaks['generate_cover_title_font']
    if not fp:
        fp = P('fonts/liberation/LiberationSerif-Bold.ttf')
    font_path = default_font = fp
    recs = load_defaults('mobi_output')
    masthead_font_family = recs.get('masthead_font', 'Default')

    if masthead_font_family != 'Default':
        from calibre.utils.fonts.scanner import font_scanner, NoFonts
        try:
            faces = font_scanner.fonts_for_family(masthead_font_family)
        except NoFonts:
            faces = []
        if faces:
            font_path = faces[0]['path']

    if not font_path or not os.access(font_path, os.R_OK):
        font_path = default_font

    try:
        from PIL import Image, ImageDraw, ImageFont
        Image, ImageDraw, ImageFont
    except ImportError:
        import Image, ImageDraw, ImageFont

    img = Image.new('RGB', (width, height), 'white')
    draw = ImageDraw.Draw(img)
    try:
        font = ImageFont.truetype(font_path, 48, encoding='unic')
    except:
        font = ImageFont.truetype(default_font, 48, encoding='unic')
    text = force_unicode(title)
    width, height = draw.textsize(text, font=font)
    left = max(int((width - width)/2.), 0)
    top = max(int((height - height)/2.), 0)
    draw.text((left, top), text, fill=(0,0,0), font=font)
    if output_path is None:
        f = StringIO()
        img.save(f, 'JPEG')
        return f.getvalue()
    else:
        with open(output_path, 'wb') as f:
            img.save(f, 'JPEG')
Esempio n. 24
0
def generate_masthead(title, output_path=None, width=600, height=60):
    from calibre.ebooks.conversion.config import load_defaults
    from calibre.utils.fonts import fontconfig
    from calibre.utils.config import tweaks
    fp = tweaks['generate_cover_title_font']
    if not fp:
        fp = P('fonts/liberation/LiberationSerif-Bold.ttf')
    font_path = default_font = fp
    recs = load_defaults('mobi_output')
    masthead_font_family = recs.get('masthead_font', 'Default')

    if masthead_font_family != 'Default':
        masthead_font = fontconfig.files_for_family(masthead_font_family)
        # Assume 'normal' always in dict, else use default
        # {'normal': (path_to_font, friendly name)}
        if 'normal' in masthead_font:
            font_path = masthead_font['normal'][0]

    if not font_path or not os.access(font_path, os.R_OK):
        font_path = default_font

    try:
        from PIL import Image, ImageDraw, ImageFont
        Image, ImageDraw, ImageFont
    except ImportError:
        import Image, ImageDraw, ImageFont

    img = Image.new('RGB', (width, height), 'white')
    draw = ImageDraw.Draw(img)
    try:
        font = ImageFont.truetype(font_path, 48, encoding='unic')
    except:
        font = ImageFont.truetype(default_font, 48, encoding='unic')
    text = force_unicode(title)
    width, height = draw.textsize(text, font=font)
    left = max(int((width - width)/2.), 0)
    top = max(int((height - height)/2.), 0)
    draw.text((left, top), text, fill=(0,0,0), font=font)
    if output_path is None:
        f = StringIO()
        img.save(f, 'JPEG')
        return f.getvalue()
    else:
        with open(output_path, 'wb') as f:
            img.save(f, 'JPEG')
Esempio n. 25
0
def render_jacket(container, jacket):
    mi = container.mi
    ps = load_defaults('page_setup')
    op = ps.get('output_profile', 'default')
    opmap = {x.short_name:x for x in output_profiles()}
    output_profile = opmap.get(op, opmap['default'])
    root = render(mi, output_profile)
    for img, path in referenced_images(root):
        container.log('Embedding referenced image: %s into jacket' % path)
        ext = path.rpartition('.')[-1]
        jacket_item = container.generate_item('jacket_image.'+ext, id_prefix='jacket_img')
        name = container.href_to_name(jacket_item.get('href'), container.opf_name)
        with open(path, 'rb') as f:
            container.parsed_cache[name] = f.read()
            container.commit_item(name)
        href = container.name_to_href(name, jacket)
        img.set('src', href)
    return root
Esempio n. 26
0
def render_jacket(container, jacket):
    mi = container.mi
    ps = load_defaults('page_setup')
    op = ps.get('output_profile', 'default')
    opmap = {x.short_name:x for x in output_profiles()}
    output_profile = opmap.get(op, opmap['default'])
    root = render(mi, output_profile)
    for img, path in referenced_images(root):
        container.log('Embedding referenced image: %s into jacket' % path)
        ext = path.rpartition('.')[-1]
        jacket_item = container.generate_item('jacket_image.'+ext, id_prefix='jacket_img')
        name = container.href_to_name(jacket_item.get('href'), container.opf_name)
        with open(path, 'rb') as f:
            container.parsed_cache[name] = f.read()
            container.commit_item(name)
        href = container.name_to_href(name, jacket)
        img.set('src', href)
    return root
Esempio n. 27
0
 def set_image_settings(cls):
     from calibre.ebooks.conversion.config import load_defaults, save_defaults
     recs = load_defaults('comic_input')
     
     output_profile = "No output profile found."
     for profile in output_profiles():
         if profile.short_name == cls.output_profile:
             output_profile = profile
     
     if getattr(output_profile, 'colors', 0): # Can also refer to grayscale shades
         recs['colors'] = getattr(output_profile, 'colors')
     
     if getattr(output_profile, 'supports_color', False):
         recs['dont_grayscale'] = True
     
     if getattr(output_profile, 'large_screen', False):
         recs['keep_aspect_ratio'] = True
     
     save_defaults('comic_input', recs)
Esempio n. 28
0
    def update(self, mi):
        # Collect the original metadata
        self.get_original_metadata()

        try:
            from calibre.ebooks.conversion.config import load_defaults
            prefs = load_defaults('mobi_output')
            pas = prefs.get('prefer_author_sort', False)
        except:
            pas = False

        if mi.author_sort and pas:
            authors = mi.author_sort
            self.metadata['Authors'] = authors.encode('utf-8')
        elif mi.authors:
            authors = '; '.join(mi.authors)
            self.metadata['Authors'] = authors.encode('utf-8')
        self.metadata['Title'] = mi.title.encode('utf-8')

        updated_metadata = self.generate_metadata_stream()
        # Skip tag_len, tag, extra
        prefix = len('metadata') + 2
        um_buf_len = len(updated_metadata) - prefix
        head = self.regenerate_headers(um_buf_len)

        # Chunk1: self.base -> original metadata start
        # Chunk2: original metadata end -> eof
        chunk1 = self.data[self.base:self.original_md_start]
        chunk2 = self.data[prefix + self.original_md_start +
                           self.original_md_len:]

        self.stream.seek(0)
        self.stream.truncate(0)

        # Write the revised stream
        self.stream.write(head)
        self.stream.write('d')
        self.stream.write(chunk1)
        self.stream.write(updated_metadata)
        self.stream.write(chunk2)
Esempio n. 29
0
    def update(self,mi):
        # Collect the original metadata
        self.get_original_metadata()

        try:
            from calibre.ebooks.conversion.config import load_defaults
            prefs = load_defaults('mobi_output')
            pas = prefs.get('prefer_author_sort', False)
        except:
            pas = False

        if mi.author_sort and pas:
            authors = mi.author_sort
            self.metadata['Authors'] = authors.encode('utf-8')
        elif mi.authors:
            authors = '; '.join(mi.authors)
            self.metadata['Authors'] = authors.encode('utf-8')
        self.metadata['Title'] = mi.title.encode('utf-8')

        updated_metadata = self.generate_metadata_stream()
        # Skip tag_len, tag, extra
        prefix = len('metadata') + 2
        um_buf_len = len(updated_metadata) - prefix
        head = self.regenerate_headers(um_buf_len)

        # Chunk1: self.base -> original metadata start
        # Chunk2: original metadata end -> eof
        chunk1 = self.data[self.base:self.original_md_start]
        chunk2 = self.data[prefix + self.original_md_start + self.original_md_len:]

        self.stream.seek(0)
        self.stream.truncate(0)

        # Write the revised stream
        self.stream.write(head)
        self.stream.write('d')
        self.stream.write(chunk1)
        self.stream.write(updated_metadata)
        self.stream.write(chunk2)
Esempio n. 30
0
    def options(self):
        # Save/return the current options
        # exclude_genre stores literally
        # Section switches store as True/False
        # others store as lists

        opts_dict = {}
        prefix_rules_processed = False
        exclusion_rules_processed = False

        for opt in self.OPTION_FIELDS:
            c_name, c_def, c_type = opt
            if c_name == 'exclusion_rules_tw' and exclusion_rules_processed:
                continue
            if c_name == 'prefix_rules_tw' and prefix_rules_processed:
                continue

            if c_type in ['check_box', 'radio_button']:
                opt_value = getattr(self, c_name).isChecked()
            elif c_type in ['combo_box']:
                opt_value = unicode(getattr(self,c_name).currentText()).strip()
            elif c_type in ['line_edit']:
                opt_value = unicode(getattr(self, c_name).text()).strip()
            elif c_type in ['spin_box']:
                opt_value = unicode(getattr(self, c_name).value())
            elif c_type in ['table_widget']:
                if c_name == 'prefix_rules_tw':
                    opt_value = self.prefix_rules_table.get_data()
                    prefix_rules_processed = True
                if c_name == 'exclusion_rules_tw':
                    opt_value = self.exclusion_rules_table.get_data()
                    exclusion_rules_processed = True

            # Store UI values to gui.json in config dir
            gprefs.set(self.name + '_' + c_name, opt_value)

            # Construct opts object for catalog builder
            if c_name in ['exclusion_rules_tw','prefix_rules_tw']:
                self.construct_tw_opts_object(c_name, opt_value, opts_dict)
            else:
                opts_dict[c_name] = opt_value

        # Generate specs for merge_comments, header_note_source_field
        checked = ''
        if self.merge_before.isChecked():
            checked = 'before'
        elif self.merge_after.isChecked():
            checked = 'after'
        include_hr = self.include_hr.isChecked()
        opts_dict['merge_comments_rule'] = "%s:%s:%s" % \
            (self.merge_source_field_name, checked, include_hr)

        opts_dict['header_note_source_field'] = self.header_note_source_field_name

        # Fix up exclude_genre regex if blank. Assume blank = no exclusions
        if opts_dict['exclude_genre'] == '':
            opts_dict['exclude_genre'] = 'a^'

        # Append the output profile
        try:
            opts_dict['output_profile'] = [load_defaults('page_setup')['output_profile']]
        except:
            opts_dict['output_profile'] = ['default']

        if self.DEBUG:
            print "opts_dict"
            for opt in sorted(opts_dict.keys(), key=sort_key):
                print " %s: %s" % (opt, repr(opts_dict[opt]))
        return opts_dict
Esempio n. 31
0
    def update(self, mi, asin=None):
        mi.title = normalize(mi.title)

        def update_exth_record(rec):
            recs.append(rec)
            if rec[0] in self.original_exth_records:
                self.original_exth_records.pop(rec[0])

        if self.type != b"BOOKMOBI":
            raise MobiError(
                "Setting metadata only supported for MOBI files of type 'BOOK'.\n"
                "\tThis is a %r file of type %r" %
                (self.type[0:4], self.type[4:8]))

        recs = []
        added_501 = False
        try:
            from calibre.ebooks.conversion.config import load_defaults
            prefs = load_defaults('mobi_output')
            pas = prefs.get('prefer_author_sort', False)
            kindle_pdoc = prefs.get('personal_doc', None)
            share_not_sync = prefs.get('share_not_sync', False)
        except:
            pas = False
            kindle_pdoc = None
            share_not_sync = False
        if mi.author_sort and pas:
            # We want an EXTH field per author...
            authors = mi.author_sort.split(' & ')
            for author in authors:
                update_exth_record(
                    (100, normalize(author).encode(self.codec, 'replace')))
        elif mi.authors:
            authors = mi.authors
            for author in authors:
                update_exth_record(
                    (100, normalize(author).encode(self.codec, 'replace')))
        if mi.publisher:
            update_exth_record(
                (101, normalize(mi.publisher).encode(self.codec, 'replace')))
        if mi.comments:
            # Strip user annotations
            a_offset = mi.comments.find('<div class="user_annotations">')
            ad_offset = mi.comments.find('<hr class="annotations_divider" />')
            if a_offset >= 0:
                mi.comments = mi.comments[:a_offset]
            if ad_offset >= 0:
                mi.comments = mi.comments[:ad_offset]
            update_exth_record(
                (103, normalize(mi.comments).encode(self.codec, 'replace')))
        if mi.isbn:
            update_exth_record((104, mi.isbn.encode(self.codec, 'replace')))
        if mi.tags:
            # FIXME: Keep a single subject per EXTH field?
            subjects = '; '.join(mi.tags)
            update_exth_record(
                (105, normalize(subjects).encode(self.codec, 'replace')))

            if kindle_pdoc and kindle_pdoc in mi.tags:
                added_501 = True
                update_exth_record((501, b'PDOC'))

        if mi.pubdate:
            update_exth_record(
                (106, unicode_type(mi.pubdate).encode(self.codec, 'replace')))
        elif mi.timestamp:
            update_exth_record(
                (106, unicode_type(mi.timestamp).encode(self.codec,
                                                        'replace')))
        elif self.timestamp:
            update_exth_record((106, self.timestamp))
        else:
            update_exth_record(
                (106, nowf().isoformat().encode(self.codec, 'replace')))
        if self.cover_record is not None:
            update_exth_record((201, pack('>I', self.cover_rindex)))
            update_exth_record((203, pack('>I', 0)))
        if self.thumbnail_record is not None:
            update_exth_record((202, pack('>I', self.thumbnail_rindex)))
        # Add a 113 record if not present to allow Amazon syncing
        if (113 not in self.original_exth_records
                and self.original_exth_records.get(501, None) == 'EBOK'
                and not added_501 and not share_not_sync):
            from uuid import uuid4
            update_exth_record((113, unicode_type(uuid4()).encode(self.codec)))

        if asin is not None:
            update_exth_record((113, asin.encode(self.codec)))
            update_exth_record((504, asin.encode(self.codec)))

        # Add a 112 record with actual UUID
        if getattr(mi, 'uuid', None):
            update_exth_record(
                (112, ("calibre:%s" % mi.uuid).encode(self.codec, 'replace')))
        if 503 in self.original_exth_records:
            update_exth_record((503, mi.title.encode(self.codec, 'replace')))

        # Update book producer
        if getattr(mi, 'book_producer', False):
            update_exth_record(
                (108, mi.book_producer.encode(self.codec, 'replace')))

        # Set langcode in EXTH header
        if not mi.is_null('language'):
            lang = canonicalize_lang(mi.language)
            lang = lang_as_iso639_1(lang) or lang
            if lang:
                update_exth_record((524, lang.encode(self.codec, 'replace')))

        # Include remaining original EXTH fields
        for id in sorted(self.original_exth_records):
            recs.append((id, self.original_exth_records[id]))
        recs = sorted(recs, key=lambda x: (x[0], x[0]))

        exth = io.BytesIO()
        for code, data in recs:
            exth.write(pack('>II', code, len(data) + 8))
            exth.write(data)
        exth = exth.getvalue()
        trail = len(exth) % 4
        pad = b'\0' * (4 - trail)  # Always pad w/ at least 1 byte
        exth = [b'EXTH', pack('>II', len(exth) + 12, len(recs)), exth, pad]
        exth = b''.join(exth)

        if getattr(self, 'exth', None) is None:
            raise MobiError('No existing EXTH record. Cannot update metadata.')

        if not mi.is_null('language'):
            self.record0[92:96] = iana2mobi(mi.language)
        self.create_exth(exth=exth, new_title=mi.title)

        # Fetch updated timestamp, cover_record, thumbnail_record
        self.fetchEXTHFields()

        if mi.cover_data[1] or mi.cover:
            try:
                data = mi.cover_data[1]
                if not data:
                    with open(mi.cover, 'rb') as f:
                        data = f.read()
            except:
                pass
            else:
                if is_image(self.cover_record):
                    size = len(self.cover_record)
                    cover = rescale_image(data, size)
                    if len(cover) <= size:
                        cover += b'\0' * (size - len(cover))
                        self.cover_record[:] = cover
                if is_image(self.thumbnail_record):
                    size = len(self.thumbnail_record)
                    thumbnail = rescale_image(data,
                                              size,
                                              dimen=MAX_THUMB_DIMEN)
                    if len(thumbnail) <= size:
                        thumbnail += b'\0' * (size - len(thumbnail))
                        self.thumbnail_record[:] = thumbnail
                return
Esempio n. 32
0
    def set_metadata(self, stream, mi, type_):
        from calibre_plugins.kfx_output.kfxlib import (set_logger, YJ_Book, YJ_Metadata)
        from calibre.ebooks import normalize as normalize_unicode
        from calibre.ebooks.metadata import author_to_author_sort
        from calibre.utils.config_base import tweaks
        from calibre.utils.date import (is_date_undefined, isoformat)
        from calibre.utils.logging import Log
        from calibre.utils.localization import (canonicalize_lang, lang_as_iso639_1)

        def mapped_author_to_author_sort(author):
            if hasattr(mi, "author_sort_map"):
                author_sort = mi.author_sort_map.get(author)    # use mapping if provided
                if author_sort:
                    return author_sort

            return author_to_author_sort(author)

        def normalize(s):
            if not isinstance(s, type("")):
                s = s.decode("utf8", "ignore")

            return normalize_unicode(s)

        log = set_logger(Log())

        filename = stream.name if hasattr(stream, "name") else "stream"
        log.info("KFX metadata writer activated for %s" % filename)

        try:
            from calibre.ebooks.conversion.config import load_defaults
            prefs = load_defaults('kfx_output')
        except Exception:
            prefs = {}
            log.info("Failed to read default KFX Output preferences")

        md = YJ_Metadata(author_sort_fn=mapped_author_to_author_sort)

        md.title = normalize(mi.title)

        md.authors = [normalize(author) for author in mi.authors]

        if mi.publisher:
            md.publisher = normalize(mi.publisher)

        if mi.pubdate and not is_date_undefined(mi.pubdate):
            md.issue_date = str(isoformat(mi.pubdate)[:10])

        if mi.comments:
            # Strip user annotations
            a_offset = mi.comments.find('<div class="user_annotations">')
            ad_offset = mi.comments.find('<hr class="annotations_divider" />')

            if a_offset >= 0:
                mi.comments = mi.comments[:a_offset]
            if ad_offset >= 0:
                mi.comments = mi.comments[:ad_offset]

            md.description = normalize(mi.comments)

        if not mi.is_null('language'):
            lang = canonicalize_lang(mi.language)
            lang = lang_as_iso639_1(lang) or lang
            if lang:
                md.language = normalize(lang)

        if mi.cover_data[1]:
            md.cover_image_data = mi.cover_data
        elif mi.cover:
            md.cover_image_data = ("jpg", open(mi.cover, 'rb').read())

        if not tweaks.get("kfx_output_ignore_asin_metadata", False):
            value = mi.identifiers.get("mobi-asin")
            if value is not None and re.match(ASIN_RE, value):
                md.asin = value
            else:
                for ident, value in mi.identifiers.items():
                    if ident.startswith("amazon") and re.match(ASIN_RE, value):
                        md.asin = value
                        break
                else:
                    value = mi.identifiers.get("asin")
                    if value is not None and re.match(ASIN_RE, value):
                        md.asin = value

        if md.asin:
            md.cde_content_type = "EBOK"

        if prefs.get("approximate_pages", False):
            page_count = 0
            number_of_pages_field = prefs.get("number_of_pages_field", AUTO_PAGES)
            if number_of_pages_field and number_of_pages_field != AUTO_PAGES:
                number_of_pages = mi.get(number_of_pages_field, "")
                try:
                    page_count = int(number_of_pages)
                except Exception:
                    pass
        else:
            page_count = -1

        book = YJ_Book(stream, log)
        book.decode_book(set_metadata=md, set_approximate_pages=page_count)
        new_data = book.convert_to_single_kfx()
        set_logger()

        stream.seek(0)
        stream.truncate()
        stream.write(new_data)
        stream.seek(0)
Esempio n. 33
0
 def set_output_profile(cls):
     if cls.output_profile:
         from calibre.ebooks.conversion.config import load_defaults, save_defaults
         recs = load_defaults('page_setup')
         recs['output_profile'] = cls.output_profile
         save_defaults('page_setup', recs)
Esempio n. 34
0
def create_epub_cover(container, cover_path, existing_image, options=None):
    from calibre.ebooks.conversion.config import load_defaults
    from calibre.ebooks.oeb.transforms.cover import CoverManager

    try:
        ext = cover_path.rpartition(".")[-1].lower()
    except Exception:
        ext = "jpeg"
    cname, tname = "cover." + ext, "titlepage.xhtml"
    recommended_folders = get_recommended_folders(container, (cname, tname))

    if existing_image:
        raster_cover = existing_image
        manifest_id = {v: k for k, v in container.manifest_id_map.iteritems()}[existing_image]
        raster_cover_item = container.opf_xpath('//opf:manifest/*[@id="%s"]' % manifest_id)[0]
    else:
        folder = recommended_folders[cname]
        if folder:
            cname = folder + "/" + cname
        raster_cover_item = container.generate_item(cname, id_prefix="cover")
        raster_cover = container.href_to_name(raster_cover_item.get("href"), container.opf_name)

        with container.open(raster_cover, "wb") as dest:
            if callable(cover_path):
                cover_path("write_image", dest)
            else:
                with lopen(cover_path, "rb") as src:
                    shutil.copyfileobj(src, dest)
    if options is None:
        opts = load_defaults("epub_output")
        keep_aspect = opts.get("preserve_cover_aspect_ratio", False)
        no_svg = opts.get("no_svg_cover", False)
    else:
        keep_aspect = options.get("keep_aspect", False)
        no_svg = options.get("no_svg", False)
    if no_svg:
        style = 'style="height: 100%%"'
        templ = CoverManager.NONSVG_TEMPLATE.replace("__style__", style)
    else:
        if callable(cover_path):
            templ = (options or {}).get("template", CoverManager.SVG_TEMPLATE)
        else:
            width, height = 600, 800
            try:
                if existing_image:
                    width, height = identify(container.raw_data(existing_image, decode=False))[1:]
                else:
                    with lopen(cover_path, "rb") as csrc:
                        width, height = identify(csrc)[1:]
            except:
                container.log.exception("Failed to get width and height of cover")
            ar = "xMidYMid meet" if keep_aspect else "none"
            templ = CoverManager.SVG_TEMPLATE.replace("__ar__", ar)
            templ = templ.replace("__viewbox__", "0 0 %d %d" % (width, height))
            templ = templ.replace("__width__", str(width))
            templ = templ.replace("__height__", str(height))
    folder = recommended_folders[tname]
    if folder:
        tname = folder + "/" + tname
    titlepage_item = container.generate_item(tname, id_prefix="titlepage")
    titlepage = container.href_to_name(titlepage_item.get("href"), container.opf_name)
    raw = templ % container.name_to_href(raster_cover, titlepage).encode("utf-8")
    with container.open(titlepage, "wb") as f:
        f.write(raw)

    # We have to make sure the raster cover item has id="cover" for the moron
    # that wrote the Nook firmware
    if raster_cover_item.get("id") != "cover":
        from calibre.ebooks.oeb.base import uuid_id

        newid = uuid_id()
        for item in container.opf_xpath('//*[@id="cover"]'):
            item.set("id", newid)
        for item in container.opf_xpath('//*[@idref="cover"]'):
            item.set("idref", newid)
        raster_cover_item.set("id", "cover")

    spine = container.opf_xpath("//opf:spine")[0]
    ref = spine.makeelement(OPF("itemref"), idref=titlepage_item.get("id"))
    container.insert_into_xml(spine, ref, index=0)
    guide = container.opf_get_or_create("guide")
    container.insert_into_xml(
        guide,
        guide.makeelement(
            OPF("reference"),
            type="cover",
            title=_("Cover"),
            href=container.name_to_href(titlepage, base=container.opf_name),
        ),
    )
    metadata = container.opf_get_or_create("metadata")
    meta = metadata.makeelement(OPF("meta"), name="cover")
    meta.set("content", raster_cover_item.get("id"))
    container.insert_into_xml(metadata, meta)

    return raster_cover, titlepage
Esempio n. 35
0
def create_epub_cover(container, cover_path, existing_image, options=None):
    from calibre.ebooks.conversion.config import load_defaults
    from calibre.ebooks.oeb.transforms.cover import CoverManager

    try:
        ext = cover_path.rpartition('.')[-1].lower()
    except Exception:
        ext = 'jpeg'
    cname, tname = 'cover.' + ext, 'titlepage.xhtml'
    recommended_folders = get_recommended_folders(container, (cname, tname))

    if existing_image:
        raster_cover = existing_image
        manifest_id = {v:k for k, v in container.manifest_id_map.iteritems()}[existing_image]
        raster_cover_item = container.opf_xpath('//opf:manifest/*[@id="%s"]' % manifest_id)[0]
    else:
        folder = recommended_folders[cname]
        if folder:
            cname = folder + '/' + cname
        raster_cover_item = container.generate_item(cname, id_prefix='cover')
        raster_cover = container.href_to_name(raster_cover_item.get('href'), container.opf_name)

        with container.open(raster_cover, 'wb') as dest:
            if callable(cover_path):
                cover_path('write_image', dest)
            else:
                with lopen(cover_path, 'rb') as src:
                    shutil.copyfileobj(src, dest)
    if options is None:
        opts = load_defaults('epub_output')
        keep_aspect = opts.get('preserve_cover_aspect_ratio', False)
        no_svg = opts.get('no_svg_cover', False)
    else:
        keep_aspect = options.get('keep_aspect', False)
        no_svg = options.get('no_svg', False)
    if no_svg:
        style = 'style="height: 100%%"'
        templ = CoverManager.NONSVG_TEMPLATE.replace('__style__', style)
        has_svg = False
    else:
        if callable(cover_path):
            templ = (options or {}).get('template', CoverManager.SVG_TEMPLATE)
            has_svg = 'xlink:href' in templ
        else:
            width, height = 600, 800
            has_svg = True
            try:
                if existing_image:
                    width, height = identify(container.raw_data(existing_image, decode=False))[1:]
                else:
                    with lopen(cover_path, 'rb') as csrc:
                        width, height = identify(csrc)[1:]
            except:
                container.log.exception("Failed to get width and height of cover")
            ar = 'xMidYMid meet' if keep_aspect else 'none'
            templ = CoverManager.SVG_TEMPLATE.replace('__ar__', ar)
            templ = templ.replace('__viewbox__', '0 0 %d %d'%(width, height))
            templ = templ.replace('__width__', str(width))
            templ = templ.replace('__height__', str(height))
    folder = recommended_folders[tname]
    if folder:
        tname = folder + '/' + tname
    titlepage_item = container.generate_item(tname, id_prefix='titlepage')
    titlepage = container.href_to_name(titlepage_item.get('href'),
                                          container.opf_name)
    raw = templ%container.name_to_href(raster_cover, titlepage).encode('utf-8')
    with container.open(titlepage, 'wb') as f:
        f.write(raw)

    # We have to make sure the raster cover item has id="cover" for the moron
    # that wrote the Nook firmware
    if raster_cover_item.get('id') != 'cover':
        from calibre.ebooks.oeb.base import uuid_id
        newid = uuid_id()
        for item in container.opf_xpath('//*[@id="cover"]'):
            item.set('id', newid)
        for item in container.opf_xpath('//*[@idref="cover"]'):
            item.set('idref', newid)
        raster_cover_item.set('id', 'cover')

    spine = container.opf_xpath('//opf:spine')[0]
    ref = spine.makeelement(OPF('itemref'), idref=titlepage_item.get('id'))
    container.insert_into_xml(spine, ref, index=0)
    ver = container.opf_version_parsed
    if ver.major < 3:
        guide = container.opf_get_or_create('guide')
        container.insert_into_xml(guide, guide.makeelement(
            OPF('reference'), type='cover', title=_('Cover'),
            href=container.name_to_href(titlepage, base=container.opf_name)))
        metadata = container.opf_get_or_create('metadata')
        meta = metadata.makeelement(OPF('meta'), name='cover')
        meta.set('content', raster_cover_item.get('id'))
        container.insert_into_xml(metadata, meta)
    else:
        container.apply_unique_properties(raster_cover, 'cover-image')
        container.apply_unique_properties(titlepage, 'calibre:title-page')
        if has_svg:
            container.add_properties(titlepage, 'svg')

    return raster_cover, titlepage
Esempio n. 36
0
def render_jacket(mi):
    ps = load_defaults('page_setup')
    op = ps.get('output_profile', 'default')
    opmap = {x.short_name:x for x in output_profiles()}
    output_profile = opmap.get(op, opmap['default'])
    return render(mi, output_profile)
Esempio n. 37
0
def create_epub_cover(container, cover_path, existing_image, options=None):
    from calibre.ebooks.conversion.config import load_defaults
    from calibre.ebooks.oeb.transforms.cover import CoverManager

    try:
        ext = cover_path.rpartition('.')[-1].lower()
    except Exception:
        ext = 'jpeg'
    cname, tname = 'cover.' + ext, 'titlepage.xhtml'
    recommended_folders = get_recommended_folders(container, (cname, tname))

    if existing_image:
        raster_cover = existing_image
        manifest_id = {v: k
                       for k, v in iteritems(container.manifest_id_map)
                       }[existing_image]
        raster_cover_item = container.opf_xpath('//opf:manifest/*[@id="%s"]' %
                                                manifest_id)[0]
    else:
        folder = recommended_folders[cname]
        if folder:
            cname = folder + '/' + cname
        raster_cover_item = container.generate_item(cname, id_prefix='cover')
        raster_cover = container.href_to_name(raster_cover_item.get('href'),
                                              container.opf_name)

        with container.open(raster_cover, 'wb') as dest:
            if callable(cover_path):
                cover_path('write_image', dest)
            else:
                with lopen(cover_path, 'rb') as src:
                    shutil.copyfileobj(src, dest)
    if options is None:
        opts = load_defaults('epub_output')
        keep_aspect = opts.get('preserve_cover_aspect_ratio', False)
        no_svg = opts.get('no_svg_cover', False)
    else:
        keep_aspect = options.get('keep_aspect', False)
        no_svg = options.get('no_svg', False)
    if no_svg:
        style = 'style="height: 100%%"'
        templ = CoverManager.NONSVG_TEMPLATE.replace('__style__', style)
        has_svg = False
    else:
        if callable(cover_path):
            templ = (options or {}).get('template', CoverManager.SVG_TEMPLATE)
            has_svg = 'xlink:href' in templ
        else:
            width, height = 600, 800
            has_svg = True
            try:
                if existing_image:
                    width, height = identify(
                        container.raw_data(existing_image, decode=False))[1:]
                else:
                    with lopen(cover_path, 'rb') as csrc:
                        width, height = identify(csrc)[1:]
            except:
                container.log.exception(
                    "Failed to get width and height of cover")
            ar = 'xMidYMid meet' if keep_aspect else 'none'
            templ = CoverManager.SVG_TEMPLATE.replace('__ar__', ar)
            templ = templ.replace('__viewbox__', '0 0 %d %d' % (width, height))
            templ = templ.replace('__width__', str(width))
            templ = templ.replace('__height__', str(height))
    folder = recommended_folders[tname]
    if folder:
        tname = folder + '/' + tname
    titlepage_item = container.generate_item(tname, id_prefix='titlepage')
    titlepage = container.href_to_name(titlepage_item.get('href'),
                                       container.opf_name)
    raw = templ % container.name_to_href(raster_cover,
                                         titlepage).encode('utf-8')
    with container.open(titlepage, 'wb') as f:
        f.write(raw)

    # We have to make sure the raster cover item has id="cover" for the moron
    # that wrote the Nook firmware
    if raster_cover_item.get('id') != 'cover':
        from calibre.ebooks.oeb.base import uuid_id
        newid = uuid_id()
        for item in container.opf_xpath('//*[@id="cover"]'):
            item.set('id', newid)
        for item in container.opf_xpath('//*[@idref="cover"]'):
            item.set('idref', newid)
        raster_cover_item.set('id', 'cover')

    spine = container.opf_xpath('//opf:spine')[0]
    ref = spine.makeelement(OPF('itemref'), idref=titlepage_item.get('id'))
    container.insert_into_xml(spine, ref, index=0)
    ver = container.opf_version_parsed
    if ver.major < 3:
        guide = container.opf_get_or_create('guide')
        container.insert_into_xml(
            guide,
            guide.makeelement(OPF('reference'),
                              type='cover',
                              title=_('Cover'),
                              href=container.name_to_href(
                                  titlepage, base=container.opf_name)))
        metadata = container.opf_get_or_create('metadata')
        meta = metadata.makeelement(OPF('meta'), name='cover')
        meta.set('content', raster_cover_item.get('id'))
        container.insert_into_xml(metadata, meta)
    else:
        container.apply_unique_properties(raster_cover, 'cover-image')
        container.apply_unique_properties(titlepage, 'calibre:title-page')
        if has_svg:
            container.add_properties(titlepage, 'svg')

    return raster_cover, titlepage
Esempio n. 38
0
def generate_masthead(title, output_path=None, width=600, height=60):
    from calibre.ebooks.conversion.config import load_defaults
    recs = load_defaults('mobi_output')
    masthead_font_family = recs.get('masthead_font', None)
    from calibre.ebooks.covers import generate_masthead
    return generate_masthead(title, output_path=output_path, width=width, height=height, font_family=masthead_font_family)
Esempio n. 39
0
def render_jacket(mi):
    ps = load_defaults('page_setup')
    op = ps.get('output_profile', 'default')
    opmap = {x.short_name: x for x in output_profiles()}
    output_profile = opmap.get(op, opmap['default'])
    return render(mi, output_profile)
Esempio n. 40
0
 def set_output_profile(cls):
     if cls.output_profile:
         from calibre.ebooks.conversion.config import load_defaults, save_defaults
         recs = load_defaults('page_setup')
         recs['output_profile'] = cls.output_profile
         save_defaults('page_setup', recs)
Esempio n. 41
0
    def update(self, mi):
        mi.title = normalize(mi.title)
        def update_exth_record(rec):
            recs.append(rec)
            if rec[0] in self.original_exth_records:
                self.original_exth_records.pop(rec[0])

        if self.type != "BOOKMOBI":
                raise MobiError("Setting metadata only supported for MOBI files of type 'BOOK'.\n"
                                "\tThis is a %r file of type %r" % (self.type[0:4], self.type[4:8]))

        recs = []
        added_501 = False
        try:
            from calibre.ebooks.conversion.config import load_defaults
            prefs = load_defaults('mobi_output')
            pas = prefs.get('prefer_author_sort', False)
            kindle_pdoc = prefs.get('personal_doc', None)
            share_not_sync = prefs.get('share_not_sync', False)
        except:
            pas = False
            kindle_pdoc = None
            share_not_sync = False
        if mi.author_sort and pas:
            # We want an EXTH field per author...
            authors = mi.author_sort.split(' & ')
            for author in authors:
                update_exth_record((100, normalize(author).encode(self.codec, 'replace')))
        elif mi.authors:
            authors = mi.authors
            for author in authors:
                update_exth_record((100, normalize(author).encode(self.codec, 'replace')))
        if mi.publisher:
            update_exth_record((101, normalize(mi.publisher).encode(self.codec, 'replace')))
        if mi.comments:
            # Strip user annotations
            a_offset = mi.comments.find('<div class="user_annotations">')
            ad_offset = mi.comments.find('<hr class="annotations_divider" />')
            if a_offset >= 0:
                mi.comments = mi.comments[:a_offset]
            if ad_offset >= 0:
                mi.comments = mi.comments[:ad_offset]
            update_exth_record((103, normalize(mi.comments).encode(self.codec, 'replace')))
        if mi.isbn:
            update_exth_record((104, mi.isbn.encode(self.codec, 'replace')))
        if mi.tags:
            # FIXME: Keep a single subject per EXTH field?
            subjects = '; '.join(mi.tags)
            update_exth_record((105, normalize(subjects).encode(self.codec, 'replace')))

            if kindle_pdoc and kindle_pdoc in mi.tags:
                added_501 = True
                update_exth_record((501, b'PDOC'))

        if mi.pubdate:
            update_exth_record((106, str(mi.pubdate).encode(self.codec, 'replace')))
        elif mi.timestamp:
            update_exth_record((106, str(mi.timestamp).encode(self.codec, 'replace')))
        elif self.timestamp:
            update_exth_record((106, self.timestamp))
        else:
            update_exth_record((106, nowf().isoformat().encode(self.codec, 'replace')))
        if self.cover_record is not None:
            update_exth_record((201, pack('>I', self.cover_rindex)))
            update_exth_record((203, pack('>I', 0)))
        if self.thumbnail_record is not None:
            update_exth_record((202, pack('>I', self.thumbnail_rindex)))
        # Add a 113 record if not present to allow Amazon syncing
        if (113 not in self.original_exth_records and
                self.original_exth_records.get(501, None) == 'EBOK' and
                not added_501 and not share_not_sync):
            from uuid import uuid4
            update_exth_record((113, str(uuid4())))
        # Add a 112 record with actual UUID
        if getattr(mi, 'uuid', None):
            update_exth_record((112,
                    (u"calibre:%s" % mi.uuid).encode(self.codec, 'replace')))
        if 503 in self.original_exth_records:
            update_exth_record((503, mi.title.encode(self.codec, 'replace')))

        # Update book producer
        if getattr(mi, 'book_producer', False):
            update_exth_record((108, mi.book_producer.encode(self.codec, 'replace')))

        # Set langcode in EXTH header
        if not mi.is_null('language'):
            lang = canonicalize_lang(mi.language)
            lang = lang_as_iso639_1(lang) or lang
            if lang:
                update_exth_record((524, lang.encode(self.codec, 'replace')))

        # Include remaining original EXTH fields
        for id in sorted(self.original_exth_records):
            recs.append((id, self.original_exth_records[id]))
        recs = sorted(recs, key=lambda x:(x[0],x[0]))

        exth = StringIO()
        for code, data in recs:
            exth.write(pack('>II', code, len(data) + 8))
            exth.write(data)
        exth = exth.getvalue()
        trail = len(exth) % 4
        pad = '\0' * (4 - trail)  # Always pad w/ at least 1 byte
        exth = ['EXTH', pack('>II', len(exth) + 12, len(recs)), exth, pad]
        exth = ''.join(exth)

        if getattr(self, 'exth', None) is None:
            raise MobiError('No existing EXTH record. Cannot update metadata.')

        if not mi.is_null('language'):
            self.record0[92:96] = iana2mobi(mi.language)
        self.create_exth(exth=exth, new_title=mi.title)

        # Fetch updated timestamp, cover_record, thumbnail_record
        self.fetchEXTHFields()

        if mi.cover_data[1] or mi.cover:
            try:
                data =  mi.cover_data[1] if mi.cover_data[1] else open(mi.cover, 'rb').read()
            except:
                pass
            else:
                if is_image(self.cover_record):
                    size = len(self.cover_record)
                    cover = rescale_image(data, size)
                    if len(cover) <= size:
                        cover += b'\0' * (size - len(cover))
                        self.cover_record[:] = cover
                if is_image(self.thumbnail_record):
                    size = len(self.thumbnail_record)
                    thumbnail = rescale_image(data, size, dimen=MAX_THUMB_DIMEN)
                    if len(thumbnail) <= size:
                        thumbnail += b'\0' * (size - len(thumbnail))
                        self.thumbnail_record[:] = thumbnail
                return
Esempio n. 42
0
def create_epub_cover(container, cover_path):
    from calibre.ebooks.conversion.config import load_defaults
    from calibre.ebooks.oeb.transforms.cover import CoverManager

    ext = cover_path.rpartition(".")[-1].lower()
    raster_cover_item = container.generate_item("cover." + ext, id_prefix="cover")
    raster_cover = container.href_to_name(raster_cover_item.get("href"), container.opf_name)
    with open(cover_path, "rb") as src, container.open(raster_cover, "wb") as dest:
        shutil.copyfileobj(src, dest)
    opts = load_defaults("epub_output")
    keep_aspect = opts.get("preserve_cover_aspect_ratio", False)
    no_svg = opts.get("no_svg_cover", False)
    if no_svg:
        style = 'style="height: 100%%"'
        templ = CoverManager.NONSVG_TEMPLATE.replace("__style__", style)
    else:
        width, height = 600, 800
        try:
            width, height = identify(cover_path)[:2]
        except:
            container.log.exception("Failed to get width and height of cover")
        ar = "xMidYMid meet" if keep_aspect else "none"
        templ = CoverManager.SVG_TEMPLATE.replace("__ar__", ar)
        templ = templ.replace("__viewbox__", "0 0 %d %d" % (width, height))
        templ = templ.replace("__width__", str(width))
        templ = templ.replace("__height__", str(height))
    titlepage_item = container.generate_item("titlepage.xhtml", id_prefix="titlepage")
    titlepage = container.href_to_name(titlepage_item.get("href"), container.opf_name)
    raw = templ % container.name_to_href(raster_cover).encode("utf-8")
    with container.open(titlepage, "wb") as f:
        f.write(raw)

    # We have to make sure the raster cover item has id="cover" for the moron
    # that wrote the Nook firmware
    if raster_cover_item.get("id") != "cover":
        from calibre.ebooks.oeb.base import uuid_id

        newid = uuid_id()
        for item in container.opf_xpath('//*[@id="cover"]'):
            item.set("id", newid)
        for item in container.opf_xpath('//*[@idref="cover"]'):
            item.set("idref", newid)
        raster_cover_item.set("id", "cover")

    spine = container.opf_xpath("//opf:spine")[0]
    ref = spine.makeelement(OPF("itemref"), idref=titlepage_item.get("id"))
    container.insert_into_xml(spine, ref, index=0)
    guide = container.opf_get_or_create("guide")
    container.insert_into_xml(
        guide,
        guide.makeelement(
            OPF("reference"),
            type="cover",
            title=_("Cover"),
            href=container.name_to_href(titlepage, base=container.opf_name),
        ),
    )
    metadata = container.opf_get_or_create("metadata")
    meta = metadata.makeelement(OPF("meta"), name="cover")
    meta.set("content", raster_cover_item.get("id"))
    container.insert_into_xml(metadata, meta)

    return raster_cover, titlepage