コード例 #1
0
ファイル: cdb.py プロジェクト: JimmXinu/calibre
def cdb_add_book(ctx, rd, job_id, add_duplicates, filename, library_id):
    '''
    Add a file as a new book. The file contents must be in the body of the request.

    The response will also have the title/authors/languages read from the
    metadata of the file/filename. It will contain a `book_id` field specifying the id of the newly added book,
    or if add_duplicates is not specified and a duplicate was found, no book_id will be present. It will also
    return the value of `job_id` as the `id` field and `filename` as the `filename` field.
    '''
    db = get_db(ctx, rd, library_id)
    if ctx.restriction_for(rd, db):
        raise HTTPForbidden('Cannot use the add book interface with a user who has per library restrictions')
    if not filename:
        raise HTTPBadRequest('An empty filename is not allowed')
    sfilename = sanitize_file_name(filename)
    fmt = os.path.splitext(sfilename)[1]
    fmt = fmt[1:] if fmt else None
    if not fmt:
        raise HTTPBadRequest('An filename with no extension is not allowed')
    if isinstance(rd.request_body_file, BytesIO):
        raise HTTPBadRequest('A request body containing the file data must be specified')
    add_duplicates = add_duplicates in ('y', '1')
    path = os.path.join(rd.tdir, sfilename)
    rd.request_body_file.name = path
    rd.request_body_file.seek(0)
    mi = get_metadata(rd.request_body_file, stream_type=fmt, use_libprs_metadata=True)
    rd.request_body_file.seek(0)
    ids, duplicates = db.add_books([(mi, {fmt: rd.request_body_file})], add_duplicates=add_duplicates)
    ans = {'title': mi.title, 'authors': mi.authors, 'languages': mi.languages, 'filename': filename, 'id': job_id}
    if ids:
        ans['book_id'] = ids[0]
        ctx.notify_changes(db.backend.library_path, books_added(ids))
    return ans
コード例 #2
0
ファイル: filenames.py プロジェクト: Pipeliner/calibre
def ascii_filename(orig, substitute='_'):
    ans = []
    orig = ascii_text(orig).replace('?', '_')
    for x in orig:
        if ord(x) < 32:
            x = substitute
        ans.append(x)
    return sanitize_file_name(''.join(ans), substitute=substitute)
コード例 #3
0
ファイル: content.py プロジェクト: JimmXinu/calibre
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
コード例 #4
0
ファイル: file_list.py プロジェクト: JimmXinu/calibre
def name_is_ok(name, show_error):
    if not name or not name.strip():
        return show_error('') and False
    ext = name.rpartition('.')[-1]
    if not ext or ext == name:
        return show_error(_('The file name must have an extension')) and False
    norm = name.replace('\\', '/')
    parts = name.split('/')
    for x in parts:
        if sanitize_file_name(x) != x:
            return show_error(_('The file name contains invalid characters')) and False
    if current_container().has_name(norm):
        return show_error(_('This file name already exists in the book')) and False
    show_error('')
    return True
コード例 #5
0
ファイル: printing.py プロジェクト: JimmXinu/calibre
 def data(self):
     fpath = self.file_name.text().strip()
     head, tail = os.path.split(fpath)
     tail = sanitize_file_name(tail)
     fpath = tail
     if head:
         fpath = os.path.join(head, tail)
     ans = {
         'output': fpath,
         'paper_size': self.paper_size.currentText().lower(),
         'page_numbers':self.pnum.isChecked(),
         'show_file':self.show_file.isChecked(),
     }
     for edge in 'left top right bottom'.split():
         ans['margin_' + edge] = getattr(self, '%s_margin' % edge).value()
     return ans
コード例 #6
0
ファイル: choose_library.py プロジェクト: JimmXinu/calibre
 def rename_requested(self, name, location):
     LibraryDatabase = db_class()
     loc = location.replace('/', os.sep)
     base = os.path.dirname(loc)
     old_name = name.replace('&&', '&')
     newname, ok = QInputDialog.getText(self.gui, _('Rename') + ' ' + old_name,
             '<p>'+_(
                 'Choose a new name for the library <b>%s</b>. ')%name + '<p>'+_(
                 'Note that the actual library folder will be renamed.'),
             text=old_name)
     newname = sanitize_file_name(unicode_type(newname))
     if not ok or not newname or newname == old_name:
         return
     newloc = os.path.join(base, newname)
     if os.path.exists(newloc):
         return error_dialog(self.gui, _('Already exists'),
                 _('The folder %s already exists. Delete it first.') %
                 newloc, show=True)
     if (iswindows and len(newloc) > LibraryDatabase.WINDOWS_LIBRARY_PATH_LIMIT):
         return error_dialog(self.gui, _('Too long'),
                 _('Path to library too long. Must be less than'
                 ' %d characters.')%LibraryDatabase.WINDOWS_LIBRARY_PATH_LIMIT,
                 show=True)
     if not os.path.exists(loc):
         error_dialog(self.gui, _('Not found'),
                 _('Cannot rename as no library was found at %s. '
                   'Try switching to this library first, then switch back '
                   'and retry the renaming.')%loc, show=True)
         return
     self.gui.library_broker.remove_library(loc)
     try:
         os.rename(loc, newloc)
     except:
         import traceback
         det_msg = 'Location: %r New Location: %r\n%s'%(loc, newloc,
                                                     traceback.format_exc())
         error_dialog(self.gui, _('Rename failed'),
                 _('Failed to rename the library at %s. '
             'The most common cause for this is if one of the files'
             ' in the library is open in another program.') % loc,
                 det_msg=det_msg, show=True)
         return
     self.stats.rename(location, newloc)
     self.build_menus()
     self.gui.iactions['Copy To Library'].build_menus()
コード例 #7
0
ファイル: catalog.py プロジェクト: JimmXinu/calibre
    def catalog_generated(self, job):
        if job.result:
            # Problems during catalog generation
            # jobs.results is a list - the first entry is the intended title for the dialog
            # Subsequent strings are error messages
            dialog_title = job.result.pop(0)
            if re.search('warning', job.result[0].lower()):
                msg = _("Catalog generation complete, with warnings.")
                warning_dialog(self.gui, dialog_title, msg, det_msg='\n'.join(job.result), show=True)
            else:
                job.result.append("Catalog generation terminated.")
                error_dialog(self.gui, dialog_title,'\n'.join(job.result),show=True)
                return

        if job.failed:
            return self.gui.job_exception(job)
        if dynamic.get('catalog_add_to_library', True):
            id = self.gui.library_view.model().add_catalog(job.catalog_file_path, job.catalog_title)
            self.gui.library_view.model().beginResetModel(), self.gui.library_view.model().endResetModel()
            if job.catalog_sync:
                sync = dynamic.get('catalogs_to_be_synced', set([]))
                sync.add(id)
                dynamic.set('catalogs_to_be_synced', sync)
        self.gui.status_bar.show_message(_('Catalog generated.'), 3000)
        self.gui.sync_catalogs()
        if not dynamic.get('catalog_add_to_library', True) or job.fmt not in {'EPUB','MOBI', 'AZW3'}:
            export_dir = choose_dir(self.gui, _('Export Catalog Directory'),
                    _('Select destination for %(title)s.%(fmt)s') % dict(
                        title=job.catalog_title, fmt=job.fmt.lower()))
            if export_dir:
                destination = os.path.join(export_dir, '%s.%s' % (
                    sanitize_file_name(job.catalog_title), job.fmt.lower()))
                try:
                    shutil.copyfile(job.catalog_file_path, destination)
                except EnvironmentError as err:
                    if getattr(err, 'errno', None) == errno.EACCES:  # Permission denied
                        import traceback
                        error_dialog(self.gui, _('Permission denied'),
                                _('Could not open %s. Is it being used by another'
                                ' program?')%destination, det_msg=traceback.format_exc(),
                                show=True)
                        return
                    raise
コード例 #8
0
    def prepare_addable_books(self, paths):
        """
        Given a list of paths, returns another list of paths. These paths
        point to addable versions of the books.

        If there is an error preparing a book, then instead of a path, the
        position in the returned list for that book should be a three tuple:
        (original_path, the exception instance, traceback)
        Modeled on calibre.devices.mtp.driver:prepare_addable_books() #304
        """
        from calibre import sanitize_file_name
        from calibre.ptempfile import PersistentTemporaryDirectory

        self._log_location()
        tdir = PersistentTemporaryDirectory("_prep_gr")
        ans = []
        for path in paths:
            if not self.ios.exists("/".join([self.documents_folder, path])):
                ans.append((path, "File not found", "File not found"))
                continue

            base = tdir
            if iswindows:
                from calibre.utils.filenames import shorten_components_to

                plen = len(base)
                bfn = path.split("/")[-1]
                dest = "".join(shorten_components_to(245 - plen, [bfn]))
            else:
                dest = path

            out_path = os.path.normpath(os.path.join(base, sanitize_file_name(dest)))
            with open(out_path, "wb") as out:
                try:
                    self.get_file(path, out)
                except Exception as e:
                    import traceback

                    ans.append((dest, e, traceback.format_exc()))
                else:
                    ans.append(out.name)

        return ans
コード例 #9
0
ファイル: replace.py プロジェクト: j-howell/calibre
def replace_file(container, name, path, basename, force_mt=None):
    dirname, base = name.rpartition('/')[0::2]
    nname = sanitize_file_name(basename)
    if dirname:
        nname = dirname + '/' + nname
    with open(path, 'rb') as src:
        if name != nname:
            count = 0
            b, e = nname.rpartition('.')[0::2]
            while container.exists(nname):
                count += 1
                nname = b + ('_%d.%s' % (count, e))
            rename_files(container, {name:nname})
            mt = force_mt or container.guess_type(nname)
            container.mime_map[nname] = mt
            for itemid, q in iteritems(container.manifest_id_map):
                if q == nname:
                    for item in container.opf_xpath('//opf:manifest/opf:item[@href and @id="%s"]' % itemid):
                        item.set('media-type', mt)
        container.dirty(container.opf_name)
        with container.open(nname, 'wb') as dest:
            shutil.copyfileobj(src, dest)
コード例 #10
0
ファイル: config.py プロジェクト: j-howell/calibre
def name_to_path(name):
    return os.path.join(config_dir, sanitize_file_name(name)+'.py')
