1
0
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:
kiryl
2025-11-24 22:45:02 +01:00
committed by GitHub
parent 2444a28127
commit 5b069322a4
3 changed files with 42 additions and 41 deletions

View File

@@ -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)

View File

@@ -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)

View File

@@ -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: