diff --git a/gui/KCC.ui b/gui/KCC.ui index ed691d7..4991751 100644 --- a/gui/KCC.ui +++ b/gui/KCC.ui @@ -590,6 +590,16 @@ + + + + <html><head/><body><p>Combines all selected files into a single file. (Helpful for combining chapters into volumes.)</p></body></html> + + + File Fusion + + + diff --git a/kindlecomicconverter/KCC_gui.py b/kindlecomicconverter/KCC_gui.py index af2c41c..87c83d9 100644 --- a/kindlecomicconverter/KCC_gui.py +++ b/kindlecomicconverter/KCC_gui.py @@ -267,6 +267,10 @@ class WorkerThread(QThread): options.delete = True if GUI.spreadShiftBox.isChecked(): options.spreadshift = True + if GUI.fileFusionBox.isChecked(): + options.filefusion = True + else: + options.filefusion = False if GUI.noRotateBox.isChecked(): options.norotate = True if GUI.mozJpegBox.checkState() == Qt.CheckState.PartiallyChecked: @@ -288,6 +292,19 @@ class WorkerThread(QThread): if GUI.jobList.item(i).icon().isNull(): currentJobs.append(str(GUI.jobList.item(i).text())) GUI.jobList.clear() + if options.filefusion: + bookDir = [] + MW.addMessage.emit('Attempting file fusion', 'info', False) + for job in currentJobs: + bookDir.append(job) + try: + comic2ebook.options = comic2ebook.checkOptions(copy(options)) + currentJobs.clear() + currentJobs.append(comic2ebook.makeFusion(bookDir)) + MW.addMessage.emit('Created fusion at ' + currentJobs[0], 'info', False) + except Exception as e: + print('Fusion Failed. ' + str(e)) + MW.addMessage.emit('Fusion Failed. ' + str(e), 'error', True) for job in currentJobs: sleep(0.5) if not self.conversionAlive: @@ -433,6 +450,12 @@ class WorkerThread(QThread): move(item, GUI.targetDirectory) except Exception: pass + if options.filefusion: + for path in currentJobs: + if os.path.isfile(path): + os.remove(path) + elif os.path.isdir(path): + rmtree(path) GUI.progress.content = '' GUI.progress.stop() MW.hideProgressBar.emit() @@ -825,6 +848,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow): 'heightBox': GUI.heightBox.value(), 'deleteBox': GUI.deleteBox.checkState().value, 'spreadShiftBox': GUI.spreadShiftBox.checkState().value, + 'fileFusionBox': GUI.fileFusionBox.checkState().value, 'noRotateBox': GUI.noRotateBox.checkState().value, 'maximizeStrips': GUI.maximizeStrips.checkState().value, 'gammaSlider': float(self.gammaValue) * 100, diff --git a/kindlecomicconverter/KCC_rc.py b/kindlecomicconverter/KCC_rc.py index e0eb11f..46ed290 100644 --- a/kindlecomicconverter/KCC_rc.py +++ b/kindlecomicconverter/KCC_rc.py @@ -1,6 +1,6 @@ # Resource object code (Python 3) # Created by: object code -# Created by: The Resource Compiler for Qt version 6.9.0 +# Created by: The Resource Compiler for Qt version 6.9.1 # WARNING! All changes made in this file will be lost! from PySide6 import QtCore @@ -11612,51 +11612,51 @@ qt_resource_struct = b"\ \x00\x00\x00X\x00\x02\x00\x00\x00\x04\x00\x00\x00\x07\ \x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x01\xc0\x00\x00\x00\x00\x00\x01\x00\x02.\xed\ -\x00\x00\x01\x97 [\xc3\x1b\ +\x00\x00\x01\x97\x5c>\xea\xe6\ \x00\x00\x01\xfe\x00\x00\x00\x00\x00\x01\x00\x02\x83\x87\ -\x00\x00\x01\x97 [\xc3\x19\ +\x00\x00\x01\x97\x5c>\xea\xe5\ \x00\x00\x01\xea\x00\x00\x00\x00\x00\x01\x00\x02Y\x8c\ -\x00\x00\x01\x97 [\xc3\x19\ +\x00\x00\x01\x97\x5c>\xea\xe4\ \x00\x00\x01\xd6\x00\x00\x00\x00\x00\x01\x00\x02N)\ -\x00\x00\x01\x97 [\xc3\x1a\ +\x00\x00\x01\x97\x5c>\xea\xe5\ \x00\x00\x00X\x00\x02\x00\x00\x00\x04\x00\x00\x00\x0c\ \x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\xa6\x00\x00\x00\x00\x00\x01\x00\x01(\x97\ -\x00\x00\x01\x97 [\xc3\x1b\ +\x00\x00\x01\x97\x5c>\xea\xe6\ \x00\x00\x00\xbc\x00\x00\x00\x00\x00\x01\x00\x011\xef\ -\x00\x00\x01\x97 [\xc3\x1c\ +\x00\x00\x01\x97\x5c>\xea\xe7\ \x00\x00\x00\x8c\x00\x00\x00\x00\x00\x01\x00\x01\x1d\x90\ -\x00\x00\x01\x97 [\xc3\x1a\ +\x00\x00\x01\x97\x5c>\xea\xe5\ \x00\x00\x00\xd0\x00\x00\x00\x00\x00\x01\x00\x01:\x05\ -\x00\x00\x01\x97 [\xc3\x1c\ +\x00\x00\x01\x97\x5c>\xea\xe6\ \x00\x00\x00X\x00\x02\x00\x00\x00\x03\x00\x00\x00\x11\ \x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x02B\x00\x00\x00\x00\x00\x01\x00\x02\xb5\xd3\ -\x00\x00\x01\x97 [\xc3*\ +\x00\x00\x01\x97\x5c>\xea\xf1\ \x00\x00\x02\x14\x00\x00\x00\x00\x00\x01\x00\x02\x9f\xd6\ -\x00\x00\x01\x97 [\xc3(\ +\x00\x00\x01\x97\x5c>\xea\xf0\ \x00\x00\x02*\x00\x00\x00\x00\x00\x01\x00\x02\xa93\ -\x00\x00\x01\x97 [\xc3(\ +\x00\x00\x01\x97\x5c>\xea\xef\ \x00\x00\x00X\x00\x02\x00\x00\x00\x07\x00\x00\x00\x15\ \x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x01\x1c\x00\x00\x00\x00\x00\x01\x00\x01P\xb1\ -\x00\x00\x01\x97 [\xc3+\ +\x00\x00\x01\x97\x5c>\xea\xf1\ \x00\x00\x012\x00\x00\x00\x00\x00\x01\x00\x01yY\ -\x00\x00\x01\x97 [\xc3(\ +\x00\x00\x01\x97\x5c>\xea\xef\ \x00\x00\x01\x94\x00\x00\x00\x00\x00\x01\x00\x01\xd2-\ -\x00\x00\x01\x97 [\xc3)\ +\x00\x00\x01\x97\x5c>\xea\xf0\ \x00\x00\x01z\x00\x00\x00\x00\x00\x01\x00\x01\x8c\xe6\ -\x00\x00\x01\x97 [\xc3'\ +\x00\x00\x01\x97\x5c>\xea\xef\ \x00\x00\x01\x04\x00\x00\x00\x00\x00\x01\x00\x01LR\ -\x00\x00\x01\x97 [\xc3!\ +\x00\x00\x01\x97\x5c>\xea\xea\ \x00\x00\x00\xe8\x00\x00\x00\x00\x00\x01\x00\x01?\xe9\ -\x00\x00\x01\x97 [\xc3&\ +\x00\x00\x01\x97\x5c>\xea\xee\ \x00\x00\x01T\x00\x00\x00\x00\x00\x01\x00\x01\x82\xb0\ -\x00\x00\x01\x97 [\xc3'\ +\x00\x00\x01\x97\x5c>\xea\xef\ \x00\x00\x00X\x00\x02\x00\x00\x00\x01\x00\x00\x00\x1d\ \x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00h\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ -\x00\x00\x01\x97 [\xc3&\ +\x00\x00\x01\x97\x5c>\xea\xee\ " def qInitResources(): diff --git a/kindlecomicconverter/KCC_ui.py b/kindlecomicconverter/KCC_ui.py index 4a03a26..288b950 100644 --- a/kindlecomicconverter/KCC_ui.py +++ b/kindlecomicconverter/KCC_ui.py @@ -3,7 +3,7 @@ ################################################################################ ## Form generated from reading UI file 'KCC.ui' ## -## Created by: Qt User Interface Compiler version 6.9.0 +## Created by: Qt User Interface Compiler version 6.9.1 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ @@ -320,6 +320,11 @@ class Ui_mainWindow(object): self.gridLayout_2.addWidget(self.spreadShiftBox, 5, 0, 1, 1) + self.fileFusionBox = QCheckBox(self.optionWidget) + self.fileFusionBox.setObjectName(u"fileFusionBox") + + self.gridLayout_2.addWidget(self.fileFusionBox, 6, 0, 1, 1) + self.upscaleBox = QCheckBox(self.optionWidget) self.upscaleBox.setObjectName(u"upscaleBox") self.upscaleBox.setTristate(True) @@ -555,6 +560,10 @@ class Ui_mainWindow(object): self.spreadShiftBox.setToolTip(QCoreApplication.translate("mainWindow", u"Shift first page to opposite side in landscape for two page spread alignment", None)) #endif // QT_CONFIG(tooltip) self.spreadShiftBox.setText(QCoreApplication.translate("mainWindow", u"Spread shift", None)) +#if QT_CONFIG(tooltip) + self.fileFusionBox.setToolTip(QCoreApplication.translate("mainWindow", u"

Combines all selected files into a single file. (Helpful for combining chapters into volumes.)

", None)) +#endif // QT_CONFIG(tooltip) + self.fileFusionBox.setText(QCoreApplication.translate("mainWindow", u"File Fusion", None)) #if QT_CONFIG(tooltip) self.upscaleBox.setToolTip(QCoreApplication.translate("mainWindow", u"

Unchecked - Nothing
Images smaller than device resolution will not be resized.

Indeterminate - Stretching
Images smaller than device resolution will be resized. Aspect ratio will be not preserved.

Checked - Upscaling
Images smaller than device resolution will be resized. Aspect ratio will be preserved.

", None)) #endif // QT_CONFIG(tooltip) diff --git a/kindlecomicconverter/KCC_ui_editor.py b/kindlecomicconverter/KCC_ui_editor.py index a9526c9..75fac37 100644 --- a/kindlecomicconverter/KCC_ui_editor.py +++ b/kindlecomicconverter/KCC_ui_editor.py @@ -3,7 +3,7 @@ ################################################################################ ## Form generated from reading UI file 'MetaEditor.ui' ## -## Created by: Qt User Interface Compiler version 6.9.0 +## Created by: Qt User Interface Compiler version 6.9.1 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ diff --git a/kindlecomicconverter/comic2ebook.py b/kindlecomicconverter/comic2ebook.py index 498651b..6d76b2c 100755 --- a/kindlecomicconverter/comic2ebook.py +++ b/kindlecomicconverter/comic2ebook.py @@ -28,6 +28,7 @@ from copy import copy from glob import glob, escape from re import sub from stat import S_IWRITE, S_IREAD, S_IEXEC +from typing import List from zipfile import ZipFile, ZIP_STORED, ZIP_DEFLATED from tempfile import mkdtemp, gettempdir, TemporaryFile from shutil import move, copytree, rmtree, copyfile @@ -36,6 +37,7 @@ from uuid import uuid4 from natsort import os_sort_keygen from slugify import slugify as slugify_ext from PIL import Image, ImageFile +from pathlib import Path from subprocess import STDOUT, PIPE, CalledProcessError from psutil import virtual_memory, disk_usage from html import escape as hescape @@ -1242,6 +1244,40 @@ def checkPre(source): raise UserWarning("Target directory is not writable.") +def makeFusion(sources: List[str]): + if len(sources) < 2: + raise UserWarning('Fusion requires at least 2 sources. Did you forget to uncheck fusion?') + start = perf_counter() + first_path = Path(sources[0]) + if first_path.is_file(): + fusion_path = first_path.parent.joinpath(first_path.stem + ' [fused]') + else: + fusion_path = first_path.parent.joinpath(first_path.name + ' [fused]') + print("Running Fusion") + + for source in sources: + print(f"Processing {source}...") + checkPre(source) + print("Checking images...") + path = getWorkFolder(source) + pathfinder = os.path.join(path, "OEBPS", "Images") + sanitizeTree(pathfinder) + # TODO: remove flattenTree when subchapters are supported + flattenTree(pathfinder) + source_path = Path(source) + if source_path.is_file(): + os.renames(pathfinder, fusion_path.joinpath(source_path.stem)) + else: + os.renames(pathfinder, fusion_path.joinpath(source_path.name)) + + + end = perf_counter() + print(f"makefusion: {end - start} seconds") + print("Combined File: "+ str(fusion_path)) + + return str(fusion_path) + + def makeBook(source, qtgui=None): start = perf_counter() global GUI