コード例 #11
0
ファイル: test.py プロジェクト: JimmXinu/calibre
def test_identify_plugin(name, tests, modify_plugin=lambda plugin:None,  # {{{
        fail_missing_meta=True):
    '''
    :param name: Plugin name
    :param tests: List of 2-tuples. Each two tuple is of the form (args,
                  test_funcs). args is a dict of keyword arguments to pass to
                  the identify method. test_funcs are callables that accept a
                  Metadata object and return True iff the object passes the
                  test.
    '''
    plugin = None
    for x in all_metadata_plugins():
        if x.name == name and 'identify' in x.capabilities:
            plugin = x
            break
    modify_plugin(plugin)
    prints('Testing the identify function of', plugin.name)
    prints('Using extra headers:', plugin.browser.addheaders)

    tdir, lf, log, abort = init_test(plugin.name)
    prints('Log saved to', lf)

    times = []
    for kwargs, test_funcs in tests:
        log('')
        log('#'*80)
        log('### Running test with:', kwargs)
        log('#'*80)
        prints('Running test with:', kwargs)
        rq = Queue()
        args = (log, rq, abort)
        start_time = time.time()
        plugin.running_a_test = True
        try:
            err = plugin.identify(*args, **kwargs)
        finally:
            plugin.running_a_test = False
        total_time = time.time() - start_time
        times.append(total_time)
        if err is not None:
            prints('identify returned an error for args', args)
            prints(err)
            break

        results = []
        while True:
            try:
                results.append(rq.get_nowait())
            except Empty:
                break

        prints('Found', len(results), 'matches:', end=' ')
        prints('Smaller relevance means better match')

        results.sort(key=plugin.identify_results_keygen(
            title=kwargs.get('title', None), authors=kwargs.get('authors',
                None), identifiers=kwargs.get('identifiers', {})))

        for i, mi in enumerate(results):
            prints('*'*30, 'Relevance:', i, '*'*30)
            if mi.rating:
                mi.rating *= 2
            prints(mi)
            prints('\nCached cover URL    :',
                    plugin.get_cached_cover_url(mi.identifiers))
            prints('*'*75, '\n\n')

        possibles = []
        for mi in results:
            test_failed = False
            for tfunc in test_funcs:
                if not tfunc(mi):
                    test_failed = True
                    break
            if not test_failed:
                possibles.append(mi)

        if not possibles:
            prints('ERROR: No results that passed all tests were found')
            prints('Log saved to', lf)
            log.close()
            dump_log(lf)
            raise SystemExit(1)

        good = [x for x in possibles if plugin.test_fields(x) is
                None]
        if not good:
            prints('Failed to find', plugin.test_fields(possibles[0]))
            if fail_missing_meta:
                raise SystemExit(1)

        if results[0] is not possibles[0]:
            prints('Most relevant result failed the tests')
            raise SystemExit(1)

        if 'cover' in plugin.capabilities:
            rq = Queue()
            mi = results[0]
            plugin.download_cover(log, rq, abort, title=mi.title,
                    authors=mi.authors, identifiers=mi.identifiers)
            results = []
            while True:
                try:
                    results.append(rq.get_nowait())
                except Empty:
                    break
            if not results and fail_missing_meta:
                prints('Cover download failed')
                raise SystemExit(1)
            elif results:
                cdata = results[0]
                cover = os.path.join(tdir, plugin.name.replace(' ',
                    '')+'-%s-cover.jpg'%sanitize_file_name(mi.title.replace(' ',
                        '_')))
                with open(cover, 'wb') as f:
                    f.write(cdata[-1])

                prints('Cover downloaded to:', cover)

                if len(cdata[-1]) < 10240:
                    prints('Downloaded cover too small')
                    raise SystemExit(1)

    prints('Average time per query', sum(times)/len(times))

    if os.stat(lf).st_size > 10:
        prints('There were some errors/warnings, see log', lf)
コード例 #12
0
ファイル: printing.py プロジェクト: JimmXinu/calibre
 def __init__(self, book_title, parent=None, prefs=vprefs):
     self.book_title = book_title
     self.default_file_name = sanitize_file_name(book_title[:75] + '.pdf')
     self.paper_size_map = {a:getattr(QPageSize, a.capitalize()) for a in PAPER_SIZES}
     Dialog.__init__(self, _('Print to PDF'), 'print-to-pdf', prefs=prefs, parent=parent)
コード例 #13
0
ファイル: config.py プロジェクト: tpanthera/calibre
def name_to_path(name):
    return os.path.join(config_dir, sanitize_file_name(name) + '.py')
コード例 #14
0
ファイル: coloring.py プロジェクト: JimmXinu/calibre
 def sanitize_icon_file_name(self, icon_path):
     n = lower(sanitize_file_name(
                          os.path.splitext(
                                os.path.basename(icon_path))[0]+'.png'))
     return n.replace("'", '_')
コード例 #15
0
def image_filename(x):
    return sanitize_file_name(
        re.sub(r'[^0-9a-zA-Z.-]', '_',
               ascii_filename(x)).lstrip('_').lstrip('.'))
コード例 #16
0
ファイル: filenames.py プロジェクト: smdx023/calibre
def ascii_filename(orig, substitute='_'):
    if isinstance(substitute, bytes):
        substitute = substitute.decode(filesystem_encoding)
    orig = ascii_text(orig).replace('?', '_')
    ans = ''.join(x if ord(x) >= 32 else substitute for x in orig)
    return sanitize_file_name(ans, substitute=substitute)
コード例 #17
0
 def sanitize_icon_file_name(self, icon_path):
     n = lower(sanitize_file_name(
                          os.path.splitext(
                                os.path.basename(icon_path))[0]+'.png'))
     return n.replace("'", '_')
コード例 #18
0
ファイル: choose_library.py プロジェクト: qykth-git/calibre
def library_icon_path(lib_name=''):
    return os.path.join(
        config_dir, 'library_icons',
        sanitize_file_name(lib_name or current_library_name()) + '.png')
コード例 #19
0
def test_identify_plugin(
        name,
        tests,
        modify_plugin=lambda plugin: None,  # {{{
        fail_missing_meta=True):
    '''
    :param name: Plugin name
    :param tests: List of 2-tuples. Each two tuple is of the form (args,
                  test_funcs). args is a dict of keyword arguments to pass to
                  the identify method. test_funcs are callables that accept a
                  Metadata object and return True iff the object passes the
                  test.
    '''
    plugin = None
    for x in all_metadata_plugins():
        if x.name == name and 'identify' in x.capabilities:
            plugin = x
            break
    modify_plugin(plugin)
    prints('Testing the identify function of', plugin.name)
    prints('Using extra headers:', plugin.browser.addheaders)

    tdir, lf, log, abort = init_test(plugin.name)
    prints('Log saved to', lf)

    times = []
    for kwargs, test_funcs in tests:
        log('')
        log('#' * 80)
        log('### Running test with:', kwargs)
        log('#' * 80)
        prints('Running test with:', kwargs)
        rq = Queue()
        args = (log, rq, abort)
        start_time = time.time()
        plugin.running_a_test = True
        try:
            err = plugin.identify(*args, **kwargs)
        finally:
            plugin.running_a_test = False
        total_time = time.time() - start_time
        times.append(total_time)
        if err is not None:
            prints('identify returned an error for args', args)
            prints(err)
            break

        results = []
        while True:
            try:
                results.append(rq.get_nowait())
            except Empty:
                break

        prints('Found', len(results), 'matches:', end=' ')
        prints('Smaller relevance means better match')

        results.sort(key=plugin.identify_results_keygen(
            title=kwargs.get('title', None),
            authors=kwargs.get('authors', None),
            identifiers=kwargs.get('identifiers', {})))

        for i, mi in enumerate(results):
            prints('*' * 30, 'Relevance:', i, '*' * 30)
            if mi.rating:
                mi.rating *= 2
            prints(mi)
            prints('\nCached cover URL    :',
                   plugin.get_cached_cover_url(mi.identifiers))
            prints('*' * 75, '\n\n')

        possibles = []
        for mi in results:
            test_failed = False
            for tfunc in test_funcs:
                if not tfunc(mi):
                    test_failed = True
                    break
            if not test_failed:
                possibles.append(mi)

        if not possibles:
            prints('ERROR: No results that passed all tests were found')
            prints('Log saved to', lf)
            log.close()
            dump_log(lf)
            raise SystemExit(1)

        good = [x for x in possibles if plugin.test_fields(x) is None]
        if not good:
            prints('Failed to find', plugin.test_fields(possibles[0]))
            if fail_missing_meta:
                raise SystemExit(1)

        if results[0] is not possibles[0]:
            prints('Most relevant result failed the tests')
            raise SystemExit(1)

        if 'cover' in plugin.capabilities:
            rq = Queue()
            mi = results[0]
            plugin.download_cover(log,
                                  rq,
                                  abort,
                                  title=mi.title,
                                  authors=mi.authors,
                                  identifiers=mi.identifiers)
            results = []
            while True:
                try:
                    results.append(rq.get_nowait())
                except Empty:
                    break
            if not results and fail_missing_meta:
                prints('Cover download failed')
                raise SystemExit(1)
            elif results:
                cdata = results[0]
                cover = os.path.join(
                    tdir,
                    plugin.name.replace(' ', '') + '-%s-cover.jpg' %
                    sanitize_file_name(mi.title.replace(' ', '_')))
                with open(cover, 'wb') as f:
                    f.write(cdata[-1])

                prints('Cover downloaded to:', cover)

                if len(cdata[-1]) < 10240:
                    prints('Downloaded cover too small')
                    raise SystemExit(1)

    prints('Average time per query', sum(times) / len(times))

    if os.stat(lf).st_size > 10:
        prints('There were some errors/warnings, see log', lf)
