diff --git a/src/calibre/ebooks/conversion/config.py b/src/calibre/ebooks/conversion/config.py index 1387afdecb..872171302c 100644 --- a/src/calibre/ebooks/conversion/config.py +++ b/src/calibre/ebooks/conversion/config.py @@ -8,10 +8,11 @@ __docformat__ = 'restructuredtext en' import os, ast, json -from calibre.utils.config import config_dir +from calibre.utils.config import config_dir, prefs, tweaks from calibre.utils.lock import ExclusiveFile from calibre import sanitize_file_name from calibre.customize.conversion import OptionRecommendation +from calibre.customize.ui import available_output_formats config_dir = os.path.join(config_dir, 'conversion') @@ -114,3 +115,78 @@ class GuiRecommendations(dict): self.disabled_options.add(name) elif opt.level > level or name not in self: self[name] = opt.recommended_value + + +def get_available_formats_for_book(db, book_id): + available_formats = db.new_api.formats(book_id) + return {x.lower() for x in available_formats} + + +class NoSupportedInputFormats(Exception): + + def __init__(self, available_formats): + Exception.__init__(self) + self.available_formats = available_formats + + +def get_supported_input_formats_for_book(db, book_id): + from calibre.ebooks.conversion.plumber import supported_input_formats + available_formats = get_available_formats_for_book(db, book_id) + input_formats = {x.lower() for x in supported_input_formats()} + input_formats = sorted(available_formats.intersection(input_formats)) + if not input_formats: + raise NoSupportedInputFormats(tuple(x for x in available_formats if x)) + return input_formats + + +def get_preferred_input_format_for_book(db, book_id): + recs = load_specifics(db, book_id) + if recs: + return recs.get('gui_preferred_input_format', None) + + +def sort_formats_by_preference(formats, prefs): + uprefs = [x.upper() for x in prefs] + + def key(x): + try: + return uprefs.index(x.upper()) + except ValueError: + pass + return len(prefs) + return sorted(formats, key=key) + + +def get_input_format_for_book(db, book_id, pref=None): + ''' + Return (preferred input format, list of available formats) for the book + identified by book_id. Raises an error if the book has no input formats. + + :param pref: If None, the format used as input for the last conversion, if + any, on this book is used. If not None, should be a lowercase format like + 'epub' or 'mobi'. If you do not want the last converted format to be used, + set pref=False. + ''' + if pref is None: + pref = get_preferred_input_format_for_book(db, book_id) + if hasattr(pref, 'lower'): + pref = pref.lower() + input_formats = get_supported_input_formats_for_book(db, book_id) + input_format = pref if pref in input_formats else \ + sort_formats_by_preference(input_formats, prefs['input_format_order'])[0] + return input_format, input_formats + + +def get_output_formats(preferred_output_format): + all_formats = {x.upper() for x in available_output_formats()} + all_formats.discard('OEB') + pfo = preferred_output_format.upper() if preferred_output_format else '' + restrict = tweaks['restrict_output_formats'] + if restrict: + fmts = [x.upper() for x in restrict] + if pfo and pfo not in fmts and pfo in all_formats: + fmts.append(pfo) + else: + fmts = list(sorted(all_formats, + key=lambda x:{'EPUB':'!A', 'MOBI':'!B'}.get(x.upper(), x))) + return fmts diff --git a/src/calibre/gui2/convert/bulk.py b/src/calibre/gui2/convert/bulk.py index 0aae167d4b..5ec8e2f8d4 100644 --- a/src/calibre/gui2/convert/bulk.py +++ b/src/calibre/gui2/convert/bulk.py @@ -8,8 +8,7 @@ import shutil from PyQt5.Qt import QModelIndex, QDialog -from calibre.gui2.convert.single import (Config, sort_formats_by_preference, - GroupModel, gprefs, get_output_formats) +from calibre.gui2.convert.single import Config, GroupModel, gprefs from calibre.gui2.convert.look_and_feel import LookAndFeelWidget from calibre.gui2.convert.heuristics import HeuristicsWidget from calibre.gui2.convert.search_and_replace import SearchAndReplaceWidget @@ -18,6 +17,7 @@ from calibre.gui2.convert.structure_detection import StructureDetectionWidget from calibre.gui2.convert.toc import TOCWidget from calibre.gui2.convert import GuiRecommendations from calibre.ebooks.conversion.plumber import Plumber +from calibre.ebooks.conversion.config import sort_formats_by_preference, get_output_formats from calibre.utils.config import prefs from calibre.utils.logging import Log diff --git a/src/calibre/gui2/convert/single.py b/src/calibre/gui2/convert/single.py index 269bfcec79..a96ddd31ef 100644 --- a/src/calibre/gui2/convert/single.py +++ b/src/calibre/gui2/convert/single.py @@ -11,8 +11,8 @@ import cPickle, shutil from PyQt5.Qt import QAbstractListModel, Qt, QFont, QModelIndex, QDialog, QCoreApplication, QSize from calibre.gui2 import gprefs -from calibre.ebooks.conversion.config import (GuiRecommendations, save_specifics, - load_specifics) +from calibre.ebooks.conversion.config import ( + GuiRecommendations, save_specifics, sort_formats_by_preference, get_input_format_for_book, get_output_formats) from calibre.gui2.convert.single_ui import Ui_Dialog from calibre.gui2.convert.metadata import MetadataWidget from calibre.gui2.convert.look_and_feel import LookAndFeelWidget @@ -24,49 +24,13 @@ from calibre.gui2.convert.toc import TOCWidget from calibre.gui2.convert.debug import DebugWidget -from calibre.ebooks.conversion.plumber import (Plumber, - supported_input_formats, ARCHIVE_FMTS) +from calibre.ebooks.conversion.plumber import (Plumber, ARCHIVE_FMTS) from calibre.ebooks.conversion.config import delete_specifics -from calibre.customize.ui import available_output_formats from calibre.customize.conversion import OptionRecommendation -from calibre.utils.config import prefs, tweaks +from calibre.utils.config import prefs from calibre.utils.logging import Log -class NoSupportedInputFormats(Exception): - - def __init__(self, available_formats): - Exception.__init__(self) - self.available_formats = available_formats - - -def sort_formats_by_preference(formats, prefs): - uprefs = [x.upper() for x in prefs] - - def key(x): - try: - return uprefs.index(x.upper()) - except ValueError: - pass - return len(prefs) - return sorted(formats, key=key) - - -def get_output_formats(preferred_output_format): - all_formats = {x.upper() for x in available_output_formats()} - all_formats.discard('OEB') - pfo = preferred_output_format.upper() if preferred_output_format else '' - restrict = tweaks['restrict_output_formats'] - if restrict: - fmts = [x.upper() for x in restrict] - if pfo and pfo not in fmts and pfo in all_formats: - fmts.append(pfo) - else: - fmts = list(sorted(all_formats, - key=lambda x:{'EPUB':'!A', 'MOBI':'!B'}.get(x.upper(), x))) - return fmts - - class GroupModel(QAbstractListModel): def __init__(self, widgets): @@ -92,49 +56,6 @@ class GroupModel(QAbstractListModel): return None -def get_preferred_input_format_for_book(db, book_id): - recs = load_specifics(db, book_id) - if recs: - return recs.get('gui_preferred_input_format', None) - - -def get_available_formats_for_book(db, book_id): - available_formats = db.formats(book_id, index_is_id=True) - if not available_formats: - available_formats = '' - return set([x.lower() for x in - available_formats.split(',')]) - - -def get_supported_input_formats_for_book(db, book_id): - available_formats = get_available_formats_for_book(db, book_id) - input_formats = set([x.lower() for x in supported_input_formats()]) - input_formats = sorted(available_formats.intersection(input_formats)) - if not input_formats: - raise NoSupportedInputFormats(tuple(x for x in available_formats if x)) - return input_formats - - -def get_input_format_for_book(db, book_id, pref): - ''' - Return (preferred input format, list of available formats) for the book - identified by book_id. Raises an error if the book has no input formats. - - :param pref: If None, the format used as input for the last conversion, if - any, on this book is used. If not None, should be a lowercase format like - 'epub' or 'mobi'. If you do not want the last converted format to be used, - set pref=False. - ''' - if pref is None: - pref = get_preferred_input_format_for_book(db, book_id) - if hasattr(pref, 'lower'): - pref = pref.lower() - input_formats = get_supported_input_formats_for_book(db, book_id) - input_format = pref if pref in input_formats else \ - sort_formats_by_preference(input_formats, prefs['input_format_order'])[0] - return input_format, input_formats - - class Config(QDialog, Ui_Dialog): ''' Configuration dialog for single book conversion. If accepted, has the diff --git a/src/calibre/gui2/tools.py b/src/calibre/gui2/tools.py index 471fcb845a..45b9152bb8 100644 --- a/src/calibre/gui2/tools.py +++ b/src/calibre/gui2/tools.py @@ -13,15 +13,14 @@ from PyQt5.Qt import QDialog, QProgressDialog, QTimer from calibre.ptempfile import PersistentTemporaryFile from calibre.gui2 import warning_dialog, question_dialog -from calibre.gui2.convert.single import NoSupportedInputFormats -from calibre.gui2.convert.single import Config as SingleConfig, \ - get_input_format_for_book +from calibre.gui2.convert.single import Config as SingleConfig from calibre.gui2.convert.bulk import BulkConfig from calibre.gui2.convert.metadata import create_opf_file, create_cover_file from calibre.customize.conversion import OptionRecommendation from calibre.utils.config import prefs -from calibre.ebooks.conversion.config import GuiRecommendations, \ - load_defaults, load_specifics, save_specifics +from calibre.ebooks.conversion.config import ( + GuiRecommendations, load_defaults, load_specifics, save_specifics, + get_input_format_for_book, NoSupportedInputFormats) from calibre.gui2.convert import bulk_defaults_for_input_format @@ -100,12 +99,12 @@ def convert_single_ebook(parent, db, book_ids, auto_conversion=False, # {{{ if bad and show_no_format_warning: if len(bad) == 1 and not bad[0][1]: title = db.title(bad[0][0], True) - warning_dialog(parent, _('Could not convert'), '

'+ - _('Could not convert %s as it has no e-book files. If you ' - 'think it should have files, but calibre is not finding ' - 'them, that is most likely because you moved the book\'s ' - 'files around outside of calibre. You will need to find those files ' - 'and re-add them to calibre.')%title, show=True) + warning_dialog(parent, _('Could not convert'), '

'+ _( + 'Could not convert %s as it has no e-book files. If you ' + 'think it should have files, but calibre is not finding ' + 'them, that is most likely because you moved the book\'s ' + 'files around outside of calibre. You will need to find those files ' + 'and re-add them to calibre.')%title, show=True) else: res = [] for id, available_formats in bad: