Compare commits

...
Author SHA1 Message Date
Alex Xu c611cf6dc7 bump to 11.3.0 2026-09-15 18:37:16 -07:00
dependabot[bot]andpublic 80fe280b50 Bump signpath/github-action-submit-signing-request from 2.3 to 3.0 (#1437)
Bumps [signpath/github-action-submit-signing-request](https://github.com/signpath/github-action-submit-signing-request) from 2.3 to 3.0.
- [Release notes](https://github.com/signpath/github-action-submit-signing-request/releases)
- [Commits](https://github.com/signpath/github-action-submit-signing-request/compare/v2.3...v3.0)

---
updated-dependencies:
- dependency-name: signpath/github-action-submit-signing-request
  dependency-version: '3.0'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-15 18:36:09 -07:00
Alex Xu ff9a5e518d fix expert button height on windows 2026-09-15 18:35:19 -07:00
Alex Xu 05e5844779 support Kindle Previewer 4 on Windows (#1440)
* initial commit

* refactor kindlegen check

* search for windows kindlegen

* increase search range
2026-09-15 18:27:43 -07:00
Alex Xu aaf3548595 increase search range 2026-09-15 18:25:32 -07:00
Alex Xu ea8a4db26e search for windows kindlegen 2026-09-15 18:25:32 -07:00
Alex Xu aa652ff6c0 refactor kindlegen check 2026-09-15 18:25:32 -07:00
Alex Xu a310d4c2b1 initial commit 2026-09-15 18:25:32 -07:00
Alex Xu 7245fdf2e1 support kindle previewer 4 (#1439) 2026-09-14 15:56:18 -07:00
Alex Xu fe85274105 implement custom covers for webtoon and fusion (#1438) 2026-09-14 13:06:53 -07:00
8 changed files with 96 additions and 51 deletions
+1 -1
View File
@@ -58,7 +58,7 @@ jobs:
name: windows-build-${{ matrix.entry }}
path: dist/*.exe
- id: optional_step_id
uses: signpath/github-action-submit-signing-request@v2.3
uses: signpath/github-action-submit-signing-request@v3.0
if: ${{ github.repository == 'ciromattia/kcc' }}
with:
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
+1 -1
View File
@@ -51,7 +51,7 @@ jobs:
name: windows7-build
path: dist/*.exe
- id: optional_step_id
uses: signpath/github-action-submit-signing-request@v2.3
uses: signpath/github-action-submit-signing-request@v3.0
if: ${{ github.repository == 'ciromattia/kcc' }}
with:
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
+6
View File
@@ -1127,6 +1127,12 @@ Keeping this file may crash some readers like the Kobo native CBZ reader.</strin
</item>
<item row="0" column="4">
<widget class="QPushButton" name="expertButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="toolTip">
<string>Toggle Easy/Expert Mode</string>
</property>
+2
View File
@@ -33,6 +33,7 @@ def modify_path():
mac_paths = [
'/Applications/Kindle Comic Creator/Kindle Comic Creator.app/Contents/MacOS',
'/Applications/Kindle Previewer 3.app/Contents/lib/fc/bin/',
'/Applications/Kindle Previewer 4.app/Contents/Resources/KFXGen/bin/'
]
if getattr(sys, 'frozen', False):
os.environ['PATH'] += os.pathsep + os.pathsep.join(mac_paths +
@@ -68,6 +69,7 @@ def modify_path():
os.path.expandvars('%LOCALAPPDATA%\\Amazon\\KC2'),
os.path.expandvars('%LOCALAPPDATA%\\Amazon\\Kindle Previewer 3\\lib\\fc\\bin\\'),
os.path.expandvars('%UserProfile%\\Kindle Previewer 3\\lib\\fc\\bin\\'),
'C:\\Tools',
'C:\\Apps\\Kindle Previewer 3\\lib\\fc\\bin',
'D:\\Apps\\Kindle Previewer 3\\lib\\fc\\bin',
'E:\\Apps\\Kindle Previewer 3\\lib\\fc\\bin',
+11 -34
View File
@@ -32,7 +32,6 @@ import sys
from urllib.parse import unquote
from time import sleep
from shutil import move, rmtree
from subprocess import STDOUT, PIPE, CalledProcessError
import requests
from xml.sax.saxutils import escape
@@ -45,9 +44,9 @@ from PIL.Image import Dither
from .KCC_spread_label import LabelSpreadsDialog
from .shared import HTMLStripper, sanitizeTrace, walkLevel, subprocess_run
from .shared import HTMLStripper, sanitizeTrace, walkLevel
from .comicarchive import SEVENZIP, TAR, available_archive_tools
from .comic2ebook import OS_SORT_KEY, flattenTree, getWorkFolder, removeNonImages, sanitizeTree
from .comic2ebook import OS_SORT_KEY, flattenTree, getWorkFolder, removeNonImages, sanitizeTree, detectKindleGen
from . import __version__
from . import comic2ebook
from . import metadata
@@ -418,6 +417,7 @@ class WorkerThread(QThread):
if GUI.jobList.item(i).icon().isNull():
currentJobs.append(str(GUI.jobList.item(i).text()))
GUI.jobList.clear()
fusion_cover_path = None
if options.filefusion:
bookDir = []
MW.addMessage.emit('Attempting file fusion', 'info', False)
@@ -429,7 +429,8 @@ class WorkerThread(QThread):
if options.output is None:
options.output = fusion_source_parent
currentJobs.clear()
currentJobs.append(comic2ebook.makeFusion(bookDir))
job, fusion_cover_path = comic2ebook.makeFusion(bookDir)
currentJobs.append(job)
MW.addMessage.emit('Created fusion at ' + currentJobs[0], 'info', False)
except Exception as e:
print('Fusion Failed. ' + str(e))
@@ -463,7 +464,7 @@ class WorkerThread(QThread):
jobargv.append(job)
try:
comic2ebook.options = comic2ebook.checkOptions(copy(options))
outputPath = comic2ebook.makeBook(job, self, job_progress_number)
outputPath = comic2ebook.makeBook(job, fusion_cover_path, self, job_progress_number)
MW.hideProgressBar.emit()
except UserWarning as warn:
if not self.conversionAlive:
@@ -1253,8 +1254,8 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
self.needClean = True
return
if 'MOBI' in GUI.formats[str(GUI.formatBox.currentText())]['format'] and not self.kindleGen:
self.detectKindleGen()
if not self.kindleGen:
if not detectKindleGen(GUI):
self.progress.stop()
GUI.jobList.clear()
self.display_kindlegen_missing()
self.needClean = True
@@ -1382,32 +1383,6 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
self.saveSettings(None)
sys.exit(0)
def detectKindleGen(self, startup=False):
if not sys.platform.startswith('win'):
try:
os.chmod('/usr/local/bin/kindlegen', 0o755)
except Exception:
pass
try:
versionCheck = subprocess_run(['kindlegen', '-locale', 'en'], stdout=PIPE, stderr=STDOUT, encoding='UTF-8', errors='ignore', check=True)
self.kindleGen = True
for line in versionCheck.stdout.splitlines():
if 'Amazon kindlegen' in line:
versionCheck = line.split('V')[1].split(' ')[0]
if Version(versionCheck) < Version('2.9'):
self.addMessage('Your <a href="https://www.amazon.com/b?node=23496309011">KindleGen</a>'
' is outdated! MOBI conversion might fail.', 'warning')
break
except (FileNotFoundError, CalledProcessError):
self.kindleGen = False
if startup:
self.display_kindlegen_missing()
except OSError as e:
self.kindleGen = False
if startup:
error = f"kindlegen: {e.strerror}\n\n Re-install Rosetta/Kindle Previewer/other Intel app?\n\nPlease email Amazon to make Kindle Previewer Apple silicon native at amazon.com/kindle-help"
self.showDialog(error, 'error')
def __init__(self, kccapp, kccwindow):
global APP, MW, GUI
APP = kccapp
@@ -1440,8 +1415,11 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
except Exception:
self.options = default_options
self.worker = WorkerThread()
self.worker.setObjectName('worker')
self.versionCheck = VersionThread(self.startNumber2)
self.versionCheck.setObjectName('version')
self.progress = ProgressThread()
self.progress.setObjectName('progress')
self.tray = SystemTrayIcon()
self.conversionAlive = False
self.needClean = True
@@ -1672,7 +1650,6 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
if not any([self.tar, self.sevenzip]):
self.addMessage('<a href="https://github.com/ciromattia/kcc#7-zip">Install 7z (link)</a>'
' to enable CBZ/CBR/ZIP/etc processing.', 'warning')
self.detectKindleGen(True)
APP.messageFromOtherInstance.connect(self.handleMessage)
GUI.defaultOutputFolderButton.clicked.connect(self.selectDefaultOutputFolder)
+1
View File
@@ -567,6 +567,7 @@ class Ui_mainWindow(object):
self.expertButton = QPushButton(self.toolWidget)
self.expertButton.setObjectName(u"expertButton")
self.expertButton.setMinimumSize(QSize(0, 30))
self.gridLayout_6.addWidget(self.expertButton, 0, 4, 1, 1)
+1 -1
View File
@@ -1,4 +1,4 @@
__version__ = '11.2.0'
__version__ = '11.3.0'
__license__ = 'ISC'
__copyright__ = '2012-2022, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>, darodi'
__docformat__ = 'restructuredtext en'
+73 -14
View File
@@ -40,6 +40,7 @@ from shutil import move, copytree, rmtree
from multiprocessing import Pool, cpu_count
from uuid import uuid4
from natsort import os_sort_keygen, os_sorted
from packaging.version import Version
from slugify import slugify as slugify_ext
from PIL import Image, ImageFile, ImageOps
from pathlib import Path
@@ -77,9 +78,10 @@ def main(argv=None):
if len(sources) == 0:
print('No matching files found.')
return 1
fusion_cover_path = None
if options.filefusion:
fusion_source_parent = str(Path(sources[0]).parent)
fusion_path = makeFusion(list(sources))
fusion_path, fusion_cover_path = makeFusion(list(sources))
sources.clear()
sources.append(fusion_path)
for source in sources:
@@ -89,7 +91,7 @@ def main(argv=None):
options.output = fusion_source_parent
options = checkOptions(options)
print('Working on ' + source + '...')
makeBook(source)
makeBook(source, fusion_cover_path)
return 0
@@ -1748,17 +1750,58 @@ def checkTools(source):
print('ERROR: 7z is missing!')
sys.exit(1)
if options.format == 'MOBI':
try:
subprocess_run(['kindlegen', '-locale', 'en'], stdout=PIPE, stderr=STDOUT, check=True)
except (FileNotFoundError, CalledProcessError):
print('ERROR: KindleGen is missing!')
sys.exit(1)
except OSError as e:
print(f"kindlegen: {e.strerror}")
print('Re-install Rosetta/Kindle Previewer/other Intel app?')
print('Please email Amazon to make Kindle Previewer Apple silicon native at amazon.com/kindle-help')
if not detectKindleGen():
sys.exit(1)
def detectKindleGen(GUI=None):
if sys.platform.startswith('win'):
if not _detectKindleGen():
start = perf_counter()
try:
for i in range(0, 200):
for j in range(0, 20):
for k in range (0, 20):
path = f'C:\\Program Files\\WindowsApps\\KindlePreviewerApp_4.{i}.{j}.{k}_x64__ek06e0aw29nma'
if os.path.exists(path):
kindlegen_path = os.path.join(path, 'KindlePreviewerApp\\resources\\KFXGen\\bin\\kindlegen.exe')
tool_path = 'C:\\Tools'
if not os.path.isdir(tool_path):
os.mkdir(tool_path)
shutil.copy2(kindlegen_path, tool_path)
except Exception:
pass
end = perf_counter()
print(f"Search for Windows KindleGen: {end - start} sec")
return _detectKindleGen(GUI)
else:
try:
os.chmod('/usr/local/bin/kindlegen', 0o755)
except Exception:
pass
return _detectKindleGen(GUI)
def _detectKindleGen(GUI=None):
try:
versionCheck = subprocess_run(['kindlegen', '-locale', 'en'], stdout=PIPE, stderr=STDOUT, encoding='UTF-8', errors='ignore', check=True)
for line in versionCheck.stdout.splitlines():
if 'Amazon kindlegen' in line:
versionCheck = line.split('V')[1].split(' ')[0]
if Version(versionCheck) < Version('2.9'):
if GUI:
GUI.addMessage('Your <a href="https://www.amazon.com/b?node=23496309011">KindleGen</a>'
' is outdated! MOBI conversion might fail.', 'warning')
break
return True
except (FileNotFoundError, CalledProcessError):
print('ERROR: KindleGen is missing!')
return False
except (OSError, Exception) as e:
print(f"kindlegen: {e.strerror}")
print('Re-install or re-open Rosetta/Kindle Previewer/other Intel app?')
if GUI:
error = f"kindlegen: {e.strerror}\n\n Re-install or re-open Rosetta/Kindle Previewer/other Intel app?"
GUI.showDialog(error, 'error')
return False
def checkPre(source='KCC-'):
# Make sure that all temporary files are gone
@@ -1773,6 +1816,19 @@ def makeFusion(sources: List[str]):
start = perf_counter()
first_path = Path(sources[0])
fusion_cover_path = None
if first_path.parent.joinpath('Covers').is_dir():
covers = os.listdir(first_path.parent.joinpath('Covers'))
filtered_covers = []
for cover in covers:
_, cover_ext = getImageFileName(cover)
if cover_ext in IMAGE_TYPES:
filtered_covers.append(cover)
try:
fusion_cover_path = first_path.parent.joinpath('Covers', filtered_covers[0])
except IndexError:
pass
if options.tempdir:
fusion_parent = first_path.parent
else:
@@ -1814,10 +1870,10 @@ def makeFusion(sources: List[str]):
print(f"makefusion: {end - start} seconds")
print("Combined File: "+ str(fusion_path))
return str(fusion_path)
return str(fusion_path), fusion_cover_path
def makeBook(source, qtgui=None, job_progress=''):
def makeBook(source, fusion_cover_path=None, qtgui=None, job_progress=''):
start = perf_counter()
global GUI
GUI = qtgui
@@ -1912,9 +1968,12 @@ def makeBook(source, qtgui=None, job_progress=''):
options.customcover = True
except IndexError:
pass
if fusion_cover_path:
options.customcover = True
cover_path = fusion_cover_path
cover = None
if not options.webtoon:
if not options.webtoon or options.customcover:
cover = image.Cover(cover_path, options)
x, y = image.ProfileData.Profiles[options.profile][1]