コード例 #20
0
ファイル: filenames.py プロジェクト: JimmXinu/calibre
def ascii_filename(orig, substitute='_'):
    if isinstance(substitute, bytes):
        substitute = substitute.decode(filesystem_encoding)
    orig = ascii_text(orig).replace('?', '_')
    ans = ''.join(x if ord(x) >= 32 else substitute for x in orig)
    return sanitize_file_name(ans, substitute=substitute)
コード例 #21
0
    def context_menu_handler(self, action=None, category=None,
                             key=None, index=None, search_state=None,
                             use_vl=None):
        if not action:
            return
        try:
            if action == 'set_icon':
                try:
                    path = choose_files(self, 'choose_category_icon',
                                _('Change icon for: %s')%key, filters=[
                                ('Images', ['png', 'gif', 'jpg', 'jpeg'])],
                            all_files=False, select_only_single_file=True)
                    if path:
                        path = path[0]
                        p = QIcon(path).pixmap(QSize(128, 128))
                        d = os.path.join(config_dir, 'tb_icons')
                        if not os.path.exists(d):
                            os.makedirs(d)
                        with open(os.path.join(d, 'icon_' + sanitize_file_name(key)+'.png'), 'wb') as f:
                            f.write(pixmap_to_data(p, format='PNG'))
                            path = os.path.basename(f.name)
                        self._model.set_custom_category_icon(key, unicode_type(path))
                        self.recount()
                except:
                    import traceback
                    traceback.print_exc()
                return
            if action == 'clear_icon':
                self._model.set_custom_category_icon(key, None)
                self.recount()
                return

            if action == 'edit_item_no_vl':
                item = self.model().get_node(index)
                item.use_vl = False
                self.edit(index)
                return
            if action == 'edit_item_in_vl':
                item = self.model().get_node(index)
                item.use_vl = True
                self.edit(index)
                return
            if action == 'delete_item_in_vl':
                self.tag_item_delete.emit(key, index.id, index.original_name,
                                          self.model().get_book_ids_to_use())
                return
            if action == 'delete_item_no_vl':
                self.tag_item_delete.emit(key, index.id, index.original_name, None)
                return
            if action == 'open_editor':
                self.tags_list_edit.emit(category, key)
                return
            if action == 'manage_categories':
                self.edit_user_category.emit(category)
                return
            if action == 'search':
                self._toggle(index, set_to=search_state)
                return
            if action == "raw_search":
                from calibre.gui2.ui import get_gui
                get_gui().get_saved_search_text(search_name='search:' + key)
                return
            if action == 'add_to_category':
                tag = index.tag
                if len(index.children) > 0:
                    for c in index.all_children():
                        self.add_item_to_user_cat.emit(category, c.tag.original_name,
                                               c.tag.category)
                self.add_item_to_user_cat.emit(category, tag.original_name,
                                               tag.category)
                return
            if action == 'add_subcategory':
                self.add_subcategory.emit(key)
                return
            if action == 'search_category':
                self._toggle(index, set_to=search_state)
                return
            if action == 'delete_user_category':
                self.delete_user_category.emit(key)
                return
            if action == 'delete_search':
                self.model().db.saved_search_delete(key)
                self.rebuild_saved_searches.emit()
                return
            if action == 'delete_item_from_user_category':
                tag = index.tag
                if len(index.children) > 0:
                    for c in index.children:
                        self.del_item_from_user_cat.emit(key, c.tag.original_name,
                                               c.tag.category)
                self.del_item_from_user_cat.emit(key, tag.original_name, tag.category)
                return
            if action == 'manage_searches':
                self.saved_search_edit.emit(category)
                return
            if action == 'edit_author_sort':
                self.author_sort_edit.emit(self, index, True, False)
                return
            if action == 'edit_author_link':
                self.author_sort_edit.emit(self, index, False, True)
                return

            reset_filter_categories = True
            if action == 'hide':
                self.hidden_categories.add(category)
            elif action == 'show':
                self.hidden_categories.discard(category)
            elif action == 'categorization':
                changed = self.collapse_model != category
                self._model.collapse_model = category
                if changed:
                    reset_filter_categories = False
                    gprefs['tags_browser_partition_method'] = category
            elif action == 'defaults':
                self.hidden_categories.clear()
            self.db.new_api.set_pref('tag_browser_hidden_categories', list(self.hidden_categories))
            if reset_filter_categories:
                self._model.set_categories_filter(None)
            self._model.rebuild_node_tree()
        except:
            return
