mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Auto convert in GUI working
This commit is contained in:
parent
a60cd4c567
commit
c1a37749a6
@ -577,7 +577,7 @@ class DeviceGUI(object):
|
|||||||
|
|
||||||
|
|
||||||
def sync_to_device(self, on_card, delete_from_library,
|
def sync_to_device(self, on_card, delete_from_library,
|
||||||
specific_format=None, send_rows=None, auto_convert=True):
|
specific_format=None, send_rows=None, do_auto_convert=True):
|
||||||
rows = self.library_view.selectionModel().selectedRows() if send_rows is None else send_rows
|
rows = self.library_view.selectionModel().selectedRows() if send_rows is None else send_rows
|
||||||
if not self.device_manager or not rows or len(rows) == 0:
|
if not self.device_manager or not rows or len(rows) == 0:
|
||||||
return
|
return
|
||||||
@ -585,8 +585,12 @@ class DeviceGUI(object):
|
|||||||
_files, _auto_rows = self.library_view.model().get_preferred_formats(rows,
|
_files, _auto_rows = self.library_view.model().get_preferred_formats(rows,
|
||||||
self.device_manager.device_class.FORMATS,
|
self.device_manager.device_class.FORMATS,
|
||||||
paths=True, set_metadata=True,
|
paths=True, set_metadata=True,
|
||||||
specific_format=specific_format)
|
specific_format=specific_format,
|
||||||
rows = list(set(rows).difference(_auto_rows))
|
exclude_auto=do_auto_convert)
|
||||||
|
if do_auto_convert:
|
||||||
|
rows = list(set(rows).difference(_auto_rows))
|
||||||
|
else:
|
||||||
|
_auto_rows = []
|
||||||
|
|
||||||
ids = iter(self.library_view.model().id(r) for r in rows)
|
ids = iter(self.library_view.model().id(r) for r in rows)
|
||||||
metadata = self.library_view.model().get_metadata(rows)
|
metadata = self.library_view.model().get_metadata(rows)
|
||||||
@ -626,9 +630,9 @@ class DeviceGUI(object):
|
|||||||
if _auto_rows != []:
|
if _auto_rows != []:
|
||||||
for row in _auto_rows:
|
for row in _auto_rows:
|
||||||
if specific_format == None:
|
if specific_format == None:
|
||||||
formats = self.library_view.model().db.formats(row).split(',')
|
formats = [f.lower() for f in self.library_view.model().db.formats(row).split(',')]
|
||||||
formats = formats if formats != None else []
|
formats = formats if formats != None else []
|
||||||
if set(formats).intersection(available_input_formats()) is not None and set(self.device_manager.device_class.FORMATS).intersection(available_output_formats()) is not None:
|
if list(set(formats).intersection(available_input_formats())) != [] and list(set(self.device_manager.device_class.FORMATS).intersection(available_output_formats())) != []:
|
||||||
auto.append(row)
|
auto.append(row)
|
||||||
else:
|
else:
|
||||||
bad.append(self.library_view.model().title(row))
|
bad.append(self.library_view.model().title(row))
|
||||||
@ -646,10 +650,10 @@ class DeviceGUI(object):
|
|||||||
for fmt in self.device_manager.device_class.FORMATS:
|
for fmt in self.device_manager.device_class.FORMATS:
|
||||||
if fmt in list(set(self.device_manager.device_class.FORMATS).intersection(set(available_output_formats()))):
|
if fmt in list(set(self.device_manager.device_class.FORMATS).intersection(set(available_output_formats()))):
|
||||||
format = fmt
|
format = fmt
|
||||||
break
|
break
|
||||||
|
d.exec_()
|
||||||
self.auto_convert(_auto_rows, on_card, format)
|
self.auto_convert(_auto_rows, on_card, format)
|
||||||
d.exec_()
|
|
||||||
|
|
||||||
if bad:
|
if bad:
|
||||||
bad = '\n'.join('<li>%s</li>'%(i,) for i in bad)
|
bad = '\n'.join('<li>%s</li>'%(i,) for i in bad)
|
||||||
d = warning_dialog(self, _('No suitable formats'),
|
d = warning_dialog(self, _('No suitable formats'),
|
||||||
|
@ -420,7 +420,8 @@ class BooksModel(QAbstractTableModel):
|
|||||||
|
|
||||||
|
|
||||||
def get_preferred_formats(self, rows, formats, paths=False,
|
def get_preferred_formats(self, rows, formats, paths=False,
|
||||||
set_metadata=False, specific_format=None):
|
set_metadata=False, specific_format=None,
|
||||||
|
exclude_auto=False):
|
||||||
ans = []
|
ans = []
|
||||||
need_auto = []
|
need_auto = []
|
||||||
if specific_format is not None:
|
if specific_format is not None:
|
||||||
@ -448,7 +449,8 @@ class BooksModel(QAbstractTableModel):
|
|||||||
ans.append(pt)
|
ans.append(pt)
|
||||||
else:
|
else:
|
||||||
need_auto.append(row)
|
need_auto.append(row)
|
||||||
ans.append(None)
|
if not exclude_auto:
|
||||||
|
ans.append(None)
|
||||||
return ans, need_auto
|
return ans, need_auto
|
||||||
|
|
||||||
def id(self, row):
|
def id(self, row):
|
||||||
|
@ -969,17 +969,9 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
|
|||||||
def auto_convert(self, rows, on_card, format):
|
def auto_convert(self, rows, on_card, format):
|
||||||
previous = self.library_view.currentIndex()
|
previous = self.library_view.currentIndex()
|
||||||
|
|
||||||
comics, others = [], []
|
jobs, changed, bad_rows = auto_convert_ebook(format, self, self.library_view.model().db, rows)
|
||||||
db = self.library_view.model().db
|
if jobs is None:
|
||||||
for r in rows:
|
return
|
||||||
formats = db.formats(r)
|
|
||||||
if not formats: continue
|
|
||||||
formats = formats.lower().split(',')
|
|
||||||
if 'cbr' in formats or 'cbz' in formats:
|
|
||||||
comics.append(r)
|
|
||||||
else:
|
|
||||||
others.append(r)
|
|
||||||
jobs, changed, bad_rows = auto_convert_ebook(format, self, self.library_view.model().db, comics, others)
|
|
||||||
for func, args, desc, fmt, id, temp_files in jobs:
|
for func, args, desc, fmt, id, temp_files in jobs:
|
||||||
if id not in bad_rows:
|
if id not in bad_rows:
|
||||||
job = self.job_manager.run_job(Dispatcher(self.book_auto_converted),
|
job = self.job_manager.run_job(Dispatcher(self.book_auto_converted),
|
||||||
@ -1063,7 +1055,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
|
|||||||
if job.exception is not None:
|
if job.exception is not None:
|
||||||
self.job_exception(job)
|
self.job_exception(job)
|
||||||
return
|
return
|
||||||
data = open(temp_files[-1].name, 'rb')
|
data = open(temp_files[0].name, 'rb')
|
||||||
self.library_view.model().db.add_format(book_id, fmt, data, index_is_id=True)
|
self.library_view.model().db.add_format(book_id, fmt, data, index_is_id=True)
|
||||||
data.close()
|
data.close()
|
||||||
self.status_bar.showMessage(job.description + (' completed'), 2000)
|
self.status_bar.showMessage(job.description + (' completed'), 2000)
|
||||||
@ -1080,7 +1072,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
|
|||||||
self.library_view.model().current_changed(current, QModelIndex())
|
self.library_view.model().current_changed(current, QModelIndex())
|
||||||
|
|
||||||
r = self.library_view.model().index(self.library_view.model().db.row(book_id), 0)
|
r = self.library_view.model().index(self.library_view.model().db.row(book_id), 0)
|
||||||
self.sync_to_device(on_card, False, specific_format=fmt, send_rows=[r], auto_convert=False)
|
self.sync_to_device(on_card, False, specific_format=fmt, send_rows=[r], do_auto_convert=False)
|
||||||
|
|
||||||
def book_converted(self, job):
|
def book_converted(self, job):
|
||||||
temp_files, fmt, book_id = self.conversion_jobs.pop(job)
|
temp_files, fmt, book_id = self.conversion_jobs.pop(job)
|
||||||
|
@ -9,6 +9,7 @@ Logic for setting up conversion jobs
|
|||||||
import os
|
import os
|
||||||
from PyQt4.Qt import QDialog
|
from PyQt4.Qt import QDialog
|
||||||
|
|
||||||
|
from calibre.customize.ui import available_input_formats
|
||||||
from calibre.utils.config import prefs
|
from calibre.utils.config import prefs
|
||||||
from calibre.gui2.dialogs.lrf_single import LRFSingleDialog, LRFBulkDialog
|
from calibre.gui2.dialogs.lrf_single import LRFSingleDialog, LRFBulkDialog
|
||||||
from calibre.gui2.dialogs.epub import Config as EPUBConvert
|
from calibre.gui2.dialogs.epub import Config as EPUBConvert
|
||||||
@ -22,6 +23,11 @@ from calibre.ebooks.epub.from_any import SOURCE_FORMATS as EPUB_PREFERRED_SOURCE
|
|||||||
from calibre.ebooks.mobi.from_any import config as mobiconfig
|
from calibre.ebooks.mobi.from_any import config as mobiconfig
|
||||||
from calibre.ebooks.lrf.comic.convert_from import config as comicconfig
|
from calibre.ebooks.lrf.comic.convert_from import config as comicconfig
|
||||||
|
|
||||||
|
# Ordered list of source formats. Items closer to the beginning are
|
||||||
|
# preferred for conversion over those toward the end.
|
||||||
|
PREFERRED_SOURCE_FORMATS = ['epub', 'lit', 'mobi', 'prc', 'azw', 'fb2', 'odt', 'rtf',
|
||||||
|
'txt', 'pdf', 'oebzip', 'htm', 'html']
|
||||||
|
|
||||||
def get_dialog(fmt):
|
def get_dialog(fmt):
|
||||||
return {
|
return {
|
||||||
'epub':EPUBConvert,
|
'epub':EPUBConvert,
|
||||||
@ -34,101 +40,77 @@ def get_config(fmt):
|
|||||||
'mobi':mobiconfig,
|
'mobi':mobiconfig,
|
||||||
}[fmt]
|
}[fmt]
|
||||||
|
|
||||||
def auto_convert(fmt, parent, db, comics, others):
|
def auto_convert(fmt, parent, db, rows):
|
||||||
changed = False
|
changed = False
|
||||||
jobs = []
|
jobs = []
|
||||||
|
|
||||||
total = sum(map(len, (others, comics)))
|
total = len(rows)
|
||||||
if total == 0:
|
if total == 0:
|
||||||
return
|
return None, None, None
|
||||||
parent.status_bar.showMessage(_('Starting auto conversion of %d books')%total, 2000)
|
parent.status_bar.showMessage(_('Starting auto conversion of %d books')%total, 2000)
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
bad_rows = []
|
bad_rows = []
|
||||||
|
|
||||||
for i, row in enumerate(others+comics):
|
for i, row in enumerate(rows):
|
||||||
row_id = db.id(row)
|
row_id = db.id(row)
|
||||||
|
|
||||||
if row in others:
|
temp_files = []
|
||||||
temp_files = []
|
|
||||||
|
|
||||||
data = None
|
|
||||||
for _fmt in EPUB_PREFERRED_SOURCE_FORMATS:
|
|
||||||
try:
|
|
||||||
data = db.format(row, _fmt.upper())
|
|
||||||
if data is not None:
|
|
||||||
break
|
|
||||||
except:
|
|
||||||
continue
|
|
||||||
if data is None:
|
|
||||||
bad_rows.append(row)
|
|
||||||
continue
|
|
||||||
|
|
||||||
defaults = db.conversion_options(db.id(row), fmt)
|
data = None
|
||||||
defaults = defaults if defaults else ''
|
in_formats = [f.lower() for f in db.formats(row).split(',')]
|
||||||
options = get_config(fmt)(defaults=defaults).parse()
|
in_formats = list(set(in_formats).intersection(available_input_formats()))
|
||||||
|
for _fmt in PREFERRED_SOURCE_FORMATS:
|
||||||
mi = db.get_metadata(row)
|
if _fmt in in_formats:
|
||||||
opf = OPFCreator(os.getcwdu(), mi)
|
data = _fmt
|
||||||
opf_file = PersistentTemporaryFile('.opf')
|
break
|
||||||
opf.render(opf_file)
|
if data is None:
|
||||||
opf_file.close()
|
if in_formats != []:
|
||||||
pt = PersistentTemporaryFile('.'+_fmt.lower())
|
data = list(in_formats)[0]
|
||||||
pt.write(data)
|
else:
|
||||||
pt.close()
|
|
||||||
of = PersistentTemporaryFile('.'+fmt)
|
|
||||||
of.close()
|
|
||||||
cover = db.cover(row)
|
|
||||||
cf = None
|
|
||||||
if cover:
|
|
||||||
cf = PersistentTemporaryFile('.jpeg')
|
|
||||||
cf.write(cover)
|
|
||||||
cf.close()
|
|
||||||
options.cover = cf.name
|
|
||||||
options.output = of.name
|
|
||||||
options.from_opf = opf_file.name
|
|
||||||
args = [options, pt.name]
|
|
||||||
desc = _('Auto convert book %d of %d (%s)')%(i+1, total, repr(mi.title))
|
|
||||||
temp_files = [cf] if cf is not None else []
|
|
||||||
temp_files.extend([opf_file, pt, of])
|
|
||||||
jobs.append(('any2'+fmt, args, desc, fmt.upper(), row_id, temp_files))
|
|
||||||
|
|
||||||
changed = True
|
|
||||||
else:
|
|
||||||
defaults = db.conversion_options(db.id(row), fmt)
|
|
||||||
defaults = defaults if defaults else ''
|
|
||||||
options = comicconfig(defaults=defaults).parse()
|
|
||||||
|
|
||||||
mi = db.get_metadata(row)
|
|
||||||
if mi.title:
|
|
||||||
options.title = mi.title
|
|
||||||
if mi.authors:
|
|
||||||
options.author = ','.join(mi.authors)
|
|
||||||
data = None
|
|
||||||
for _fmt in ['cbz', 'cbr']:
|
|
||||||
try:
|
|
||||||
data = db.format(row, _fmt.upper())
|
|
||||||
if data is not None:
|
|
||||||
break
|
|
||||||
except:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if data is None:
|
|
||||||
bad_rows.append(row)
|
bad_rows.append(row)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
pt = PersistentTemporaryFile('.'+_fmt.lower())
|
# defaults = db.conversion_options(db.id(row), fmt)
|
||||||
pt.write(data)
|
# defaults = defaults if defaults else ''
|
||||||
pt.close()
|
# options = get_config(fmt)(defaults=defaults).parse()
|
||||||
of = PersistentTemporaryFile('.'+fmt)
|
|
||||||
of.close()
|
# mi = db.get_metadata(row)
|
||||||
setattr(options, 'output', of.name)
|
# opf = OPFCreator(os.getcwdu(), mi)
|
||||||
options.verbose = 1
|
# opf_file = PersistentTemporaryFile('.opf')
|
||||||
args = [pt.name, options]
|
# opf.render(opf_file)
|
||||||
desc = _('Convert book %d of %d (%s)')%(i+1, total, repr(mi.title))
|
# opf_file.close()
|
||||||
jobs.append(('comic2'+fmt, args, desc, fmt.upper(), row_id, [pt, of]))
|
# pt = PersistentTemporaryFile('.'+_fmt.lower())
|
||||||
|
# pt.write(data)
|
||||||
changed = True
|
# pt.close()
|
||||||
|
# of = PersistentTemporaryFile('.'+fmt)
|
||||||
|
# of.close()
|
||||||
|
# cover = db.cover(row)
|
||||||
|
# cf = None
|
||||||
|
# if cover:
|
||||||
|
# cf = PersistentTemporaryFile('.jpeg')
|
||||||
|
# cf.write(cover)
|
||||||
|
# cf.close()
|
||||||
|
# options.cover = cf.name
|
||||||
|
# options.output = of.name
|
||||||
|
# options.from_opf = opf_file.name
|
||||||
|
# args = [options, pt.name]
|
||||||
|
# desc = _('Auto convert book %d of %d (%s)')%(i+1, total, repr(mi.title))
|
||||||
|
# temp_files = [cf] if cf is not None else []
|
||||||
|
# temp_files.extend([opf_file, pt, of])
|
||||||
|
# jobs.append(('any2'+fmt, args, desc, fmt.upper(), row_id, temp_files))
|
||||||
|
|
||||||
|
mi = db.get_metadata(row)
|
||||||
|
in_file = db.format_abspath(row, data)
|
||||||
|
out_file = PersistentTemporaryFile('.'+fmt.lower())
|
||||||
|
out_file.write(data)
|
||||||
|
out_file.close()
|
||||||
|
desc = _('Auto convert book %d of %d (%s)')%(i+1, total, repr(mi.title))
|
||||||
|
args = [['', in_file, out_file.name]]
|
||||||
|
temp_files = [out_file]
|
||||||
|
jobs.append(('ebook-convert', args, desc, fmt.upper(), row_id, temp_files))
|
||||||
|
|
||||||
|
changed = True
|
||||||
|
|
||||||
if bad_rows:
|
if bad_rows:
|
||||||
res = []
|
res = []
|
||||||
@ -141,9 +123,6 @@ def auto_convert(fmt, parent, db, comics, others):
|
|||||||
|
|
||||||
return jobs, changed, bad_rows
|
return jobs, changed, bad_rows
|
||||||
|
|
||||||
def auto_convert_lrf(fmt, parent, db, comics, others):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def convert_single(fmt, parent, db, comics, others):
|
def convert_single(fmt, parent, db, comics, others):
|
||||||
changed = False
|
changed = False
|
||||||
jobs = []
|
jobs = []
|
||||||
|
@ -79,6 +79,9 @@ PARALLEL_FUNCS = {
|
|||||||
|
|
||||||
'comic2mobi' :
|
'comic2mobi' :
|
||||||
('calibre.ebooks.mobi.from_comic', 'convert', {}, 'notification'),
|
('calibre.ebooks.mobi.from_comic', 'convert', {}, 'notification'),
|
||||||
|
|
||||||
|
'ebook-convert' :
|
||||||
|
('calibre.ebooks.conversion.cli', 'main', {}, None),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user