mirror of
https://github.com/ciromattia/kcc
synced 2025-12-12 17:26:23 +00:00
Update progress notification for bulk jobs (#1109)
This commit is contained in:
@@ -382,13 +382,14 @@ class WorkerThread(QThread):
|
|||||||
error_message = 'Process Failed. Custom title can\'t be set when processing more than 1 source.\nDid you forget to check fusion?'
|
error_message = 'Process Failed. Custom title can\'t be set when processing more than 1 source.\nDid you forget to check fusion?'
|
||||||
print(error_message)
|
print(error_message)
|
||||||
MW.addMessage.emit(error_message, 'error', True)
|
MW.addMessage.emit(error_message, 'error', True)
|
||||||
for job in currentJobs:
|
for i, job in enumerate(currentJobs, start=1):
|
||||||
|
job_progress_number = f'[{i}/{len(currentJobs)}] '
|
||||||
sleep(0.5)
|
sleep(0.5)
|
||||||
if not self.conversionAlive:
|
if not self.conversionAlive:
|
||||||
self.clean()
|
self.clean()
|
||||||
return
|
return
|
||||||
self.errors = False
|
self.errors = False
|
||||||
MW.addMessage.emit('<b>Source:</b> ' + job, 'info', False)
|
MW.addMessage.emit(f'<b>{job_progress_number}Source:</b> ' + job, 'info', False)
|
||||||
if gui_current_format == 'CBZ':
|
if gui_current_format == 'CBZ':
|
||||||
MW.addMessage.emit('Creating CBZ files', 'info', False)
|
MW.addMessage.emit('Creating CBZ files', 'info', False)
|
||||||
GUI.progress.content = 'Creating CBZ files'
|
GUI.progress.content = 'Creating CBZ files'
|
||||||
@@ -402,7 +403,7 @@ class WorkerThread(QThread):
|
|||||||
jobargv.append(job)
|
jobargv.append(job)
|
||||||
try:
|
try:
|
||||||
comic2ebook.options = comic2ebook.checkOptions(copy(options))
|
comic2ebook.options = comic2ebook.checkOptions(copy(options))
|
||||||
outputPath = comic2ebook.makeBook(job, self)
|
outputPath = comic2ebook.makeBook(job, self, job_progress_number)
|
||||||
MW.hideProgressBar.emit()
|
MW.hideProgressBar.emit()
|
||||||
except UserWarning as warn:
|
except UserWarning as warn:
|
||||||
if not self.conversionAlive:
|
if not self.conversionAlive:
|
||||||
@@ -444,7 +445,7 @@ class WorkerThread(QThread):
|
|||||||
else:
|
else:
|
||||||
MW.addMessage.emit('Creating EPUB files... <b>Done!</b>', 'info', True)
|
MW.addMessage.emit('Creating EPUB files... <b>Done!</b>', 'info', True)
|
||||||
if 'MOBI' in gui_current_format:
|
if 'MOBI' in gui_current_format:
|
||||||
MW.progressBarTick.emit('Creating MOBI files')
|
MW.progressBarTick.emit(f'{job_progress_number}Creating MOBI files')
|
||||||
MW.progressBarTick.emit(str(len(outputPath) * 2 + 1))
|
MW.progressBarTick.emit(str(len(outputPath) * 2 + 1))
|
||||||
MW.progressBarTick.emit('tick')
|
MW.progressBarTick.emit('tick')
|
||||||
MW.addMessage.emit('Creating MOBI files', 'info', False)
|
MW.addMessage.emit('Creating MOBI files', 'info', False)
|
||||||
|
|||||||
@@ -456,7 +456,7 @@ def buildOPF(dstdir, title, filelist, originalpath, cover=None):
|
|||||||
"</container>"])
|
"</container>"])
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
def buildEPUB(path, chapternames, tomenumber, ischunked, cover: image.Cover, originalpath, len_tomes=0):
|
def buildEPUB(path, chapternames, tomenumber, ischunked, cover: image.Cover, originalpath, job_progress='', len_tomes=0):
|
||||||
filelist = []
|
filelist = []
|
||||||
chapterlist = []
|
chapterlist = []
|
||||||
os.mkdir(os.path.join(path, 'OEBPS', 'Text'))
|
os.mkdir(os.path.join(path, 'OEBPS', 'Text'))
|
||||||
@@ -564,7 +564,7 @@ def buildEPUB(path, chapternames, tomenumber, ischunked, cover: image.Cover, ori
|
|||||||
else:
|
else:
|
||||||
filelist.append(buildHTML(dirpath, afile, os.path.join(dirpath, afile)))
|
filelist.append(buildHTML(dirpath, afile, os.path.join(dirpath, afile)))
|
||||||
build_html_end = perf_counter()
|
build_html_end = perf_counter()
|
||||||
print(f"buildHTML: {build_html_end - build_html_start} seconds")
|
print(f"{job_progress}buildHTML: {build_html_end - build_html_start} seconds")
|
||||||
# Overwrite chapternames if ComicInfo.xml has bookmarks
|
# Overwrite chapternames if ComicInfo.xml has bookmarks
|
||||||
if ischunked:
|
if ischunked:
|
||||||
options.comicinfo_chapters = []
|
options.comicinfo_chapters = []
|
||||||
@@ -600,7 +600,7 @@ def buildEPUB(path, chapternames, tomenumber, ischunked, cover: image.Cover, ori
|
|||||||
buildOPF(path, options.title, filelist, originalpath, cover)
|
buildOPF(path, options.title, filelist, originalpath, cover)
|
||||||
|
|
||||||
|
|
||||||
def buildPDF(path, title, cover=None, output_file=None):
|
def buildPDF(path, title, job_progress='', cover=None, output_file=None):
|
||||||
"""
|
"""
|
||||||
Build a PDF file from processed comic images.
|
Build a PDF file from processed comic images.
|
||||||
Images are combined into a single PDF optimized for e-readers.
|
Images are combined into a single PDF optimized for e-readers.
|
||||||
@@ -625,11 +625,11 @@ def buildPDF(path, title, cover=None, output_file=None):
|
|||||||
# Save with optimizations for smaller file size
|
# Save with optimizations for smaller file size
|
||||||
doc.save(output_file, deflate=True, garbage=4, clean=True)
|
doc.save(output_file, deflate=True, garbage=4, clean=True)
|
||||||
end = perf_counter()
|
end = perf_counter()
|
||||||
print(f"MuPDF output: {end-start} sec")
|
print(f"{job_progress}MuPDF output: {end-start} sec")
|
||||||
return output_file
|
return output_file
|
||||||
|
|
||||||
|
|
||||||
def imgDirectoryProcessing(path):
|
def imgDirectoryProcessing(path, job_progress=''):
|
||||||
global workerPool, workerOutput
|
global workerPool, workerOutput
|
||||||
workerPool = Pool(maxtasksperchild=100)
|
workerPool = Pool(maxtasksperchild=100)
|
||||||
workerOutput = []
|
workerOutput = []
|
||||||
@@ -649,7 +649,7 @@ def imgDirectoryProcessing(path):
|
|||||||
workerPool.close()
|
workerPool.close()
|
||||||
workerPool.join()
|
workerPool.join()
|
||||||
img_processing_end = perf_counter()
|
img_processing_end = perf_counter()
|
||||||
print(f"imgFileProcessing: {img_processing_end - img_processing_start} seconds")
|
print(f"{job_progress}imgFileProcessing: {img_processing_end - img_processing_start} seconds")
|
||||||
|
|
||||||
# macOS 15 likes to add ._ files after multiprocessing
|
# macOS 15 likes to add ._ files after multiprocessing
|
||||||
dot_clean(path)
|
dot_clean(path)
|
||||||
@@ -1254,7 +1254,7 @@ def slugify(value, is_natural_sorted):
|
|||||||
value = sub(r'0*([0-9]{4,})', r'\1', sub(r'([0-9]+)', r'0000\1', value, count=2))
|
value = sub(r'0*([0-9]{4,})', r'\1', sub(r'([0-9]+)', r'0000\1', value, count=2))
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def makeZIP(zipfilename, basedir, isepub=False):
|
def makeZIP(zipfilename, basedir, job_progress='', isepub=False):
|
||||||
start = perf_counter()
|
start = perf_counter()
|
||||||
zipfilename = os.path.abspath(zipfilename) + '.zip'
|
zipfilename = os.path.abspath(zipfilename) + '.zip'
|
||||||
if SEVENZIP in available_archive_tools():
|
if SEVENZIP in available_archive_tools():
|
||||||
@@ -1275,7 +1275,7 @@ def makeZIP(zipfilename, basedir, isepub=False):
|
|||||||
zipOutput.write(path, aPath)
|
zipOutput.write(path, aPath)
|
||||||
zipOutput.close()
|
zipOutput.close()
|
||||||
end = perf_counter()
|
end = perf_counter()
|
||||||
print(f"makeZIP time: {end - start} seconds")
|
print(f"{job_progress}makeZIP time: {end - start} seconds")
|
||||||
return zipfilename
|
return zipfilename
|
||||||
|
|
||||||
def makeParser():
|
def makeParser():
|
||||||
@@ -1539,7 +1539,7 @@ def makeFusion(sources: List[str]):
|
|||||||
return str(fusion_path)
|
return str(fusion_path)
|
||||||
|
|
||||||
|
|
||||||
def makeBook(source, qtgui=None):
|
def makeBook(source, qtgui=None, job_progress=''):
|
||||||
start = perf_counter()
|
start = perf_counter()
|
||||||
global GUI
|
global GUI
|
||||||
GUI = qtgui
|
GUI = qtgui
|
||||||
@@ -1549,9 +1549,9 @@ def makeBook(source, qtgui=None):
|
|||||||
checkTools(source)
|
checkTools(source)
|
||||||
options.kindle_scribe_azw3 = options.profile == 'KS' and ('MOBI' in options.format or 'EPUB' in options.format)
|
options.kindle_scribe_azw3 = options.profile == 'KS' and ('MOBI' in options.format or 'EPUB' in options.format)
|
||||||
checkPre(source)
|
checkPre(source)
|
||||||
print("Preparing source images...")
|
print(f"{job_progress}Preparing source images...")
|
||||||
path = getWorkFolder(source)
|
path = getWorkFolder(source)
|
||||||
print("Checking images...")
|
print(f"{job_progress}Checking images...")
|
||||||
getMetadata(os.path.join(path, "OEBPS", "Images"), source)
|
getMetadata(os.path.join(path, "OEBPS", "Images"), source)
|
||||||
removeNonImages(os.path.join(path, "OEBPS", "Images"))
|
removeNonImages(os.path.join(path, "OEBPS", "Images"))
|
||||||
detectSuboptimalProcessing(os.path.join(path, "OEBPS", "Images"), source)
|
detectSuboptimalProcessing(os.path.join(path, "OEBPS", "Images"), source)
|
||||||
@@ -1562,14 +1562,14 @@ def makeBook(source, qtgui=None):
|
|||||||
|
|
||||||
if options.webtoon:
|
if options.webtoon:
|
||||||
x, y = image.ProfileData.Profiles[options.profile][1]
|
x, y = image.ProfileData.Profiles[options.profile][1]
|
||||||
comic2panel.main(['-y ' + str(y), '-x' + str(x), '-i', '-m', path], qtgui)
|
comic2panel.main(['-y ' + str(y), '-x' + str(x), '-i', '-m', path], job_progress, qtgui)
|
||||||
if options.noprocessing:
|
if options.noprocessing:
|
||||||
print("Do not process image, ignore any profile or processing option")
|
print(f"{job_progress}Do not process image, ignore any profile or processing option")
|
||||||
else:
|
else:
|
||||||
print("Processing images...")
|
print(f"{job_progress}Processing images...")
|
||||||
if GUI:
|
if GUI:
|
||||||
GUI.progressBarTick.emit('Processing images')
|
GUI.progressBarTick.emit(f'{job_progress}Processing images')
|
||||||
imgDirectoryProcessing(os.path.join(path, "OEBPS", "Images"))
|
imgDirectoryProcessing(os.path.join(path, "OEBPS", "Images"), job_progress)
|
||||||
if GUI:
|
if GUI:
|
||||||
GUI.progressBarTick.emit('1')
|
GUI.progressBarTick.emit('1')
|
||||||
if options.batchsplit > 0 or options.targetsize:
|
if options.batchsplit > 0 or options.targetsize:
|
||||||
@@ -1580,11 +1580,11 @@ def makeBook(source, qtgui=None):
|
|||||||
tomeNumber = 0
|
tomeNumber = 0
|
||||||
if GUI:
|
if GUI:
|
||||||
if options.format == 'CBZ':
|
if options.format == 'CBZ':
|
||||||
GUI.progressBarTick.emit('Compressing CBZ files')
|
GUI.progressBarTick.emit(f'{job_progress}Compressing CBZ files')
|
||||||
elif options.format == 'PDF':
|
elif options.format == 'PDF':
|
||||||
GUI.progressBarTick.emit('Creating PDF files')
|
GUI.progressBarTick.emit(f'{job_progress}Creating PDF files')
|
||||||
else:
|
else:
|
||||||
GUI.progressBarTick.emit('Compressing EPUB files')
|
GUI.progressBarTick.emit(f'{job_progress}Compressing EPUB files')
|
||||||
GUI.progressBarTick.emit(str(len(tomes) + 1))
|
GUI.progressBarTick.emit(str(len(tomes) + 1))
|
||||||
GUI.progressBarTick.emit('tick')
|
GUI.progressBarTick.emit('tick')
|
||||||
options.baseTitle = options.title
|
options.baseTitle = options.title
|
||||||
@@ -1598,29 +1598,29 @@ def makeBook(source, qtgui=None):
|
|||||||
tomeNumber += 1
|
tomeNumber += 1
|
||||||
options.title = options.baseTitle + ' [' + str(tomeNumber) + '/' + str(len(tomes)) + ']'
|
options.title = options.baseTitle + ' [' + str(tomeNumber) + '/' + str(len(tomes)) + ']'
|
||||||
if options.format == 'CBZ':
|
if options.format == 'CBZ':
|
||||||
print("Creating CBZ file...")
|
print(f"{job_progress}Creating CBZ file...")
|
||||||
if len(tomes) > 1:
|
if len(tomes) > 1:
|
||||||
filepath.append(getOutputFilename(source, options.output, '.cbz', ' ' + str(tomeNumber)))
|
filepath.append(getOutputFilename(source, options.output, '.cbz', ' ' + str(tomeNumber)))
|
||||||
else:
|
else:
|
||||||
filepath.append(getOutputFilename(source, options.output, '.cbz', ''))
|
filepath.append(getOutputFilename(source, options.output, '.cbz', ''))
|
||||||
makeZIP(tome + '_comic', os.path.join(tome, "OEBPS", "Images"))
|
makeZIP(tome + '_comic', os.path.join(tome, "OEBPS", "Images"), job_progress)
|
||||||
elif options.format == 'PDF':
|
elif options.format == 'PDF':
|
||||||
print("Creating PDF file with PyMuPDF...")
|
print(f"{job_progress}Creating PDF file with PyMuPDF...")
|
||||||
# determine output filename based on source and tome count
|
# determine output filename based on source and tome count
|
||||||
suffix = (' ' + str(tomeNumber)) if len(tomes) > 1 else ''
|
suffix = (' ' + str(tomeNumber)) if len(tomes) > 1 else ''
|
||||||
output_file = getOutputFilename(source, options.output, '.pdf', suffix)
|
output_file = getOutputFilename(source, options.output, '.pdf', suffix)
|
||||||
# use optimized buildPDF logic with streaming and compression
|
# use optimized buildPDF logic with streaming and compression
|
||||||
output_pdf = buildPDF(tome, options.title, None, output_file)
|
output_pdf = buildPDF(tome, options.title, job_progress, None, output_file)
|
||||||
filepath.append(output_pdf)
|
filepath.append(output_pdf)
|
||||||
else:
|
else:
|
||||||
print("Creating EPUB file...")
|
print(f"{job_progress}Creating EPUB file...")
|
||||||
if len(tomes) > 1:
|
if len(tomes) > 1:
|
||||||
buildEPUB(tome, chapterNames, tomeNumber, True, cover, source, len(tomes))
|
buildEPUB(tome, chapterNames, tomeNumber, True, cover, source, job_progress, len(tomes))
|
||||||
filepath.append(getOutputFilename(source, options.output, '.epub', ' ' + str(tomeNumber)))
|
filepath.append(getOutputFilename(source, options.output, '.epub', ' ' + str(tomeNumber)))
|
||||||
else:
|
else:
|
||||||
buildEPUB(tome, chapterNames, tomeNumber, False, cover, source)
|
buildEPUB(tome, chapterNames, tomeNumber, False, cover, source, job_progress)
|
||||||
filepath.append(getOutputFilename(source, options.output, '.epub', ''))
|
filepath.append(getOutputFilename(source, options.output, '.epub', ''))
|
||||||
makeZIP(tome + '_comic', tome, True)
|
makeZIP(tome + '_comic', tome, job_progress, True)
|
||||||
# Copy files to final destination (PDF files are already saved directly)
|
# Copy files to final destination (PDF files are already saved directly)
|
||||||
if options.format != 'PDF':
|
if options.format != 'PDF':
|
||||||
copyfile(tome + '_comic.zip', filepath[-1])
|
copyfile(tome + '_comic.zip', filepath[-1])
|
||||||
@@ -1633,23 +1633,23 @@ def makeBook(source, qtgui=None):
|
|||||||
if GUI:
|
if GUI:
|
||||||
GUI.progressBarTick.emit('tick')
|
GUI.progressBarTick.emit('tick')
|
||||||
if not GUI and options.format == 'MOBI':
|
if not GUI and options.format == 'MOBI':
|
||||||
print("Creating MOBI files...")
|
print(f"{job_progress}Creating MOBI files...")
|
||||||
work = []
|
work = []
|
||||||
for i in filepath:
|
for i in filepath:
|
||||||
work.append([i])
|
work.append([i])
|
||||||
output = makeMOBI(work, GUI)
|
output = makeMOBI(work, GUI)
|
||||||
for errors in output:
|
for errors in output:
|
||||||
if errors[0] != 0:
|
if errors[0] != 0:
|
||||||
print('Error: KindleGen failed to create MOBI!')
|
print(f"{job_progress}Error: KindleGen failed to create MOBI!")
|
||||||
print(errors)
|
print(errors)
|
||||||
return filepath
|
return filepath
|
||||||
k = kindle.Kindle(options.profile)
|
k = kindle.Kindle(options.profile)
|
||||||
if k.path and k.coverSupport:
|
if k.path and k.coverSupport:
|
||||||
print("Kindle detected. Uploading covers...")
|
print(f"{job_progress}Kindle detected. Uploading covers...")
|
||||||
for i in filepath:
|
for i in filepath:
|
||||||
output = makeMOBIFix(i, options.covers[filepath.index(i)][1])
|
output = makeMOBIFix(i, options.covers[filepath.index(i)][1])
|
||||||
if not output[0]:
|
if not output[0]:
|
||||||
print('Error: Failed to tweak KindleGen output!')
|
print(f'{job_progress}Error: Failed to tweak KindleGen output!')
|
||||||
return filepath
|
return filepath
|
||||||
else:
|
else:
|
||||||
os.remove(i.replace('.epub', '.mobi') + '_toclean')
|
os.remove(i.replace('.epub', '.mobi') + '_toclean')
|
||||||
@@ -1662,7 +1662,7 @@ def makeBook(source, qtgui=None):
|
|||||||
rmtree(source, True)
|
rmtree(source, True)
|
||||||
|
|
||||||
end = perf_counter()
|
end = perf_counter()
|
||||||
print(f"makeBook: {end - start} seconds")
|
print(f"{job_progress}makeBook: {end - start} seconds")
|
||||||
# Clean up temporary workspace
|
# Clean up temporary workspace
|
||||||
try:
|
try:
|
||||||
rmtree(path, True)
|
rmtree(path, True)
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ def splitImage(work):
|
|||||||
return str(sys.exc_info()[1]), sanitizeTrace(sys.exc_info()[2])
|
return str(sys.exc_info()[1]), sanitizeTrace(sys.exc_info()[2])
|
||||||
|
|
||||||
|
|
||||||
def main(argv=None, qtgui=None):
|
def main(argv=None, job_progress='', qtgui=None):
|
||||||
global args, GUI, splitWorkerPool, splitWorkerOutput, mergeWorkerPool, mergeWorkerOutput
|
global args, GUI, splitWorkerPool, splitWorkerOutput, mergeWorkerPool, mergeWorkerOutput
|
||||||
parser = ArgumentParser(prog="kcc-c2p", usage="kcc-c2p [options] [input]", add_help=False)
|
parser = ArgumentParser(prog="kcc-c2p", usage="kcc-c2p [options] [input]", add_help=False)
|
||||||
|
|
||||||
@@ -262,7 +262,7 @@ def main(argv=None, qtgui=None):
|
|||||||
splitWorkerOutput = []
|
splitWorkerOutput = []
|
||||||
splitWorkerPool = Pool(maxtasksperchild=10)
|
splitWorkerPool = Pool(maxtasksperchild=10)
|
||||||
if args.merge:
|
if args.merge:
|
||||||
print("Merging images...")
|
print(f"{job_progress}Merging images...")
|
||||||
directoryNumer = 1
|
directoryNumer = 1
|
||||||
mergeWork = []
|
mergeWork = []
|
||||||
mergeWorkerOutput = []
|
mergeWorkerOutput = []
|
||||||
@@ -274,7 +274,7 @@ def main(argv=None, qtgui=None):
|
|||||||
directoryNumer += 1
|
directoryNumer += 1
|
||||||
mergeWork.append([os.path.join(root, directory)])
|
mergeWork.append([os.path.join(root, directory)])
|
||||||
if GUI:
|
if GUI:
|
||||||
GUI.progressBarTick.emit('Combining images')
|
GUI.progressBarTick.emit(f'{job_progress}Combining images')
|
||||||
GUI.progressBarTick.emit(str(directoryNumer))
|
GUI.progressBarTick.emit(str(directoryNumer))
|
||||||
for i in mergeWork:
|
for i in mergeWork:
|
||||||
mergeWorkerPool.apply_async(func=mergeDirectory, args=(i, ), callback=mergeDirectoryTick)
|
mergeWorkerPool.apply_async(func=mergeDirectory, args=(i, ), callback=mergeDirectoryTick)
|
||||||
@@ -287,7 +287,7 @@ def main(argv=None, qtgui=None):
|
|||||||
rmtree(targetDir, True)
|
rmtree(targetDir, True)
|
||||||
raise RuntimeError("One of workers crashed. Cause: " + mergeWorkerOutput[0][0],
|
raise RuntimeError("One of workers crashed. Cause: " + mergeWorkerOutput[0][0],
|
||||||
mergeWorkerOutput[0][1])
|
mergeWorkerOutput[0][1])
|
||||||
print("Splitting images...")
|
print(f"{job_progress}Splitting images...")
|
||||||
dot_clean(targetDir)
|
dot_clean(targetDir)
|
||||||
for root, _, files in os.walk(targetDir, False):
|
for root, _, files in os.walk(targetDir, False):
|
||||||
for name in files:
|
for name in files:
|
||||||
@@ -297,7 +297,7 @@ def main(argv=None, qtgui=None):
|
|||||||
else:
|
else:
|
||||||
os.remove(os.path.join(root, name))
|
os.remove(os.path.join(root, name))
|
||||||
if GUI:
|
if GUI:
|
||||||
GUI.progressBarTick.emit('Splitting images')
|
GUI.progressBarTick.emit(f'{job_progress}Splitting images')
|
||||||
GUI.progressBarTick.emit(str(pagenumber))
|
GUI.progressBarTick.emit(str(pagenumber))
|
||||||
GUI.progressBarTick.emit('tick')
|
GUI.progressBarTick.emit('tick')
|
||||||
if len(work) > 0:
|
if len(work) > 0:
|
||||||
|
|||||||
Reference in New Issue
Block a user