コード例 #22
0
    def catalog_generated(self, job):
        if job.result:
            # Problems during catalog generation
            # jobs.results is a list - the first entry is the intended title for the dialog
            # Subsequent strings are error messages
            dialog_title = job.result.pop(0)
            if re.search('warning', job.result[0].lower()):
                msg = _("Catalog generation complete, with warnings.")
                warning_dialog(self.gui,
                               dialog_title,
                               msg,
                               det_msg='\n'.join(job.result),
                               show=True)
            else:
                job.result.append("Catalog generation terminated.")
                error_dialog(self.gui,
                             dialog_title,
                             '\n'.join(job.result),
                             show=True)
                return

        if job.failed:
            return self.gui.job_exception(job)
        if dynamic.get('catalog_add_to_library', True):
            id = self.gui.library_view.model().add_catalog(
                job.catalog_file_path, job.catalog_title)
            self.gui.library_view.model().beginResetModel(
            ), self.gui.library_view.model().endResetModel()
            if job.catalog_sync:
                sync = dynamic.get('catalogs_to_be_synced', set())
                sync.add(id)
                dynamic.set('catalogs_to_be_synced', sync)
        self.gui.status_bar.show_message(_('Catalog generated.'), 3000)
        self.gui.sync_catalogs()
        if not dynamic.get('catalog_add_to_library', True) or job.fmt not in {
                'EPUB', 'MOBI', 'AZW3'
        }:
            export_dir = choose_dir(
                self.gui, _('Export catalog folder'),
                _('Select destination for %(title)s.%(fmt)s') %
                dict(title=job.catalog_title, fmt=job.fmt.lower()))
            if export_dir:
                destination = os.path.join(
                    export_dir,
                    '{}.{}'.format(sanitize_file_name(job.catalog_title),
                                   job.fmt.lower()))
                try:
                    shutil.copyfile(job.catalog_file_path, destination)
                except OSError as err:
                    if getattr(err, 'errno',
                               None) == errno.EACCES:  # Permission denied
                        import traceback
                        error_dialog(
                            self.gui,
                            _('Permission denied'),
                            _('Could not open %s. Is it being used by another'
                              ' program?') % destination,
                            det_msg=traceback.format_exc(),
                            show=True)
                        return
                    raise
コード例 #23
0
 def __init__(self, book_title, parent=None, prefs=vprefs):
     self.book_title = book_title
     self.default_file_name = sanitize_file_name(book_title[:75] + '.pdf')
     self.paper_size_map = {a:getattr(QPageSize, a.capitalize()) for a in PAPER_SIZES}
     Dialog.__init__(self, _('Print to PDF'), 'print-to-pdf', prefs=prefs, parent=parent)