1
0
mirror of https://github.com/ciromattia/kcc synced 2026-04-15 13:38:46 +00:00

Compare commits

..

48 Commits

Author SHA1 Message Date
Alex Xu
2fc32bae58 Update __init__.py 2024-06-29 08:52:09 -07:00
Alex Xu
db25a0939c Build windows gui version normally. 2024-06-25 22:03:10 -07:00
Alex Xu
1bd7506140 remove unar macOS 2024-06-25 21:04:52 -07:00
Alex Xu
4fc5cc9dfb remove GUI windows docker 2024-06-25 20:45:32 -07:00
Alex Xu
89289412a3 Revert "add hiddenimports=['pkg_resources.extern']"
This reverts commit 193297c8fc.
2024-06-25 19:29:17 -07:00
Alex Xu
193297c8fc add hiddenimports=['pkg_resources.extern'] 2024-06-25 19:15:34 -07:00
Alex Xu
367d71e4ad fix typo 2024-06-25 12:52:41 -07:00
Alex Xu
cdde0f18cd update prereq readme (#714)
* update prereq readme

* Update README.md

* Update README.md

* Revert "Update README.md"

This reverts commit ceb35b03b6.

* Revert "Update README.md"

This reverts commit a24e818c0e.

* add other OS note
2024-06-25 12:42:38 -07:00
Alex Xu
9fe82a9dd4 improve kindlegen detection windows (#688)
* improve kindlegen detection windows

* add C:\Apps folders
2024-06-25 12:21:48 -07:00
detournemint
e958edd135 Update package-linux.yml to include libxcb-cursor0
Including libxcb-cursor0 for linux
2024-06-25 12:15:33 -07:00
Alex Xu
6738b70487 don't display upscale warning on kindle scribe 2024-06-09 08:00:55 -07:00
Dominik Gedon
44094bdb21 Add Kobo Libra/Clara colour (#703)
* fix: trailing whitespaces

* Add color toggle mode

* Add Kobo Libra Colour

Signed-off-by: Dominik Gedon <dominik@gedon.org>

* Add Kobo Clara Colour

Signed-off-by: Dominik Gedon <dominik@gedon.org>

* Address suggestions

* Address more suggestions

---------

Signed-off-by: Dominik Gedon <dominik@gedon.org>
2024-06-09 08:00:25 -07:00
Alex Xu
a9a2f47e30 fix 1860 width 2024-05-28 09:55:59 -07:00
Bruno Resende
c35dd137ea Add de-dupe cover option for landscape alignment (#561)
* Adds --author argument to CLI

* Add --prefercoverfile and --nocoveraspage arguments to CLI

* cover checks only run once

* Revert "cover checks only run once"

This reverts commit ad7b3cc106.

* split off author portion

* split off author

* remove prefercover

* whitespace fixes

* rename to duplicatecover

* whitespace fixes

* rename to dedupecover

* add dedupe to UI

---------

Co-authored-by: Alex Xu <alexkurosakimh3@gmail.com>
2024-05-17 09:56:22 -07:00
Alex Xu
1ea008c8f3 reduce dependency on 7z, unar, homebrew by using builtin tar (#693)
* reduce dependency on 7z, unar, homebrew by using builtin tar

* update readme

* fix typo

* add editor text

* remove unar

* Revert "remove unar"

This reverts commit 2c4b239d67.

* Revert "fix typo"

This reverts commit 79752c7f38.

* Revert "update readme"

This reverts commit 4f5c727a2d.
2024-05-17 09:56:04 -07:00
Alex Xu
cbc1ed5db4 Kindle Scribe 1860 max width (#691)
* Kindle Scribe 1860 max width

* create kindle_scribe_azw3 var

* clean up code
2024-05-17 09:55:43 -07:00
Alex Xu
6bf662bea3 add faq 2024-05-15 10:15:08 -07:00
Alex Xu
cfae306731 macos-latest is now macos-14 (m1) 2024-04-27 12:56:49 -07:00
Alex Xu
f6475f4c61 Close and re-open KCC note 2024-04-19 21:15:48 -07:00
Alex Xu
9646518575 shorten 7z/kindlegen notes 2024-04-18 20:58:12 -07:00
Alex Xu
937dd3984a kindlegen note 2024-04-18 18:07:06 -07:00
Alex Xu
4e6f6ec8e8 clarify 7z/kindlegen windows 2024-04-18 17:35:51 -07:00
Alex Xu
4b36fdbfa2 update C drive notes 2024-04-18 16:08:10 -07:00
Alex Xu
d8141af4eb update c drive notes 2024-04-18 15:45:34 -07:00
Alex Xu
cf38c4d445 Revert "fix package-windows-with-docker.yml (#579)"
This reverts commit 424118b7cd.
2024-04-16 15:46:44 -07:00
Alex Xu
283b2da1a0 bump to 6.0.0 2024-04-16 15:09:03 -07:00
Alex Xu
4a9f693574 Adds --author argument to CLI (#683) 2024-04-16 14:59:54 -07:00
Alex Xu
9a48887edc update C drive notes 2024-04-15 21:16:14 -07:00
Alex Xu
0981ec3c6d add more 7z Windows locations 2024-03-24 18:40:50 -07:00
dependabot[bot]
e0e6606736 Bump softprops/action-gh-release from 1 to 2
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 1 to 2.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/action-gh-release/compare/v1...v2)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-21 21:58:00 -07:00
Alex Xu
518e67c132 move install from source instructions 2024-03-16 20:12:30 -07:00
Alex Xu
6c593dac1f add gen_ui_files note 2024-03-16 14:04:35 -07:00
Alex Xu
9d065676db add install from source and qt creator instructions 2024-03-16 13:54:40 -07:00
Alex Xu
9520e59a29 Add C drive notes 2024-03-15 12:08:46 -07:00
Alex Xu
461a7fda88 add C drive note 2024-03-12 12:44:07 -07:00
Alex Xu
5ccbb770a6 do not change default install location for 7z/KP 2024-03-09 10:04:01 -08:00
Alex Xu
49bf80f5d8 LOAD_TRUNCATED_IMAGES = True 2024-03-04 21:36:07 -08:00
Alex Xu
33cc324381 prepare m1 build pipeline (#669) 2024-01-31 11:49:27 -08:00
Alex Xu
6ba5539813 Revert "docker arm install from requirements.txt" 2024-01-29 10:54:13 -08:00
Alex Xu
f725196106 reset saved settings 2024-01-29 10:29:45 -08:00
Alex Xu
c8ff88ed0f Update Dockerfile-base 2024-01-28 22:27:03 -08:00
darodi
33fed662fe Merge pull request #666
* fix dependencies
2024-01-12 23:22:09 +00:00
Alex Xu
bc7cd17916 rename kp3 2024-01-12 12:41:51 -08:00
Alex Xu
c5e1e18ac2 Revert "rename pw to paperwhite"
This reverts commit 48541404ee.
2024-01-02 14:26:53 -08:00
Alex Xu
ee31b784cb Add native Apple Silicon support by upgrading qt5 to qt6 (#523)
* initial upgrade

* fix epub icon

* pyside6

* fix tray icon

* add spaces

* add comment back

* change exec

* edit shared

* Add CheckState enums

* add mozJpeg

* fix batch

* import CheckedState

* remove references to qt5

* add mozJpeg warning

* Update package-linux.yml

* Update package-linux.yml

* Update Dockerfile-base

* Update README.md

* Update package-linux.yml

* Update README.md

* Update README.md

* add mozjpeg to gitignore

* add warning text

* fix state issue

* use same settings save location as qt5

* remove space

* remove mozJpeg

* update Dockerfile-base file version

* use getattr instead of eval

* undo readme changes

* undo conda

* undo gitignore

---------

Co-authored-by: Alexander Xu <alexanderx@qualtrics.com>
Co-authored-by: darodi <4682830+darodi@users.noreply.github.com>
2024-01-02 14:08:39 -08:00
Alex Xu
48541404ee rename pw to paperwhite 2024-01-02 12:14:51 -08:00
Alex Xu
acbebcfd40 rename kindle labels by gen 2024-01-02 12:14:51 -08:00
VampiroMedicado
dd6273b864 add missing parameter output to options 2024-01-02 10:11:38 -08:00
25 changed files with 12385 additions and 12197 deletions

View File

@@ -34,8 +34,8 @@ jobs:
- name: Install python dependencies
run: |
sudo apt-get update
sudo apt-get install -y libpng-dev libjpeg-dev p7zip-full p7zip-rar python3-pyqt5 python3-pip squashfs-tools libfuse2
python -m pip install --upgrade pip setuptools wheel certifi pyinstaller PyQt6 --no-binary pyinstaller
sudo apt-get install -y libpng-dev libjpeg-dev p7zip-full p7zip-rar python3-pip squashfs-tools libfuse2 libxcb-cursor0
python -m pip install --upgrade pip setuptools wheel certifi pyinstaller --no-binary pyinstaller
python -m pip install -r requirements.txt
- name: build binary
run: |
@@ -64,7 +64,7 @@ jobs:
name: AppImage
path: './*.AppImage*'
- name: Release
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
prerelease: true

View File

@@ -23,7 +23,10 @@ on:
jobs:
build:
runs-on: macos-latest
strategy:
matrix:
os: [ macos-12, macos-14 ]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Set up Python
@@ -77,10 +80,10 @@ jobs:
- name: upload build
uses: actions/upload-artifact@v4
with:
name: mac-os-build
name: mac-os-build-${{ runner.arch }}
path: dist/*.dmg
- name: Release
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
prerelease: true
@@ -95,4 +98,4 @@ jobs:
# if: ${{ always() }}
run: |
security delete-keychain $RUNNER_TEMP/app-signing.keychain-db
rm ~/Library/MobileDevice/Provisioning\ Profiles/build_pp.mobileprovision
rm ~/Library/MobileDevice/Provisioning\ Profiles/build_pp.mobileprovision

View File

@@ -26,33 +26,27 @@ jobs:
# run: |
# pyi-makespec -F -i icons\\comic2ebook.ico -n KCC_test -w --noupx kcc.py
- name: Package Application
uses: JackMcKew/pyinstaller-action-windows@python3-10-pyinstaller-5-3
with:
path: .
spec: ./kcc.spec
- name: Package Application
uses: JackMcKew/pyinstaller-action-windows@python3-10-pyinstaller-5-3
uses: JackMcKew/pyinstaller-action-windows@main
with:
path: .
spec: ./kcc-c2e.spec
- name: Package Application
uses: JackMcKew/pyinstaller-action-windows@python3-10-pyinstaller-5-3
uses: JackMcKew/pyinstaller-action-windows@main
with:
path: .
spec: ./kcc-c2p.spec
- name: rename binaries
run: |
version_built=$(cat kindlecomicconverter/__init__.py | grep version | awk '{print $3}' | sed "s/[^.0-9b]//g")
mv dist/windows/kcc.exe dist/windows/kcc_${version_built}.exe
mv dist/windows/kcc-c2e.exe dist/windows/kcc_c2e_${version_built}.exe
mv dist/windows/kcc-c2p.exe dist/windows/kcc_c2p_${version_built}.exe
mv dist/windows/kcc-c2e.exe dist/windows/KCC_c2e_${version_built}.exe
mv dist/windows/kcc-c2p.exe dist/windows/KCC_c2p_${version_built}.exe
- name: upload build
uses: actions/upload-artifact@v4
with:
name: windows-build
path: dist/windows/*.exe
- name: Release
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
prerelease: true

View File

@@ -47,7 +47,7 @@ jobs:
name: windows-build
path: dist/*.exe
- name: Release
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
prerelease: true

View File

@@ -1,5 +1,5 @@
# Select final stage based on TARGETARCH ARG
FROM ghcr.io/ciromattia/kcc:docker-base-20230514
FROM ghcr.io/ciromattia/kcc:docker-base-20230809
LABEL com.kcc.name="Kindle Comic Converter"
LABEL com.kcc.author="Ciro Mattia Gonano, Paweł Jastrzębski and Darodi"
LABEL org.opencontainers.image.description='Kindle Comic Converter'

View File

@@ -8,7 +8,7 @@ RUN echo "I'm building for $TARGETOS/$TARGETARCH/$TARGETVARIANT"
COPY requirements.txt /opt/kcc/
ENV PATH="/opt/venv/bin:$PATH"
RUN DEBIAN_FRONTEND=noninteractive apt-get update -y && apt-get -yq upgrade && \
apt-get install -y libpng-dev libjpeg-dev p7zip-full unrar-free libgl1 python3-pyqt5 && \
apt-get install -y libpng-dev libjpeg-dev p7zip-full unrar-free libgl1 && \
python -m pip install --upgrade pip && \
python -m venv /opt/venv && \
python -m pip install -r /opt/kcc/requirements.txt
@@ -55,7 +55,6 @@ RUN set -x && \
KEPT_PACKAGES+=(p7zip-full) && \
KEPT_PACKAGES+=(python3) && \
KEPT_PACKAGES+=(python3-pip) && \
KEPT_PACKAGES+=(python3-pyqt5) && \
KEPT_PACKAGES+=(unrar-free) && \
# Install packages
DEBIAN_FRONTEND=noninteractive apt-get update -y && apt-get -yq upgrade && \
@@ -112,7 +111,6 @@ RUN set -x && \
KEPT_PACKAGES+=(p7zip-full) && \
KEPT_PACKAGES+=(python3) && \
KEPT_PACKAGES+=(python3-pip) && \
KEPT_PACKAGES+=(python3-pyqt5) && \
KEPT_PACKAGES+=(unrar-free) && \
# Install packages
DEBIAN_FRONTEND=noninteractive apt-get update -y && apt-get -yq upgrade && \
@@ -158,5 +156,5 @@ WORKDIR /app
RUN DEBIAN_FRONTEND=noninteractive apt-get update -y && apt-get -yq upgrade && \
apt-get install -y p7zip-full unrar-free && \
ln -s /app/kindlegen /bin/kindlegen && \
echo docker-base-20230514 > /IMAGE_VERSION
echo docker-base-20230809 > /IMAGE_VERSION

103
README.md
View File

@@ -2,8 +2,8 @@
[![GitHub release](https://img.shields.io/github/release/ciromattia/kcc.svg)](https://github.com/ciromattia/kcc/releases)
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/ciromattia/kcc/docker-publish.yml?label=docker%20build)](https://github.com/ciromattia/kcc/pkgs/container/kcc)
[![GitHub release](https://img.shields.io/github/release/ciromattia/kcc.svg)](https://github.com/ciromattia/kcc/releases)
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/ciromattia/kcc/docker-publish.yml?label=docker%20build)](https://github.com/ciromattia/kcc/pkgs/container/kcc)
**Kindle Comic Converter** is a Python app to convert comic/manga files or folders to EPUB, Panel View MOBI or E-Ink optimized CBZ.
@@ -36,11 +36,12 @@ If you find **KCC** valuable you can consider donating to the authors:
- **https://github.com/ciromattia/kcc/releases**
Click on **Assets** of the latest release.
Click on **Assets** of the latest release.
You probably want either
- `kcc_*.*.*.exe` (Windows)
- `KindleComicConverter_osx_*.*.*.dmg` (Mac)
You probably want either
- `KCC_*.*.*.exe` (Windows)
- `kcc_macos_arm_*.*.*.dmg` (recent Mac with Apple Silicon M1 chip or later)
- `kcc_macos_i386_*.*.*.dmg` (older Mac with Intel chip)
The `c2e` and `c2p` versions are command line tools for power users.
@@ -50,33 +51,28 @@ On Mac, right click open to get past the security warning.
For flatpak, Docker, and AppImage versions, refer to the wiki: https://github.com/ciromattia/kcc/wiki/Installation
## FAQ
- [Kindle Scribe cover guide](https://github.com/ciromattia/kcc/issues/508) (also works for older Kindles)
- [Windows 7 support](https://github.com/ciromattia/kcc/issues/678)
## PREREQUISITES
You'll need to install various tools to access important but optional features.
The installation process has been greatly streamlined. No need to add 7z to PATH or locate KindleGen from the internet and put it in a special folder with KCC. Just run it and KCC will tell you what to install.
### 7-Zip
#### Windows 7-Zip
First install 7z from https://www.7-zip.org/ or with command line:
```
winget install --id 7zip.7zip
```
#### macOS 7-Zip/Unar
with [Homebrew](https://brew.sh/) installed
```
brew install p7zip
brew install unar
```
You'll need to install various tools to access important but optional features. Close and re-open KCC to get KCC to detect them.
### KindleGen
#### Windows / macOS KindleGen
Install [Kindle Previewer 3 (KP3)](https://www.amazon.com/Kindle-Previewer/b?ie=UTF8&node=21381691011). KCC will automatically detect KindleGen from it.
Install [Kindle Previewer](https://www.amazon.com/Kindle-Previewer/b?ie=UTF8&node=21381691011) and `kindlegen` will be autodetected from it.
If you have issues detecting it, or use another OS, refer to the wiki: https://github.com/ciromattia/kcc/wiki/Installation#kindlegen
### 7-Zip
This is an optional requirement as of KCC 6.1.0. You only need to install it if 1) you are using advanced features, 2) are using Windows 10 (2017) or earlier, or 3) need to use an older KCC version.
If you need to install it, refer to the wiki: https://github.com/ciromattia/kcc/wiki/Installation#7-zip
## INPUT FORMATS
**KCC** can understand and convert, at the moment, the following input types:
@@ -122,14 +118,15 @@ sudo apt-get install python3 p7zip-full python3-pil python3-psutil python3-slugi
'KoAO': ("Kobo Aura ONE", (1404, 1872), Palette16, 1.8),
'KoN': ("Kobo Nia", (758, 1024), Palette16, 1.8),
'KoC': ("Kobo Clara HD/Kobo Clara 2E", (1072, 1448), Palette16, 1.8),
'KoCC': ("Kobo Clara Colour", (1072, 1448), Palette16, 1.8),
'KoL': ("Kobo Libra H2O/Kobo Libra 2", (1264, 1680), Palette16, 1.8),
'KoLC': ("Kobo Libra Colour", (1264, 1680), Palette16, 1.8),
'KoF': ("Kobo Forma", (1440, 1920), Palette16, 1.8),
'KoS': ("Kobo Sage", (1440, 1920), Palette16, 1.8),
'KoE': ("Kobo Elipsa", (1404, 1872), Palette16, 1.8),
'OTHER': ("Other", (0, 0), Palette16, 1.8),
```
### Standalone `kcc-c2e.py` usage:
```
@@ -210,8 +207,56 @@ OTHER:
-h, --help Show this help message and exit
```
## INSTALL FROM SOURCE
This section is for developers who want to contribute to KCC or power users who want to run the latest code without waiting for an official release.
Easiest to use [GitHub Desktop](https://desktop.github.com) to clone the KCC repo. From GitHub Desktop, click on `Repository` in the toolbar, then `Command Prompt` (Windows)/`Terminal` (Mac) to open a window in the KCC repo.
Depending on your system [Python](https://www.python.org) may be called either `python` or `python3`. We use virtual environments (venv) to manage dependencies.
If you want to edit the code, a good code editor is [VS Code](https://code.visualstudio.com).
If you want to edit the `.ui` files, use [Qt Creator](https://www.qt.io/download-qt-installer-oss), included in **Qt for desktop development**.
Then use the `gen_ui_files` scripts to autogenerate the python UI.
### Windows install from source
One time setup and running for the first time:
```
python -m venv venv
venv\Scripts\activate.bat
pip install -r requirements.txt
python kcc.py
```
Every time you close Command Prompt, you will need to re-activate the virtual environment and re-run:
```
venv\Scripts\activate.bat
python kcc.py
```
### macOS install from source
One time setup and running for the first time:
```
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python kcc.py
```
Every time you close Terminal, you will need to reactivate the virtual environment and re-run:
```
source venv/bin/activate
python kcc.py
```
## CREDITS
**KCC** is made by
**KCC** is made by
- [Ciro Mattia Gonano](http://github.com/ciromattia)
- [Paweł Jastrzębski](http://github.com/AcidWeb)
@@ -246,5 +291,5 @@ The app relies and includes the following scripts:
Please check [wiki page](https://github.com/ciromattia/kcc/wiki/Known-issues).
## COPYRIGHT
Copyright (c) 2012-2023 Ciro Mattia Gonano, Paweł Jastrzębski and Darodi.
Copyright (c) 2012-2023 Ciro Mattia Gonano, Paweł Jastrzębski and Darodi.
**KCC** is released under ISC LICENSE; see [LICENSE.txt](./LICENSE.txt) for further details.

View File

@@ -5,7 +5,7 @@ channels:
dependencies:
- python=3.11
- Pillow>=5.2.0
- psutil>=5.0.0
- psutil>=5.9.5
- python-slugify>=1.2.1
- raven>=6.0.0
- distro
@@ -13,4 +13,4 @@ dependencies:
- pip
- pip:
- mozjpeg-lossless-optimization>=1.1.2
- PyQt5>=5.6.0
- pyside6>=6.5.1

View File

@@ -1,11 +1,3 @@
REM install qt creator
REM conda create -n qtenv python=3.7
REM conda activate qtenv
REM pip install PyQt5
pyuic5 gui/KCC.ui > kindlecomicconverter/KCC_ui.py
pyuic5 gui/MetaEditor.ui > kindlecomicconverter/KCC_ui_editor.py
pyrcc5 gui/KCC.qrc > kindlecomicconverter/KCC_rc.py
pyside6-uic gui/KCC.ui > kindlecomicconverter/KCC_ui.py
pyside6-uic gui/MetaEditor.ui > kindlecomicconverter/KCC_ui_editor.py
pyside6-rcc gui/KCC.qrc > kindlecomicconverter/KCC_rc.py

View File

@@ -1,10 +1,5 @@
#!/bin/sh
# PREPARE PYTHON ENV
# conda create -n pyqt5 python=3.7
# source activate pyqt5
# pip install pyqt5
pyuic5 gui/KCC.ui --from-imports > kindlecomicconverter/KCC_ui.py
pyuic5 gui/MetaEditor.ui --from-imports > kindlecomicconverter/KCC_ui_editor.py
pyrcc5 gui/KCC.qrc > kindlecomicconverter/KCC_rc.py
pyside6-uic gui/KCC.ui --from-imports > kindlecomicconverter/KCC_ui.py
pyside6-uic gui/MetaEditor.ui --from-imports > kindlecomicconverter/KCC_ui_editor.py
pyside6-rcc gui/KCC.qrc > kindlecomicconverter/KCC_rc.py

View File

@@ -37,59 +37,36 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item row="1" column="1">
<widget class="QCheckBox" name="upscaleBox">
<item row="0" column="2">
<widget class="QCheckBox" name="qualityBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - Nothing&lt;br/&gt;&lt;/span&gt;Images smaller than device resolution will not be resized.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - Stretching&lt;br/&gt;&lt;/span&gt;Images smaller than device resolution will be resized. Aspect ratio will be not preserved.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - Upscaling&lt;br/&gt;&lt;/span&gt;Images smaller than device resolution will be resized. Aspect ratio will be preserved.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - 4 panels&lt;br/&gt;&lt;/span&gt;Zoom each corner separately.&lt;/p&gt;&lt;p style='white-space:pre'&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - 2 panels&lt;br/&gt;&lt;/span&gt;Zoom only the top and bottom of the page.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - 4 high-quality panels&lt;br/&gt;&lt;/span&gt;Zoom each corner separately. Try to increase the quality of magnification. Check wiki for more details.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Stretch/Upscale</string>
<string>Panel View 4/2/HQ</string>
</property>
<property name="tristate">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="rotateBox">
<item row="4" column="1">
<widget class="QCheckBox" name="deleteBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - Split&lt;br/&gt;&lt;/span&gt;Double page spreads will be cut into two separate pages.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - Rotate and split&lt;br/&gt;&lt;/span&gt;Double page spreads will be displayed twice. First rotated and then split. &lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - Rotate&lt;br/&gt;&lt;/span&gt;Double page spreads will be rotated.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>Delete input file(s) or directory. It's not recoverable!</string>
</property>
<property name="text">
<string>Spread splitter</string>
</property>
<property name="tristate">
<bool>true</bool>
<string>Delete input</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="outputSplit">
<item row="3" column="1">
<widget class="QCheckBox" name="maximizeStrips">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - Automatic mode&lt;br/&gt;&lt;/span&gt;The output will be split automatically.&lt;/p&gt;&lt;p style='white-space:pre'&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - Volume mode&lt;br/&gt;&lt;/span&gt;Every subdirectory will be considered as a separate volume.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - 1x4&lt;br/&gt;&lt;/span&gt;Keep format 1x4 panels strips.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - 2x2&lt;br/&gt;&lt;/span&gt;Turn 1x4 strips to 2x2 to maximize screen usage.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Output split</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="webtoonBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Enable special parsing mode for Korean Webtoons.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Webtoon mode</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QCheckBox" name="colorBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Disable conversion to grayscale.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Color mode</string>
<string>1x4 to 2x2 strips</string>
</property>
</widget>
</item>
@@ -116,6 +93,29 @@
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="webtoonBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Enable special parsing mode for Korean Webtoons.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Webtoon mode</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="upscaleBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - Nothing&lt;br/&gt;&lt;/span&gt;Images smaller than device resolution will not be resized.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - Stretching&lt;br/&gt;&lt;/span&gt;Images smaller than device resolution will be resized. Aspect ratio will be not preserved.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - Upscaling&lt;br/&gt;&lt;/span&gt;Images smaller than device resolution will be resized. Aspect ratio will be preserved.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Stretch/Upscale</string>
</property>
<property name="tristate">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="mangaBox">
<property name="toolTip">
@@ -126,42 +126,19 @@
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QCheckBox" name="qualityBox">
<item row="0" column="1">
<widget class="QCheckBox" name="rotateBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - 4 panels&lt;br/&gt;&lt;/span&gt;Zoom each corner separately.&lt;/p&gt;&lt;p style='white-space:pre'&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - 2 panels&lt;br/&gt;&lt;/span&gt;Zoom only the top and bottom of the page.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - 4 high-quality panels&lt;br/&gt;&lt;/span&gt;Zoom each corner separately. Try to increase the quality of magnification. Check wiki for more details.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - Split&lt;br/&gt;&lt;/span&gt;Double page spreads will be cut into two separate pages.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - Rotate and split&lt;br/&gt;&lt;/span&gt;Double page spreads will be displayed twice. First rotated and then split. &lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - Rotate&lt;br/&gt;&lt;/span&gt;Double page spreads will be rotated.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Panel View 4/2/HQ</string>
<string>Spread splitter</string>
</property>
<property name="tristate">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="mozJpegBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - JPEG&lt;br/&gt;&lt;/span&gt;Use JPEG files&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - force PNG&lt;br/&gt;&lt;/span&gt;Create PNG files instead JPEG&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - mozJpeg&lt;br/&gt;&lt;/span&gt;10-20% smaller JPEG file, with the same image quality, but processing time multiplied by 2&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>JPEG/PNG/mozJpeg</string>
</property>
<property name="tristate">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="maximizeStrips">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - 1x4&lt;br/&gt;&lt;/span&gt;Keep format 1x4 panels strips.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - 2x2&lt;br/&gt;&lt;/span&gt;Turn 1x4 strips to 2x2 to maximize screen usage.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>1x4 to 2x2 strips</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QCheckBox" name="croppingBox">
<property name="toolTip">
@@ -175,13 +152,36 @@
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QCheckBox" name="deleteBox">
<item row="2" column="1">
<widget class="QCheckBox" name="outputSplit">
<property name="toolTip">
<string>Delete input file(s) or directory. It's not recoverable!</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - Automatic mode&lt;br/&gt;&lt;/span&gt;The output will be split automatically.&lt;/p&gt;&lt;p style='white-space:pre'&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - Volume mode&lt;br/&gt;&lt;/span&gt;Every subdirectory will be considered as a separate volume.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Delete input</string>
<string>Output split</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="mozJpegBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - JPEG&lt;br/&gt;&lt;/span&gt;Use JPEG files&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - force PNG&lt;br/&gt;&lt;/span&gt;Create PNG files instead JPEG&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - mozJpeg&lt;br/&gt;&lt;/span&gt;10-20% smaller JPEG file, with the same image quality, but processing time multiplied by 2&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>JPEG/PNG/mozJpeg</string>
</property>
<property name="tristate">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QCheckBox" name="colorBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Disable conversion to grayscale.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Color mode</string>
</property>
</widget>
</item>
@@ -195,6 +195,16 @@
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="dedupeCoverBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Don't duplicate the first page as the cover. Useful for 2 page spread alignment.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>De-dupe cover</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>

5
kcc.py
View File

@@ -50,7 +50,12 @@ elif sys.platform.startswith('win'):
win_paths = [
os.path.expandvars('%LOCALAPPDATA%\\Amazon\\KC2'),
os.path.expandvars('%LOCALAPPDATA%\\Amazon\\Kindle Previewer 3\\lib\\fc\\bin\\'),
'C:\\Apps\\Kindle Previewer 3\\lib\\fc\\bin',
'D:\\Apps\\Kindle Previewer 3\\lib\\fc\\bin',
'E:\\Apps\\Kindle Previewer 3\\lib\\fc\\bin',
'C:\\Program Files\\7-Zip',
'D:\\Program Files\\7-Zip',
'E:\\Program Files\\7-Zip',
]
if getattr(sys, 'frozen', False):
os.environ['PATH'] += os.pathsep + os.pathsep.join(win_paths)

View File

@@ -1,39 +0,0 @@
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(['kcc.py'],
pathex=['.'],
binaries=[],
datas=[],
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='kcc',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=False,
upx_exclude=[],
runtime_tmpdir=None,
console=False,
disable_windowed_traceback=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None , icon='icons\\comic2ebook.ico')

View File

@@ -18,7 +18,6 @@
# PERFORMANCE OF THIS SOFTWARE.
import os
import re
import subprocess
import sys
from urllib.parse import unquote
from time import sleep
@@ -27,14 +26,16 @@ from subprocess import STDOUT, PIPE
import requests
# noinspection PyUnresolvedReferences
from PyQt5 import QtGui, QtCore, QtWidgets, QtNetwork
from PySide6 import QtGui, QtCore, QtWidgets, QtNetwork
from PySide6.QtCore import Qt
from xml.sax.saxutils import escape
from psutil import Process
from copy import copy
from distutils.version import StrictVersion
from raven import Client
from tempfile import gettempdir
from .shared import md5Checksum, HTMLStripper, sanitizeTrace, walkLevel, subprocess_run_silent
from .shared import HTMLStripper, sanitizeTrace, walkLevel, subprocess_run_silent
from . import __version__
from . import comic2ebook
from . import metadata
@@ -44,7 +45,7 @@ from . import KCC_ui_editor
class QApplicationMessaging(QtWidgets.QApplication):
messageFromOtherInstance = QtCore.pyqtSignal(bytes)
messageFromOtherInstance = QtCore.Signal(bytes)
def __init__(self, argv):
QtWidgets.QApplication.__init__(self, argv)
@@ -52,7 +53,7 @@ class QApplicationMessaging(QtWidgets.QApplication):
self._timeout = 1000
self._locked = False
socket = QtNetwork.QLocalSocket(self)
socket.connectToServer(self._key, QtCore.QIODevice.WriteOnly)
socket.connectToServer(self._key, QtCore.QIODeviceBase.OpenModeFlag.WriteOnly)
if not socket.waitForConnected(self._timeout):
self._server = QtNetwork.QLocalServer(self)
self._server.newConnection.connect(self.handleMessage)
@@ -66,7 +67,7 @@ class QApplicationMessaging(QtWidgets.QApplication):
self._server.close()
def event(self, e):
if e.type() == QtCore.QEvent.FileOpen:
if e.type() == QtCore.QEvent.Type.FileOpen:
self.messageFromOtherInstance.emit(bytes(e.file(), 'UTF-8'))
return True
else:
@@ -82,7 +83,7 @@ class QApplicationMessaging(QtWidgets.QApplication):
def sendMessage(self, message):
socket = QtNetwork.QLocalSocket(self)
socket.connectToServer(self._key, QtCore.QIODevice.WriteOnly)
socket.connectToServer(self._key, QtCore.QIODeviceBase.OpenModeFlag.WriteOnly)
socket.waitForConnected(self._timeout)
socket.write(bytes(message, 'UTF-8'))
socket.waitForBytesWritten(self._timeout)
@@ -90,40 +91,40 @@ class QApplicationMessaging(QtWidgets.QApplication):
class QMainWindowKCC(QtWidgets.QMainWindow):
progressBarTick = QtCore.pyqtSignal(str)
modeConvert = QtCore.pyqtSignal(int)
addMessage = QtCore.pyqtSignal(str, str, bool)
addTrayMessage = QtCore.pyqtSignal(str, str)
showDialog = QtCore.pyqtSignal(str, str)
hideProgressBar = QtCore.pyqtSignal()
forceShutdown = QtCore.pyqtSignal()
progressBarTick = QtCore.Signal(str)
modeConvert = QtCore.Signal(int)
addMessage = QtCore.Signal(str, str, bool)
addTrayMessage = QtCore.Signal(str, str)
showDialog = QtCore.Signal(str, str)
hideProgressBar = QtCore.Signal()
forceShutdown = QtCore.Signal()
class Icons:
def __init__(self):
self.deviceKindle = QtGui.QIcon()
self.deviceKindle.addPixmap(QtGui.QPixmap(":/Devices/icons/Kindle.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.deviceKindle.addPixmap(QtGui.QPixmap(":/Devices/icons/Kindle.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off)
self.deviceKobo = QtGui.QIcon()
self.deviceKobo.addPixmap(QtGui.QPixmap(":/Devices/icons/Kobo.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.deviceKobo.addPixmap(QtGui.QPixmap(":/Devices/icons/Kobo.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off)
self.deviceOther = QtGui.QIcon()
self.deviceOther.addPixmap(QtGui.QPixmap(":/Devices/icons/Other.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.deviceOther.addPixmap(QtGui.QPixmap(":/Devices/icons/Other.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off)
self.MOBIFormat = QtGui.QIcon()
self.MOBIFormat.addPixmap(QtGui.QPixmap(":/Formats/icons/MOBI.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.MOBIFormat.addPixmap(QtGui.QPixmap(":/Formats/icons/MOBI.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off)
self.CBZFormat = QtGui.QIcon()
self.CBZFormat.addPixmap(QtGui.QPixmap(":/Formats/icons/CBZ.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.CBZFormat.addPixmap(QtGui.QPixmap(":/Formats/icons/CBZ.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off)
self.EPUBFormat = QtGui.QIcon()
self.EPUBFormat.addPixmap(QtGui.QPixmap(":/Formats/icons/EPUB.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.EPUBFormat.addPixmap(QtGui.QPixmap(":/Formats/icons/EPUB.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off)
self.info = QtGui.QIcon()
self.info.addPixmap(QtGui.QPixmap(":/Status/icons/info.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.info.addPixmap(QtGui.QPixmap(":/Status/icons/info.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off)
self.warning = QtGui.QIcon()
self.warning.addPixmap(QtGui.QPixmap(":/Status/icons/warning.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.warning.addPixmap(QtGui.QPixmap(":/Status/icons/warning.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off)
self.error = QtGui.QIcon()
self.error.addPixmap(QtGui.QPixmap(":/Status/icons/error.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.error.addPixmap(QtGui.QPixmap(":/Status/icons/error.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off)
self.programIcon = QtGui.QIcon()
self.programIcon.addPixmap(QtGui.QPixmap(":/Icon/icons/comic2ebook.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.programIcon.addPixmap(QtGui.QPixmap(":/Icon/icons/comic2ebook.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off)
class VersionThread(QtCore.QThread):
@@ -220,28 +221,28 @@ class WorkerThread(QtCore.QThread):
options.format = gui_current_format
if GUI.mangaBox.isChecked():
options.righttoleft = True
if GUI.rotateBox.checkState() == 1:
if GUI.rotateBox.checkState() == Qt.CheckState.PartiallyChecked:
options.splitter = 2
elif GUI.rotateBox.checkState() == 2:
elif GUI.rotateBox.checkState() == Qt.CheckState.Checked:
options.splitter = 1
if GUI.qualityBox.checkState() == 1:
if GUI.qualityBox.checkState() == Qt.CheckState.PartiallyChecked:
options.autoscale = True
elif GUI.qualityBox.checkState() == 2:
elif GUI.qualityBox.checkState() == Qt.CheckState.Checked:
options.hq = True
if GUI.webtoonBox.isChecked():
options.webtoon = True
if GUI.upscaleBox.checkState() == 1:
if GUI.upscaleBox.checkState() == Qt.CheckState.PartiallyChecked:
options.stretch = True
elif GUI.upscaleBox.checkState() == 2:
elif GUI.upscaleBox.checkState() == Qt.CheckState.Checked:
options.upscale = True
if GUI.gammaBox.isChecked() and float(GUI.gammaValue) > 0.09:
options.gamma = float(GUI.gammaValue)
options.cropping = GUI.croppingBox.checkState()
if GUI.croppingBox.checkState() >= 1:
options.cropping = GUI.croppingBox.checkState().value
if GUI.croppingBox.checkState() != Qt.CheckState.Unchecked:
options.croppingp = float(GUI.croppingPowerValue)
if GUI.borderBox.checkState() == 1:
if GUI.borderBox.checkState() == Qt.CheckState.PartiallyChecked:
options.white_borders = True
elif GUI.borderBox.checkState() == 2:
elif GUI.borderBox.checkState() == Qt.CheckState.Checked:
options.black_borders = True
if GUI.outputSplit.isChecked():
options.batchsplit = 2
@@ -253,13 +254,17 @@ class WorkerThread(QtCore.QThread):
options.noprocessing = True
if GUI.deleteBox.isChecked():
options.delete = True
if GUI.mozJpegBox.checkState() == 1:
if GUI.dedupeCoverBox.isChecked():
options.dedupecover = True
if GUI.mozJpegBox.checkState() == Qt.CheckState.PartiallyChecked:
options.forcepng = True
elif GUI.mozJpegBox.checkState() == 2:
elif GUI.mozJpegBox.checkState() == Qt.CheckState.Checked:
options.mozjpeg = True
if GUI.currentMode > 2:
options.customwidth = str(GUI.widthBox.value())
options.customheight = str(GUI.heightBox.value())
if GUI.targetDirectory != '':
options.output = GUI.targetDirectory
for i in range(GUI.jobList.count()):
# Make sure that we don't consider any system message as job to do
@@ -428,7 +433,7 @@ class SystemTrayIcon(QtWidgets.QSystemTrayIcon):
def __init__(self):
super().__init__()
if self.isSystemTrayAvailable():
QtWidgets.QSystemTrayIcon.__init__(self, GUI.icons.programIcon, MW)
self.setIcon(GUI.icons.programIcon)
self.activated.connect(self.catchClicks)
def catchClicks(self):
@@ -437,7 +442,7 @@ class SystemTrayIcon(QtWidgets.QSystemTrayIcon):
MW.activateWindow()
def addTrayMessage(self, message, icon):
icon = eval('QtWidgets.QSystemTrayIcon.' + icon)
icon = getattr(QtWidgets.QSystemTrayIcon.MessageIcon, icon)
if self.supportsMessages() and not MW.isActiveWindow():
self.showMessage('Kindle Comic Converter', message, icon)
@@ -459,7 +464,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
if self.needClean:
self.needClean = False
GUI.jobList.clear()
if self.sevenzip:
if self.tar or self.sevenzip:
fnames = QtWidgets.QFileDialog.getOpenFileNames(MW, 'Select file', self.lastPath,
'Comic (*.cbz *.cbr *.cb7 *.zip *.rar *.7z *.pdf);;All (*.*)')
else:
@@ -489,6 +494,8 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
else:
fname = ['']
self.showDialog("Editor is disabled due to a lack of 7z.", 'error')
self.addMessage('<a href="https://github.com/ciromattia/kcc#7-zip">Install 7z (link)</a>'
' to enable metadata editing.', 'warning')
if fname[0] != '':
if sys.platform.startswith('win'):
sname = fname[0].replace('/', '\\')
@@ -547,7 +554,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
self.conversionAlive = False
self.worker.sync()
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/Other/icons/convert.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
icon.addPixmap(QtGui.QPixmap(":/Other/icons/convert.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off)
GUI.convertButton.setIcon(icon)
GUI.convertButton.setText('Convert')
GUI.centralWidget.setAcceptDrops(True)
@@ -555,7 +562,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
self.conversionAlive = True
self.worker.sync()
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/Other/icons/clear.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
icon.addPixmap(QtGui.QPixmap(":/Other/icons/clear.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off)
GUI.convertButton.setIcon(icon)
GUI.convertButton.setText('Abort')
GUI.centralWidget.setAcceptDrops(False)
@@ -635,6 +642,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
self.modeChange(2)
else:
self.modeChange(1)
GUI.colorBox.setChecked(profile['ForceColor'])
self.changeFormat()
GUI.gammaSlider.setValue(0)
self.changeGamma(0)
@@ -669,7 +677,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
def addMessage(self, message, icon, replace=False):
if icon != '':
icon = eval('self.icons.' + icon)
icon = getattr(self.icons, icon)
item = QtWidgets.QListWidgetItem(icon, ' ' + self.stripTags(message))
else:
item = QtWidgets.QListWidgetItem(' ' + self.stripTags(message))
@@ -687,7 +695,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
def showDialog(self, message, kind):
if kind == 'error':
QtWidgets.QMessageBox.critical(MW, 'KCC - Error', message, QtWidgets.QMessageBox.Ok)
QtWidgets.QMessageBox.critical(MW, 'KCC - Error', message, QtWidgets.QMessageBox.StandardButton.Ok)
elif kind == 'question':
GUI.versionCheck.setAnswer(QtWidgets.QMessageBox.question(MW, 'KCC - Question', message,
QtWidgets.QMessageBox.Yes,
@@ -715,7 +723,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
self.conversionAlive = False
self.worker.sync()
else:
if QtWidgets.QApplication.keyboardModifiers() == QtCore.Qt.ShiftModifier:
if QtWidgets.QApplication.keyboardModifiers() == QtCore.Qt.KeyboardModifier.ShiftModifier:
dname = QtWidgets.QFileDialog.getExistingDirectory(MW, 'Select output directory', self.lastPath)
if dname != '':
if sys.platform.startswith('win'):
@@ -749,7 +757,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
def display_kindlegen_missing(self):
self.addMessage(
'<a href="https://github.com/ciromattia/kcc#kindlegen"><b>Install KindleGen (link)</b></a> to enable MOBI conversion for Kindles!',
'<a href="https://github.com/ciromattia/kcc#kindlegen"><b>Install KindleGen (link)</b></a> to enable MOBI conversion for Kindles!',
'error'
)
@@ -768,23 +776,24 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
self.settings.setValue('currentFormat', GUI.formatBox.currentIndex())
self.settings.setValue('startNumber', self.startNumber + 1)
self.settings.setValue('windowSize', str(MW.size().width()) + 'x' + str(MW.size().height()))
self.settings.setValue('options', {'mangaBox': GUI.mangaBox.checkState(),
'rotateBox': GUI.rotateBox.checkState(),
'qualityBox': GUI.qualityBox.checkState(),
'gammaBox': GUI.gammaBox.checkState(),
'croppingBox': GUI.croppingBox.checkState(),
self.settings.setValue('options', {'mangaBox': GUI.mangaBox.checkState().value,
'rotateBox': GUI.rotateBox.checkState().value,
'qualityBox': GUI.qualityBox.checkState().value,
'gammaBox': GUI.gammaBox.checkState().value,
'croppingBox': GUI.croppingBox.checkState().value,
'croppingPowerSlider': float(self.croppingPowerValue) * 100,
'upscaleBox': GUI.upscaleBox.checkState(),
'borderBox': GUI.borderBox.checkState(),
'webtoonBox': GUI.webtoonBox.checkState(),
'outputSplit': GUI.outputSplit.checkState(),
'colorBox': GUI.colorBox.checkState(),
'disableProcessingBox': GUI.disableProcessingBox.checkState(),
'mozJpegBox': GUI.mozJpegBox.checkState(),
'upscaleBox': GUI.upscaleBox.checkState().value,
'borderBox': GUI.borderBox.checkState().value,
'webtoonBox': GUI.webtoonBox.checkState().value,
'outputSplit': GUI.outputSplit.checkState().value,
'colorBox': GUI.colorBox.checkState().value,
'disableProcessingBox': GUI.disableProcessingBox.checkState().value,
'mozJpegBox': GUI.mozJpegBox.checkState().value,
'widthBox': GUI.widthBox.value(),
'heightBox': GUI.heightBox.value(),
'deleteBox': GUI.deleteBox.checkState(),
'maximizeStrips': GUI.maximizeStrips.checkState(),
'deleteBox': GUI.deleteBox.checkState().value,
'dedupeCoverBox': GUI.dedupeCoverBox.checkState().value,
'maximizeStrips': GUI.maximizeStrips.checkState().value,
'gammaSlider': float(self.gammaValue) * 100})
self.settings.sync()
self.tray.hide()
@@ -799,7 +808,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
self.needClean = False
GUI.jobList.clear()
formats = ['.pdf']
if self.sevenzip:
if self.tar or self.sevenzip:
formats.extend(['.cb7', '.7z', '.cbz', '.zip', '.cbr', '.rar'])
if os.path.isdir(message):
GUI.jobList.addItem(message)
@@ -859,7 +868,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
self.setupUi(MW)
self.editor = KCCGUI_MetaEditor()
self.icons = Icons()
self.settings = QtCore.QSettings('KindleComicConverter', 'KindleComicConverter')
self.settings = QtCore.QSettings('ciromattia', 'kcc')
self.settingsVersion = self.settings.value('settingsVersion', '', type=str)
self.lastPath = self.settings.value('lastPath', '', type=str)
self.lastDevice = self.settings.value('lastDevice', 0, type=int)
@@ -892,10 +901,10 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
elif sys.platform.startswith('darwin'):
for element in ['editorButton', 'wikiButton', 'directoryButton', 'clearButton', 'fileButton', 'deviceBox',
'convertButton', 'formatBox']:
eval('GUI.' + element).setMinimumSize(QtCore.QSize(0, 0))
getattr(GUI, element).setMinimumSize(QtCore.QSize(0, 0))
GUI.gridLayout.setContentsMargins(-1, -1, -1, -1)
for element in ['gridLayout_2', 'gridLayout_3', 'gridLayout_4', 'horizontalLayout', 'horizontalLayout_2']:
eval('GUI.' + element).setContentsMargins(-1, 0, -1, 0)
getattr(GUI, element).setContentsMargins(-1, 0, -1, 0)
if self.windowSize == '0x0':
MW.resize(500, 500)
@@ -910,94 +919,100 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
self.profiles = {
"Kindle Oasis 2/3": {'PVOptions': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': True, 'Label': 'KO'},
"Kindle Oasis": {'PVOptions': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': True, 'Label': 'KV'},
"Kindle Oasis 9/10": {'PVOptions': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': True, 'ForceColor': False, 'Label': 'KO'},
"Kindle Oasis 8": {'PVOptions': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': True, 'ForceColor': False, 'Label': 'KV'},
"Kindle Voyage": {'PVOptions': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': True, 'Label': 'KV'},
'DefaultUpscale': True, 'ForceColor': False, 'Label': 'KV'},
"Kindle Scribe": {
'PVOptions': True, 'ForceExpert': False, 'DefaultFormat': 0, 'DefaultUpscale': False, 'Label': 'KS',
'PVOptions': True, 'ForceExpert': False, 'DefaultFormat': 0, 'DefaultUpscale': False, 'ForceColor': False, 'Label': 'KS',
},
"Kindle 11": {
'PVOptions': True, 'ForceExpert': False, 'DefaultFormat': 0, 'DefaultUpscale': True, 'Label': 'K11',
'PVOptions': True, 'ForceExpert': False, 'DefaultFormat': 0, 'DefaultUpscale': True, 'ForceColor': False, 'Label': 'K11',
},
"Kindle PW 5": {
'PVOptions': True, 'ForceExpert': False, 'DefaultFormat': 0, 'DefaultUpscale': True, 'Label': 'KPW5',
"Kindle PW 11": {
'PVOptions': True, 'ForceExpert': False, 'DefaultFormat': 0, 'DefaultUpscale': True, 'ForceColor': False, 'Label': 'KPW5',
},
"Kindle PW 3/4": {'PVOptions': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': True, 'Label': 'KV'},
"Kindle PW 1/2": {'PVOptions': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': False, 'Label': 'KPW'},
"Kindle PW 7/10": {'PVOptions': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': True, 'ForceColor': False, 'Label': 'KV'},
"Kindle PW 5/6": {'PVOptions': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': False, 'ForceColor': False, 'Label': 'KPW'},
"Kindle 4/5/7/8/10": {'PVOptions': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': False, 'Label': 'K578'},
"Kindle DX/DXG": {'PVOptions': False, 'ForceExpert': False, 'DefaultFormat': 2,
'DefaultUpscale': False, 'Label': 'KDX'},
'DefaultUpscale': False, 'ForceColor': False, 'Label': 'K578'},
"Kindle DX": {'PVOptions': False, 'ForceExpert': False, 'DefaultFormat': 2,
'DefaultUpscale': False, 'ForceColor': False, 'Label': 'KDX'},
"Kobo Mini/Touch": {'PVOptions': False, 'ForceExpert': False, 'DefaultFormat': 1,
'DefaultUpscale': False, 'Label': 'KoMT'},
'DefaultUpscale': False, 'ForceColor': False, 'Label': 'KoMT'},
"Kobo Glo": {'PVOptions': False, 'ForceExpert': False, 'DefaultFormat': 1,
'DefaultUpscale': False, 'Label': 'KoG'},
'DefaultUpscale': False, 'ForceColor': False, 'Label': 'KoG'},
"Kobo Glo HD": {'PVOptions': False, 'ForceExpert': False, 'DefaultFormat': 1,
'DefaultUpscale': False, 'Label': 'KoGHD'},
'DefaultUpscale': False, 'ForceColor': False, 'Label': 'KoGHD'},
"Kobo Aura": {'PVOptions': False, 'ForceExpert': False, 'DefaultFormat': 1,
'DefaultUpscale': False, 'Label': 'KoA'},
'DefaultUpscale': False, 'ForceColor': False, 'Label': 'KoA'},
"Kobo Aura HD": {'PVOptions': False, 'ForceExpert': False, 'DefaultFormat': 1,
'DefaultUpscale': True, 'Label': 'KoAHD'},
'DefaultUpscale': True, 'ForceColor': False, 'Label': 'KoAHD'},
"Kobo Aura H2O": {'PVOptions': False, 'ForceExpert': False, 'DefaultFormat': 1,
'DefaultUpscale': True, 'Label': 'KoAH2O'},
'DefaultUpscale': True, 'ForceColor': False, 'Label': 'KoAH2O'},
"Kobo Aura ONE": {'PVOptions': False, 'ForceExpert': False, 'DefaultFormat': 1,
'DefaultUpscale': True, 'Label': 'KoAO'},
'DefaultUpscale': True, 'ForceColor': False, 'Label': 'KoAO'},
"Kobo Clara HD": {'PVOptions': False, 'ForceExpert': False, 'DefaultFormat': 1,
'DefaultUpscale': True, 'Label': 'KoC'},
'DefaultUpscale': True, 'ForceColor': False, 'Label': 'KoC'},
"Kobo Libra H2O": {'PVOptions': False, 'ForceExpert': False, 'DefaultFormat': 1,
'DefaultUpscale': True, 'Label': 'KoL'},
'DefaultUpscale': True, 'ForceColor': False, 'Label': 'KoL'},
"Kobo Forma": {'PVOptions': False, 'ForceExpert': False, 'DefaultFormat': 1,
'DefaultUpscale': True, 'Label': 'KoF'},
'DefaultUpscale': True, 'ForceColor': False, 'Label': 'KoF'},
"Kindle 1": {'PVOptions': False, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': False, 'Label': 'K1'},
'DefaultUpscale': False, 'ForceColor': False, 'Label': 'K1'},
"Kindle 2": {'PVOptions': False, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': False, 'Label': 'K2'},
'DefaultUpscale': False, 'ForceColor': False, 'Label': 'K2'},
"Kindle Keyboard": {'PVOptions': False, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': False, 'Label': 'K34'},
'DefaultUpscale': False, 'ForceColor': False, 'Label': 'K34'},
"Kindle Touch": {'PVOptions': False, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': False, 'Label': 'K34'},
"Kobo Nia": {'PVOptions': False, 'ForceExpert': False, 'DefaultFormat': 1, 'DefaultUpscale': True,
'DefaultUpscale': False, 'ForceColor': False, 'Label': 'K34'},
"Kobo Nia": {'PVOptions': False, 'ForceExpert': False, 'DefaultFormat': 1, 'DefaultUpscale': True, 'ForceColor': False,
'Label': 'KoN'},
"Kobo Clara 2E": {'PVOptions': False, 'ForceExpert': False, 'DefaultFormat': 1, 'DefaultUpscale': True,
"Kobo Clara 2E": {'PVOptions': False, 'ForceExpert': False, 'DefaultFormat': 1, 'DefaultUpscale': True, 'ForceColor': False,
'Label': 'KoC'},
"Kobo Libra 2": {'PVOptions': False, 'ForceExpert': False, 'DefaultFormat': 1, 'DefaultUpscale': True,
"Kobo Clara Colour": {'PVOptions': False, 'ForceExpert': False, 'DefaultFormat': 1, 'DefaultUpscale': True, 'ForceColor': True,
'Label': 'KoCC'},
"Kobo Libra 2": {'PVOptions': False, 'ForceExpert': False, 'DefaultFormat': 1, 'DefaultUpscale': True, 'ForceColor': False,
'Label': 'KoL'},
"Kobo Sage": {'PVOptions': False, 'ForceExpert': False, 'DefaultFormat': 1, 'DefaultUpscale': True,
"Kobo Libra Colour": {'PVOptions': False, 'ForceExpert': False, 'DefaultFormat': 1, 'DefaultUpscale': True, 'ForceColor': True,
'Label': 'KoLC'},
"Kobo Sage": {'PVOptions': False, 'ForceExpert': False, 'DefaultFormat': 1, 'DefaultUpscale': True, 'ForceColor': False,
'Label': 'KoS'},
"Kobo Elipsa": {'PVOptions': False, 'ForceExpert': False, 'DefaultFormat': 1, 'DefaultUpscale': True,
"Kobo Elipsa": {'PVOptions': False, 'ForceExpert': False, 'DefaultFormat': 1, 'DefaultUpscale': True, 'ForceColor': False,
'Label': 'KoE'},
"Other": {'PVOptions': False, 'ForceExpert': True, 'DefaultFormat': 1, 'DefaultUpscale': False,
"Other": {'PVOptions': False, 'ForceExpert': True, 'DefaultFormat': 1, 'DefaultUpscale': False, 'ForceColor': False,
'Label': 'OTHER'},
}
profilesGUI = [
"Kindle Oasis 2/3",
"Kindle PW 5",
"Kindle 11",
"Kindle Scribe",
"Kindle 11",
"Kindle PW 11",
"Kindle Oasis 9/10",
"Separator",
"Kobo Clara 2E",
"Kobo Clara Colour",
"Kobo Sage",
"Kobo Libra 2",
"Kobo Libra Colour",
"Kobo Elipsa",
"Kobo Nia",
"Separator",
"Other",
"Separator",
"Kindle Oasis",
"Kindle Oasis 8",
"Kindle PW 7/10",
"Kindle Voyage",
"Kindle PW 5/6",
"Kindle 4/5/7/8/10",
"Kindle Touch",
"Kindle Keyboard",
"Kindle DX/DXG",
"Kindle PW 3/4",
"Kindle PW 1/2",
"Kindle Voyage",
"Kindle DX",
"Kindle 2",
"Kindle 1",
"Kindle 4/5/7/8/10",
"Separator",
"Kobo Aura",
"Kobo Aura ONE",
@@ -1015,7 +1030,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
'com/ciromattia/kcc/blob/master/README.md#issues--new-features--donations">DO'
'NATE</a> - <a href="http://www.mobileread.com/forums/showthread.php?t=207461'
'">FORUM</a></b>')
statusBarLabel.setAlignment(QtCore.Qt.AlignCenter)
statusBarLabel.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
statusBarLabel.setOpenExternalLinks(True)
GUI.statusBar.addPermanentWidget(statusBarLabel, 1)
@@ -1025,13 +1040,19 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
self.addMessage('Since you are a new user of <b>KCC</b> please see few '
'<a href="https://github.com/ciromattia/kcc/wiki/Important-tips">important tips</a>.',
'info')
try:
subprocess_run_silent(['tar'], stdout=PIPE, stderr=STDOUT)
self.tar = True
except FileNotFoundError:
self.tar = False
try:
subprocess_run_silent(['7z'], stdout=PIPE, stderr=STDOUT)
self.sevenzip = True
except FileNotFoundError:
self.sevenzip = False
self.addMessage('<a href="https://github.com/ciromattia/kcc#7-zip">Install 7z (link)</a>'
' to enable CBZ/CBR/ZIP/etc processing.', 'warning')
if not self.tar:
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)
@@ -1073,7 +1094,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
else:
GUI.deviceBox.addItem(self.icons.deviceKindle, profile)
for f in self.formats:
GUI.formatBox.addItem(eval('self.icons.' + self.formats[f]['icon'] + 'Format'), f)
GUI.formatBox.addItem(getattr(self.icons, self.formats[f]['icon'] + 'Format'), f)
if self.lastDevice > GUI.deviceBox.count():
self.lastDevice = 0
if profilesGUI[self.lastDevice] == "Separator":
@@ -1099,8 +1120,8 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
self.changeCroppingPower(int(self.options[option]))
else:
try:
if eval('GUI.' + str(option)).isEnabled():
eval('GUI.' + str(option)).setCheckState(self.options[option])
if getattr(GUI, option).isEnabled():
getattr(GUI, option).setCheckState(Qt.CheckState(self.options[option]))
except AttributeError:
pass
self.worker.sync()
@@ -1174,7 +1195,7 @@ class KCCGUI_MetaEditor(KCC_ui_editor.Ui_editorDialog):
self.ui = QtWidgets.QDialog()
self.parser = None
self.setupUi(self.ui)
self.ui.setWindowFlags(self.ui.windowFlags() & ~QtCore.Qt.WindowContextHelpButtonHint)
self.ui.setWindowFlags(self.ui.windowFlags() & ~QtCore.Qt.WindowType.WindowContextHelpButtonHint)
self.okButton.clicked.connect(self.saveData)
self.cancelButton.clicked.connect(self.ui.close)
if sys.platform.startswith('linux'):

File diff suppressed because it is too large Load Diff

View File

@@ -1,321 +1,463 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'gui/KCC.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
################################################################################
## Form generated from reading UI file 'KCC.ui'
##
## Created by: Qt User Interface Compiler version 6.5.2
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################
from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
QMetaObject, QObject, QPoint, QRect,
QSize, QTime, QUrl, Qt)
from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
QFont, QFontDatabase, QGradient, QIcon,
QImage, QKeySequence, QLinearGradient, QPainter,
QPalette, QPixmap, QRadialGradient, QTransform)
from PySide6.QtWidgets import (QAbstractItemView, QApplication, QCheckBox, QComboBox,
QGridLayout, QHBoxLayout, QLabel, QListWidget,
QListWidgetItem, QMainWindow, QProgressBar, QPushButton,
QSizePolicy, QSlider, QSpinBox, QStatusBar,
QWidget)
from . import KCC_rc
class Ui_mainWindow(object):
def setupUi(self, mainWindow):
mainWindow.setObjectName("mainWindow")
if not mainWindow.objectName():
mainWindow.setObjectName(u"mainWindow")
mainWindow.resize(450, 400)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/Icon/icons/comic2ebook.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
icon = QIcon()
icon.addFile(u":/Icon/icons/comic2ebook.png", QSize(), QIcon.Normal, QIcon.Off)
mainWindow.setWindowIcon(icon)
self.centralWidget = QtWidgets.QWidget(mainWindow)
self.centralWidget.setObjectName("centralWidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralWidget)
self.centralWidget = QWidget(mainWindow)
self.centralWidget.setObjectName(u"centralWidget")
self.gridLayout = QGridLayout(self.centralWidget)
self.gridLayout.setObjectName(u"gridLayout")
self.gridLayout.setContentsMargins(-1, -1, -1, 5)
self.gridLayout.setObjectName("gridLayout")
self.optionWidget = QtWidgets.QWidget(self.centralWidget)
self.optionWidget.setObjectName("optionWidget")
self.gridLayout_2 = QtWidgets.QGridLayout(self.optionWidget)
self.optionWidget = QWidget(self.centralWidget)
self.optionWidget.setObjectName(u"optionWidget")
self.gridLayout_2 = QGridLayout(self.optionWidget)
self.gridLayout_2.setObjectName(u"gridLayout_2")
self.gridLayout_2.setContentsMargins(0, 0, 0, 0)
self.gridLayout_2.setObjectName("gridLayout_2")
self.upscaleBox = QtWidgets.QCheckBox(self.optionWidget)
self.upscaleBox.setTristate(True)
self.upscaleBox.setObjectName("upscaleBox")
self.gridLayout_2.addWidget(self.upscaleBox, 1, 1, 1, 1)
self.rotateBox = QtWidgets.QCheckBox(self.optionWidget)
self.rotateBox.setTristate(True)
self.rotateBox.setObjectName("rotateBox")
self.gridLayout_2.addWidget(self.rotateBox, 0, 1, 1, 1)
self.outputSplit = QtWidgets.QCheckBox(self.optionWidget)
self.outputSplit.setObjectName("outputSplit")
self.gridLayout_2.addWidget(self.outputSplit, 2, 1, 1, 1)
self.webtoonBox = QtWidgets.QCheckBox(self.optionWidget)
self.webtoonBox.setObjectName("webtoonBox")
self.gridLayout_2.addWidget(self.webtoonBox, 1, 0, 1, 1)
self.colorBox = QtWidgets.QCheckBox(self.optionWidget)
self.colorBox.setObjectName("colorBox")
self.gridLayout_2.addWidget(self.colorBox, 2, 2, 1, 1)
self.gammaBox = QtWidgets.QCheckBox(self.optionWidget)
self.gammaBox.setObjectName("gammaBox")
self.gridLayout_2.addWidget(self.gammaBox, 1, 2, 1, 1)
self.borderBox = QtWidgets.QCheckBox(self.optionWidget)
self.borderBox.setTristate(True)
self.borderBox.setObjectName("borderBox")
self.gridLayout_2.addWidget(self.borderBox, 2, 0, 1, 1)
self.mangaBox = QtWidgets.QCheckBox(self.optionWidget)
self.mangaBox.setObjectName("mangaBox")
self.gridLayout_2.addWidget(self.mangaBox, 0, 0, 1, 1)
self.qualityBox = QtWidgets.QCheckBox(self.optionWidget)
self.qualityBox = QCheckBox(self.optionWidget)
self.qualityBox.setObjectName(u"qualityBox")
self.qualityBox.setTristate(True)
self.qualityBox.setObjectName("qualityBox")
self.gridLayout_2.addWidget(self.qualityBox, 0, 2, 1, 1)
self.mozJpegBox = QtWidgets.QCheckBox(self.optionWidget)
self.mozJpegBox.setTristate(True)
self.mozJpegBox.setObjectName("mozJpegBox")
self.gridLayout_2.addWidget(self.mozJpegBox, 3, 0, 1, 1)
self.maximizeStrips = QtWidgets.QCheckBox(self.optionWidget)
self.maximizeStrips.setObjectName("maximizeStrips")
self.gridLayout_2.addWidget(self.maximizeStrips, 3, 1, 1, 1)
self.croppingBox = QtWidgets.QCheckBox(self.optionWidget)
self.croppingBox.setTristate(True)
self.croppingBox.setObjectName("croppingBox")
self.gridLayout_2.addWidget(self.croppingBox, 3, 2, 1, 1)
self.deleteBox = QtWidgets.QCheckBox(self.optionWidget)
self.deleteBox.setObjectName("deleteBox")
self.deleteBox = QCheckBox(self.optionWidget)
self.deleteBox.setObjectName(u"deleteBox")
self.gridLayout_2.addWidget(self.deleteBox, 4, 1, 1, 1)
self.disableProcessingBox = QtWidgets.QCheckBox(self.optionWidget)
self.disableProcessingBox.setObjectName("disableProcessingBox")
self.maximizeStrips = QCheckBox(self.optionWidget)
self.maximizeStrips.setObjectName(u"maximizeStrips")
self.gridLayout_2.addWidget(self.maximizeStrips, 3, 1, 1, 1)
self.gammaBox = QCheckBox(self.optionWidget)
self.gammaBox.setObjectName(u"gammaBox")
self.gridLayout_2.addWidget(self.gammaBox, 1, 2, 1, 1)
self.borderBox = QCheckBox(self.optionWidget)
self.borderBox.setObjectName(u"borderBox")
self.borderBox.setTristate(True)
self.gridLayout_2.addWidget(self.borderBox, 2, 0, 1, 1)
self.webtoonBox = QCheckBox(self.optionWidget)
self.webtoonBox.setObjectName(u"webtoonBox")
self.gridLayout_2.addWidget(self.webtoonBox, 1, 0, 1, 1)
self.upscaleBox = QCheckBox(self.optionWidget)
self.upscaleBox.setObjectName(u"upscaleBox")
self.upscaleBox.setTristate(True)
self.gridLayout_2.addWidget(self.upscaleBox, 1, 1, 1, 1)
self.mangaBox = QCheckBox(self.optionWidget)
self.mangaBox.setObjectName(u"mangaBox")
self.gridLayout_2.addWidget(self.mangaBox, 0, 0, 1, 1)
self.rotateBox = QCheckBox(self.optionWidget)
self.rotateBox.setObjectName(u"rotateBox")
self.rotateBox.setTristate(True)
self.gridLayout_2.addWidget(self.rotateBox, 0, 1, 1, 1)
self.croppingBox = QCheckBox(self.optionWidget)
self.croppingBox.setObjectName(u"croppingBox")
self.croppingBox.setTristate(True)
self.gridLayout_2.addWidget(self.croppingBox, 3, 2, 1, 1)
self.outputSplit = QCheckBox(self.optionWidget)
self.outputSplit.setObjectName(u"outputSplit")
self.gridLayout_2.addWidget(self.outputSplit, 2, 1, 1, 1)
self.mozJpegBox = QCheckBox(self.optionWidget)
self.mozJpegBox.setObjectName(u"mozJpegBox")
self.mozJpegBox.setTristate(True)
self.gridLayout_2.addWidget(self.mozJpegBox, 3, 0, 1, 1)
self.colorBox = QCheckBox(self.optionWidget)
self.colorBox.setObjectName(u"colorBox")
self.gridLayout_2.addWidget(self.colorBox, 2, 2, 1, 1)
self.disableProcessingBox = QCheckBox(self.optionWidget)
self.disableProcessingBox.setObjectName(u"disableProcessingBox")
self.gridLayout_2.addWidget(self.disableProcessingBox, 4, 2, 1, 1)
self.dedupeCoverBox = QCheckBox(self.optionWidget)
self.dedupeCoverBox.setObjectName(u"dedupeCoverBox")
self.gridLayout_2.addWidget(self.dedupeCoverBox, 4, 0, 1, 1)
self.gridLayout.addWidget(self.optionWidget, 5, 0, 1, 2)
self.gammaWidget = QtWidgets.QWidget(self.centralWidget)
self.gammaWidget = QWidget(self.centralWidget)
self.gammaWidget.setObjectName(u"gammaWidget")
self.gammaWidget.setVisible(False)
self.gammaWidget.setObjectName("gammaWidget")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.gammaWidget)
self.horizontalLayout_2 = QHBoxLayout(self.gammaWidget)
self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.gammaLabel = QtWidgets.QLabel(self.gammaWidget)
self.gammaLabel.setObjectName("gammaLabel")
self.gammaLabel = QLabel(self.gammaWidget)
self.gammaLabel.setObjectName(u"gammaLabel")
self.horizontalLayout_2.addWidget(self.gammaLabel)
self.gammaSlider = QtWidgets.QSlider(self.gammaWidget)
self.gammaSlider = QSlider(self.gammaWidget)
self.gammaSlider.setObjectName(u"gammaSlider")
self.gammaSlider.setMaximum(250)
self.gammaSlider.setSingleStep(5)
self.gammaSlider.setOrientation(QtCore.Qt.Horizontal)
self.gammaSlider.setObjectName("gammaSlider")
self.gammaSlider.setOrientation(Qt.Horizontal)
self.horizontalLayout_2.addWidget(self.gammaSlider)
self.gridLayout.addWidget(self.gammaWidget, 6, 0, 1, 2)
self.croppingWidget = QtWidgets.QWidget(self.centralWidget)
self.croppingWidget = QWidget(self.centralWidget)
self.croppingWidget.setObjectName(u"croppingWidget")
self.croppingWidget.setVisible(False)
self.croppingWidget.setObjectName("croppingWidget")
self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.croppingWidget)
self.horizontalLayout_3 = QHBoxLayout(self.croppingWidget)
self.horizontalLayout_3.setObjectName(u"horizontalLayout_3")
self.horizontalLayout_3.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.croppingPowerLabel = QtWidgets.QLabel(self.croppingWidget)
self.croppingPowerLabel.setObjectName("croppingPowerLabel")
self.croppingPowerLabel = QLabel(self.croppingWidget)
self.croppingPowerLabel.setObjectName(u"croppingPowerLabel")
self.horizontalLayout_3.addWidget(self.croppingPowerLabel)
self.croppingPowerSlider = QtWidgets.QSlider(self.croppingWidget)
self.croppingPowerSlider = QSlider(self.croppingWidget)
self.croppingPowerSlider.setObjectName(u"croppingPowerSlider")
self.croppingPowerSlider.setMaximum(200)
self.croppingPowerSlider.setSingleStep(1)
self.croppingPowerSlider.setOrientation(QtCore.Qt.Horizontal)
self.croppingPowerSlider.setObjectName("croppingPowerSlider")
self.croppingPowerSlider.setOrientation(Qt.Horizontal)
self.horizontalLayout_3.addWidget(self.croppingPowerSlider)
self.gridLayout.addWidget(self.croppingWidget, 8, 0, 1, 2)
self.buttonWidget = QtWidgets.QWidget(self.centralWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
self.buttonWidget = QWidget(self.centralWidget)
self.buttonWidget.setObjectName(u"buttonWidget")
sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.buttonWidget.sizePolicy().hasHeightForWidth())
self.buttonWidget.setSizePolicy(sizePolicy)
self.buttonWidget.setObjectName("buttonWidget")
self.gridLayout_4 = QtWidgets.QGridLayout(self.buttonWidget)
self.gridLayout_4 = QGridLayout(self.buttonWidget)
self.gridLayout_4.setObjectName(u"gridLayout_4")
self.gridLayout_4.setContentsMargins(0, 0, 0, 0)
self.gridLayout_4.setObjectName("gridLayout_4")
self.directoryButton = QtWidgets.QPushButton(self.buttonWidget)
self.directoryButton.setMinimumSize(QtCore.QSize(0, 30))
icon1 = QtGui.QIcon()
icon1.addPixmap(QtGui.QPixmap(":/Other/icons/folder_new.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.directoryButton = QPushButton(self.buttonWidget)
self.directoryButton.setObjectName(u"directoryButton")
self.directoryButton.setMinimumSize(QSize(0, 30))
icon1 = QIcon()
icon1.addFile(u":/Other/icons/folder_new.png", QSize(), QIcon.Normal, QIcon.Off)
self.directoryButton.setIcon(icon1)
self.directoryButton.setObjectName("directoryButton")
self.gridLayout_4.addWidget(self.directoryButton, 0, 0, 1, 1)
self.fileButton = QtWidgets.QPushButton(self.buttonWidget)
self.fileButton.setMinimumSize(QtCore.QSize(0, 30))
icon2 = QtGui.QIcon()
icon2.addPixmap(QtGui.QPixmap(":/Other/icons/document_new.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.fileButton = QPushButton(self.buttonWidget)
self.fileButton.setObjectName(u"fileButton")
self.fileButton.setMinimumSize(QSize(0, 30))
icon2 = QIcon()
icon2.addFile(u":/Other/icons/document_new.png", QSize(), QIcon.Normal, QIcon.Off)
self.fileButton.setIcon(icon2)
self.fileButton.setObjectName("fileButton")
self.gridLayout_4.addWidget(self.fileButton, 0, 3, 1, 1)
self.deviceBox = QtWidgets.QComboBox(self.buttonWidget)
self.deviceBox.setMinimumSize(QtCore.QSize(0, 28))
self.deviceBox.setObjectName("deviceBox")
self.deviceBox = QComboBox(self.buttonWidget)
self.deviceBox.setObjectName(u"deviceBox")
self.deviceBox.setMinimumSize(QSize(0, 28))
self.gridLayout_4.addWidget(self.deviceBox, 1, 0, 1, 1)
self.formatBox = QtWidgets.QComboBox(self.buttonWidget)
self.formatBox.setMinimumSize(QtCore.QSize(0, 28))
self.formatBox.setObjectName("formatBox")
self.formatBox = QComboBox(self.buttonWidget)
self.formatBox.setObjectName(u"formatBox")
self.formatBox.setMinimumSize(QSize(0, 28))
self.gridLayout_4.addWidget(self.formatBox, 1, 3, 1, 1)
self.convertButton = QtWidgets.QPushButton(self.buttonWidget)
self.convertButton.setMinimumSize(QtCore.QSize(0, 30))
font = QtGui.QFont()
self.convertButton = QPushButton(self.buttonWidget)
self.convertButton.setObjectName(u"convertButton")
self.convertButton.setMinimumSize(QSize(0, 30))
font = QFont()
font.setBold(True)
self.convertButton.setFont(font)
icon3 = QtGui.QIcon()
icon3.addPixmap(QtGui.QPixmap(":/Other/icons/convert.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
icon3 = QIcon()
icon3.addFile(u":/Other/icons/convert.png", QSize(), QIcon.Normal, QIcon.Off)
self.convertButton.setIcon(icon3)
self.convertButton.setObjectName("convertButton")
self.gridLayout_4.addWidget(self.convertButton, 1, 2, 1, 1)
self.clearButton = QtWidgets.QPushButton(self.buttonWidget)
self.clearButton.setMinimumSize(QtCore.QSize(0, 30))
icon4 = QtGui.QIcon()
icon4.addPixmap(QtGui.QPixmap(":/Other/icons/clear.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.clearButton = QPushButton(self.buttonWidget)
self.clearButton.setObjectName(u"clearButton")
self.clearButton.setMinimumSize(QSize(0, 30))
icon4 = QIcon()
icon4.addFile(u":/Other/icons/clear.png", QSize(), QIcon.Normal, QIcon.Off)
self.clearButton.setIcon(icon4)
self.clearButton.setObjectName("clearButton")
self.gridLayout_4.addWidget(self.clearButton, 0, 2, 1, 1)
self.directoryButton.raise_()
self.clearButton.raise_()
self.fileButton.raise_()
self.deviceBox.raise_()
self.convertButton.raise_()
self.formatBox.raise_()
self.gridLayout.addWidget(self.buttonWidget, 3, 0, 1, 2)
self.toolWidget = QtWidgets.QWidget(self.centralWidget)
self.toolWidget.setObjectName("toolWidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.toolWidget)
self.toolWidget = QWidget(self.centralWidget)
self.toolWidget.setObjectName(u"toolWidget")
self.horizontalLayout = QHBoxLayout(self.toolWidget)
self.horizontalLayout.setObjectName(u"horizontalLayout")
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.editorButton = QtWidgets.QPushButton(self.toolWidget)
self.editorButton.setMinimumSize(QtCore.QSize(0, 30))
icon5 = QtGui.QIcon()
icon5.addPixmap(QtGui.QPixmap(":/Other/icons/editor.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.editorButton = QPushButton(self.toolWidget)
self.editorButton.setObjectName(u"editorButton")
self.editorButton.setMinimumSize(QSize(0, 30))
icon5 = QIcon()
icon5.addFile(u":/Other/icons/editor.png", QSize(), QIcon.Normal, QIcon.Off)
self.editorButton.setIcon(icon5)
self.editorButton.setObjectName("editorButton")
self.horizontalLayout.addWidget(self.editorButton)
self.wikiButton = QtWidgets.QPushButton(self.toolWidget)
self.wikiButton.setMinimumSize(QtCore.QSize(0, 30))
icon6 = QtGui.QIcon()
icon6.addPixmap(QtGui.QPixmap(":/Other/icons/wiki.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.wikiButton = QPushButton(self.toolWidget)
self.wikiButton.setObjectName(u"wikiButton")
self.wikiButton.setMinimumSize(QSize(0, 30))
icon6 = QIcon()
icon6.addFile(u":/Other/icons/wiki.png", QSize(), QIcon.Normal, QIcon.Off)
self.wikiButton.setIcon(icon6)
self.wikiButton.setObjectName("wikiButton")
self.horizontalLayout.addWidget(self.wikiButton)
self.gridLayout.addWidget(self.toolWidget, 0, 0, 1, 2)
self.jobList = QtWidgets.QListWidget(self.centralWidget)
self.jobList.setStyleSheet("QListWidget#jobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;color:rgb(0,0,0);}")
self.jobList.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
self.jobList.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel)
self.jobList.setHorizontalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel)
self.jobList.setObjectName("jobList")
self.jobList = QListWidget(self.centralWidget)
self.jobList.setObjectName(u"jobList")
self.jobList.setStyleSheet(u"QListWidget#jobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;color:rgb(0,0,0);}")
self.jobList.setSelectionMode(QAbstractItemView.NoSelection)
self.jobList.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel)
self.jobList.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel)
self.gridLayout.addWidget(self.jobList, 2, 0, 1, 2)
self.progressBar = QtWidgets.QProgressBar(self.centralWidget)
self.progressBar.setMinimumSize(QtCore.QSize(0, 30))
font = QtGui.QFont()
font.setBold(True)
self.progressBar = QProgressBar(self.centralWidget)
self.progressBar.setObjectName(u"progressBar")
self.progressBar.setMinimumSize(QSize(0, 30))
self.progressBar.setFont(font)
self.progressBar.setVisible(False)
self.progressBar.setAlignment(QtCore.Qt.AlignJustify|QtCore.Qt.AlignVCenter)
self.progressBar.setObjectName("progressBar")
self.progressBar.setAlignment(Qt.AlignJustify|Qt.AlignVCenter)
self.gridLayout.addWidget(self.progressBar, 1, 0, 1, 2)
self.customWidget = QtWidgets.QWidget(self.centralWidget)
self.customWidget = QWidget(self.centralWidget)
self.customWidget.setObjectName(u"customWidget")
self.customWidget.setVisible(False)
self.customWidget.setObjectName("customWidget")
self.gridLayout_3 = QtWidgets.QGridLayout(self.customWidget)
self.gridLayout_3 = QGridLayout(self.customWidget)
self.gridLayout_3.setObjectName(u"gridLayout_3")
self.gridLayout_3.setContentsMargins(0, 0, 0, 0)
self.gridLayout_3.setObjectName("gridLayout_3")
self.hLabel = QtWidgets.QLabel(self.customWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.hLabel.sizePolicy().hasHeightForWidth())
self.hLabel.setSizePolicy(sizePolicy)
self.hLabel.setObjectName("hLabel")
self.hLabel = QLabel(self.customWidget)
self.hLabel.setObjectName(u"hLabel")
sizePolicy1 = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred)
sizePolicy1.setHorizontalStretch(0)
sizePolicy1.setVerticalStretch(0)
sizePolicy1.setHeightForWidth(self.hLabel.sizePolicy().hasHeightForWidth())
self.hLabel.setSizePolicy(sizePolicy1)
self.gridLayout_3.addWidget(self.hLabel, 0, 2, 1, 1)
self.widthBox = QtWidgets.QSpinBox(self.customWidget)
self.widthBox = QSpinBox(self.customWidget)
self.widthBox.setObjectName(u"widthBox")
self.widthBox.setMaximum(2160)
self.widthBox.setObjectName("widthBox")
self.gridLayout_3.addWidget(self.widthBox, 0, 1, 1, 1)
self.wLabel = QtWidgets.QLabel(self.customWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.wLabel.sizePolicy().hasHeightForWidth())
self.wLabel.setSizePolicy(sizePolicy)
self.wLabel.setObjectName("wLabel")
self.wLabel = QLabel(self.customWidget)
self.wLabel.setObjectName(u"wLabel")
sizePolicy1.setHeightForWidth(self.wLabel.sizePolicy().hasHeightForWidth())
self.wLabel.setSizePolicy(sizePolicy1)
self.gridLayout_3.addWidget(self.wLabel, 0, 0, 1, 1)
self.heightBox = QtWidgets.QSpinBox(self.customWidget)
self.heightBox = QSpinBox(self.customWidget)
self.heightBox.setObjectName(u"heightBox")
self.heightBox.setMaximum(3840)
self.heightBox.setObjectName("heightBox")
self.gridLayout_3.addWidget(self.heightBox, 0, 3, 1, 1)
self.gridLayout.addWidget(self.customWidget, 7, 0, 1, 2)
mainWindow.setCentralWidget(self.centralWidget)
self.statusBar = QtWidgets.QStatusBar(mainWindow)
self.statusBar = QStatusBar(mainWindow)
self.statusBar.setObjectName(u"statusBar")
self.statusBar.setSizeGripEnabled(False)
self.statusBar.setObjectName("statusBar")
mainWindow.setStatusBar(self.statusBar)
QWidget.setTabOrder(self.convertButton, self.clearButton)
QWidget.setTabOrder(self.clearButton, self.directoryButton)
QWidget.setTabOrder(self.directoryButton, self.fileButton)
QWidget.setTabOrder(self.fileButton, self.deviceBox)
QWidget.setTabOrder(self.deviceBox, self.formatBox)
QWidget.setTabOrder(self.formatBox, self.mangaBox)
QWidget.setTabOrder(self.mangaBox, self.rotateBox)
QWidget.setTabOrder(self.rotateBox, self.qualityBox)
QWidget.setTabOrder(self.qualityBox, self.webtoonBox)
QWidget.setTabOrder(self.webtoonBox, self.upscaleBox)
QWidget.setTabOrder(self.upscaleBox, self.gammaBox)
QWidget.setTabOrder(self.gammaBox, self.borderBox)
QWidget.setTabOrder(self.borderBox, self.outputSplit)
QWidget.setTabOrder(self.outputSplit, self.colorBox)
QWidget.setTabOrder(self.colorBox, self.croppingBox)
QWidget.setTabOrder(self.croppingBox, self.mozJpegBox)
QWidget.setTabOrder(self.mozJpegBox, self.maximizeStrips)
QWidget.setTabOrder(self.maximizeStrips, self.deleteBox)
QWidget.setTabOrder(self.deleteBox, self.disableProcessingBox)
QWidget.setTabOrder(self.disableProcessingBox, self.editorButton)
QWidget.setTabOrder(self.editorButton, self.wikiButton)
QWidget.setTabOrder(self.wikiButton, self.jobList)
QWidget.setTabOrder(self.jobList, self.gammaSlider)
QWidget.setTabOrder(self.gammaSlider, self.widthBox)
QWidget.setTabOrder(self.widthBox, self.heightBox)
QWidget.setTabOrder(self.heightBox, self.croppingPowerSlider)
self.retranslateUi(mainWindow)
QtCore.QMetaObject.connectSlotsByName(mainWindow)
mainWindow.setTabOrder(self.convertButton, self.clearButton)
mainWindow.setTabOrder(self.clearButton, self.directoryButton)
mainWindow.setTabOrder(self.directoryButton, self.fileButton)
mainWindow.setTabOrder(self.fileButton, self.deviceBox)
mainWindow.setTabOrder(self.deviceBox, self.formatBox)
mainWindow.setTabOrder(self.formatBox, self.mangaBox)
mainWindow.setTabOrder(self.mangaBox, self.rotateBox)
mainWindow.setTabOrder(self.rotateBox, self.qualityBox)
mainWindow.setTabOrder(self.qualityBox, self.webtoonBox)
mainWindow.setTabOrder(self.webtoonBox, self.upscaleBox)
mainWindow.setTabOrder(self.upscaleBox, self.gammaBox)
mainWindow.setTabOrder(self.gammaBox, self.borderBox)
mainWindow.setTabOrder(self.borderBox, self.outputSplit)
mainWindow.setTabOrder(self.outputSplit, self.colorBox)
mainWindow.setTabOrder(self.colorBox, self.croppingBox)
mainWindow.setTabOrder(self.croppingBox, self.mozJpegBox)
mainWindow.setTabOrder(self.mozJpegBox, self.maximizeStrips)
mainWindow.setTabOrder(self.maximizeStrips, self.deleteBox)
mainWindow.setTabOrder(self.deleteBox, self.disableProcessingBox)
mainWindow.setTabOrder(self.disableProcessingBox, self.editorButton)
mainWindow.setTabOrder(self.editorButton, self.wikiButton)
mainWindow.setTabOrder(self.wikiButton, self.jobList)
mainWindow.setTabOrder(self.jobList, self.gammaSlider)
mainWindow.setTabOrder(self.gammaSlider, self.widthBox)
mainWindow.setTabOrder(self.widthBox, self.heightBox)
mainWindow.setTabOrder(self.heightBox, self.croppingPowerSlider)
QMetaObject.connectSlotsByName(mainWindow)
# setupUi
def retranslateUi(self, mainWindow):
_translate = QtCore.QCoreApplication.translate
mainWindow.setWindowTitle(_translate("mainWindow", "Kindle Comic Converter"))
self.upscaleBox.setToolTip(_translate("mainWindow", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Nothing<br/></span>Images smaller than device resolution will not be resized.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - Stretching<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be not preserved.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Upscaling<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be preserved.</p></body></html>"))
self.upscaleBox.setText(_translate("mainWindow", "Stretch/Upscale"))
self.rotateBox.setToolTip(_translate("mainWindow", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Split<br/></span>Double page spreads will be cut into two separate pages.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - Rotate and split<br/></span>Double page spreads will be displayed twice. First rotated and then split. </p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Rotate<br/></span>Double page spreads will be rotated.</p></body></html>"))
self.rotateBox.setText(_translate("mainWindow", "Spread splitter"))
self.outputSplit.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Automatic mode<br/></span>The output will be split automatically.</p><p style=\'white-space:pre\'><span style=\" font-weight:600; text-decoration: underline;\">Checked - Volume mode<br/></span>Every subdirectory will be considered as a separate volume.</p></body></html>"))
self.outputSplit.setText(_translate("mainWindow", "Output split"))
self.webtoonBox.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Enable special parsing mode for Korean Webtoons.</p></body></html>"))
self.webtoonBox.setText(_translate("mainWindow", "Webtoon mode"))
self.colorBox.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Disable conversion to grayscale.</p></body></html>"))
self.colorBox.setText(_translate("mainWindow", "Color mode"))
self.gammaBox.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Disable automatic gamma correction.</p></body></html>"))
self.gammaBox.setText(_translate("mainWindow", "Custom gamma"))
self.borderBox.setToolTip(_translate("mainWindow", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Autodetection<br/></span>The color of margins fill will be detected automatically.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - White<br/></span>Margins will be filled with white color.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Black<br/></span>Margins will be filled with black color.</p></body></html>"))
self.borderBox.setText(_translate("mainWindow", "W/B margins"))
self.mangaBox.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Enable right-to-left reading.</p></body></html>"))
self.mangaBox.setText(_translate("mainWindow", "Manga mode"))
self.qualityBox.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - 4 panels<br/></span>Zoom each corner separately.</p><p style=\'white-space:pre\'><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - 2 panels<br/></span>Zoom only the top and bottom of the page.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - 4 high-quality panels<br/></span>Zoom each corner separately. Try to increase the quality of magnification. Check wiki for more details.</p></body></html>"))
self.qualityBox.setText(_translate("mainWindow", "Panel View 4/2/HQ"))
self.mozJpegBox.setToolTip(_translate("mainWindow", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - JPEG<br/></span>Use JPEG files</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - force PNG<br/></span>Create PNG files instead JPEG</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - mozJpeg<br/></span>10-20% smaller JPEG file, with the same image quality, but processing time multiplied by 2</p></body></html>"))
self.mozJpegBox.setText(_translate("mainWindow", "JPEG/PNG/mozJpeg"))
self.maximizeStrips.setToolTip(_translate("mainWindow", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - 1x4<br/></span>Keep format 1x4 panels strips.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - 2x2<br/></span>Turn 1x4 strips to 2x2 to maximize screen usage.</p></body></html>"))
self.maximizeStrips.setText(_translate("mainWindow", "1x4 to 2x2 strips"))
self.croppingBox.setToolTip(_translate("mainWindow", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Disabled</span></p><p>Disabled</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - Margins<br/></span>Margins</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Margins + page numbers<br/></span>Margins +page numbers</p></body></html>"))
self.croppingBox.setText(_translate("mainWindow", "Cropping mode"))
self.deleteBox.setToolTip(_translate("mainWindow", "Delete input file(s) or directory. It\'s not recoverable!"))
self.deleteBox.setText(_translate("mainWindow", "Delete input"))
self.disableProcessingBox.setToolTip(_translate("mainWindow", "<html><head/><body><pre style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Do not process any image, ignore profile and processing options</pre></body></html>"))
self.disableProcessingBox.setText(_translate("mainWindow", "Disable processing"))
self.gammaLabel.setText(_translate("mainWindow", "Gamma: Auto"))
self.croppingPowerLabel.setText(_translate("mainWindow", "Cropping power:"))
self.directoryButton.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Add directory containing JPG, PNG or GIF files to queue.<br/><span style=\" font-weight:600;\">CBR, CBZ and CB7 files inside will not be processed!</span></p></body></html>"))
self.directoryButton.setText(_translate("mainWindow", "Add directory"))
self.fileButton.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Add CBR, CBZ, CB7 or PDF file to queue.</p></body></html>"))
self.fileButton.setText(_translate("mainWindow", "Add file"))
self.deviceBox.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Target device.</p></body></html>"))
self.formatBox.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Output format.</p></body></html>"))
self.convertButton.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Shift+Click to select the output directory.</p></body></html>"))
self.convertButton.setText(_translate("mainWindow", "Convert"))
self.clearButton.setText(_translate("mainWindow", "Clear list"))
self.editorButton.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Shift+Click to edit directory.</p></body></html>"))
self.editorButton.setText(_translate("mainWindow", "Editor"))
self.wikiButton.setText(_translate("mainWindow", "Wiki"))
self.hLabel.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Resolution of the target device.</p></body></html>"))
self.hLabel.setText(_translate("mainWindow", "Custom height:"))
self.widthBox.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Resolution of the target device.</p></body></html>"))
self.wLabel.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Resolution of the target device.</p></body></html>"))
self.wLabel.setText(_translate("mainWindow", "Custom width:"))
self.heightBox.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Resolution of the target device.</p></body></html>"))
from . import KCC_rc
mainWindow.setWindowTitle(QCoreApplication.translate("mainWindow", u"Kindle Comic Converter", None))
#if QT_CONFIG(tooltip)
self.qualityBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - 4 panels<br/></span>Zoom each corner separately.</p><p style='white-space:pre'><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - 2 panels<br/></span>Zoom only the top and bottom of the page.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - 4 high-quality panels<br/></span>Zoom each corner separately. Try to increase the quality of magnification. Check wiki for more details.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.qualityBox.setText(QCoreApplication.translate("mainWindow", u"Panel View 4/2/HQ", None))
#if QT_CONFIG(tooltip)
self.deleteBox.setToolTip(QCoreApplication.translate("mainWindow", u"Delete input file(s) or directory. It's not recoverable!", None))
#endif // QT_CONFIG(tooltip)
self.deleteBox.setText(QCoreApplication.translate("mainWindow", u"Delete input", None))
#if QT_CONFIG(tooltip)
self.maximizeStrips.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - 1x4<br/></span>Keep format 1x4 panels strips.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - 2x2<br/></span>Turn 1x4 strips to 2x2 to maximize screen usage.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.maximizeStrips.setText(QCoreApplication.translate("mainWindow", u"1x4 to 2x2 strips", None))
#if QT_CONFIG(tooltip)
self.gammaBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Disable automatic gamma correction.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.gammaBox.setText(QCoreApplication.translate("mainWindow", u"Custom gamma", None))
#if QT_CONFIG(tooltip)
self.borderBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Autodetection<br/></span>The color of margins fill will be detected automatically.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - White<br/></span>Margins will be filled with white color.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Black<br/></span>Margins will be filled with black color.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.borderBox.setText(QCoreApplication.translate("mainWindow", u"W/B margins", None))
#if QT_CONFIG(tooltip)
self.webtoonBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Enable special parsing mode for Korean Webtoons.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.webtoonBox.setText(QCoreApplication.translate("mainWindow", u"Webtoon mode", None))
#if QT_CONFIG(tooltip)
self.upscaleBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Nothing<br/></span>Images smaller than device resolution will not be resized.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - Stretching<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be not preserved.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Upscaling<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be preserved.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.upscaleBox.setText(QCoreApplication.translate("mainWindow", u"Stretch/Upscale", None))
#if QT_CONFIG(tooltip)
self.mangaBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Enable right-to-left reading.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.mangaBox.setText(QCoreApplication.translate("mainWindow", u"Manga mode", None))
#if QT_CONFIG(tooltip)
self.rotateBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Split<br/></span>Double page spreads will be cut into two separate pages.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - Rotate and split<br/></span>Double page spreads will be displayed twice. First rotated and then split. </p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Rotate<br/></span>Double page spreads will be rotated.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.rotateBox.setText(QCoreApplication.translate("mainWindow", u"Spread splitter", None))
#if QT_CONFIG(tooltip)
self.croppingBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Disabled</span></p><p>Disabled</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - Margins<br/></span>Margins</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Margins + page numbers<br/></span>Margins +page numbers</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.croppingBox.setText(QCoreApplication.translate("mainWindow", u"Cropping mode", None))
#if QT_CONFIG(tooltip)
self.outputSplit.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Automatic mode<br/></span>The output will be split automatically.</p><p style='white-space:pre'><span style=\" font-weight:600; text-decoration: underline;\">Checked - Volume mode<br/></span>Every subdirectory will be considered as a separate volume.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.outputSplit.setText(QCoreApplication.translate("mainWindow", u"Output split", None))
#if QT_CONFIG(tooltip)
self.mozJpegBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - JPEG<br/></span>Use JPEG files</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - force PNG<br/></span>Create PNG files instead JPEG</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - mozJpeg<br/></span>10-20% smaller JPEG file, with the same image quality, but processing time multiplied by 2</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.mozJpegBox.setText(QCoreApplication.translate("mainWindow", u"JPEG/PNG/mozJpeg", None))
#if QT_CONFIG(tooltip)
self.colorBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Disable conversion to grayscale.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.colorBox.setText(QCoreApplication.translate("mainWindow", u"Color mode", None))
#if QT_CONFIG(tooltip)
self.disableProcessingBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><pre style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Do not process any image, ignore profile and processing options</pre></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.disableProcessingBox.setText(QCoreApplication.translate("mainWindow", u"Disable processing", None))
#if QT_CONFIG(tooltip)
self.dedupeCoverBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p>Don't duplicate the first page as the cover. Useful for 2 page spread alignment.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.dedupeCoverBox.setText(QCoreApplication.translate("mainWindow", u"De-dupe cover", None))
self.gammaLabel.setText(QCoreApplication.translate("mainWindow", u"Gamma: Auto", None))
self.croppingPowerLabel.setText(QCoreApplication.translate("mainWindow", u"Cropping power:", None))
#if QT_CONFIG(tooltip)
self.directoryButton.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Add directory containing JPG, PNG or GIF files to queue.<br/><span style=\" font-weight:600;\">CBR, CBZ and CB7 files inside will not be processed!</span></p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.directoryButton.setText(QCoreApplication.translate("mainWindow", u"Add directory", None))
#if QT_CONFIG(tooltip)
self.fileButton.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Add CBR, CBZ, CB7 or PDF file to queue.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.fileButton.setText(QCoreApplication.translate("mainWindow", u"Add file", None))
#if QT_CONFIG(tooltip)
self.deviceBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Target device.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
#if QT_CONFIG(tooltip)
self.formatBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Output format.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
#if QT_CONFIG(tooltip)
self.convertButton.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Shift+Click to select the output directory.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.convertButton.setText(QCoreApplication.translate("mainWindow", u"Convert", None))
self.clearButton.setText(QCoreApplication.translate("mainWindow", u"Clear list", None))
#if QT_CONFIG(tooltip)
self.editorButton.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Shift+Click to edit directory.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.editorButton.setText(QCoreApplication.translate("mainWindow", u"Editor", None))
self.wikiButton.setText(QCoreApplication.translate("mainWindow", u"Wiki", None))
#if QT_CONFIG(tooltip)
self.hLabel.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Resolution of the target device.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.hLabel.setText(QCoreApplication.translate("mainWindow", u"Custom height:", None))
#if QT_CONFIG(tooltip)
self.widthBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Resolution of the target device.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
#if QT_CONFIG(tooltip)
self.wLabel.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Resolution of the target device.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.wLabel.setText(QCoreApplication.translate("mainWindow", u"Custom width:", None))
#if QT_CONFIG(tooltip)
self.heightBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Resolution of the target device.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
# retranslateUi

View File

@@ -1,118 +1,168 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'gui/MetaEditor.ui'
#
# Created by: PyQt5 UI code generator 5.15.2
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
################################################################################
## Form generated from reading UI file 'MetaEditor.ui'
##
## Created by: Qt User Interface Compiler version 6.5.2
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################
from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
QMetaObject, QObject, QPoint, QRect,
QSize, QTime, QUrl, Qt)
from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
QFont, QFontDatabase, QGradient, QIcon,
QImage, QKeySequence, QLinearGradient, QPainter,
QPalette, QPixmap, QRadialGradient, QTransform)
from PySide6.QtWidgets import (QApplication, QDialog, QGridLayout, QHBoxLayout,
QLabel, QLineEdit, QPushButton, QSizePolicy,
QVBoxLayout, QWidget)
from . import KCC_rc
class Ui_editorDialog(object):
def setupUi(self, editorDialog):
editorDialog.setObjectName("editorDialog")
if not editorDialog.objectName():
editorDialog.setObjectName(u"editorDialog")
editorDialog.resize(400, 260)
editorDialog.setMinimumSize(QtCore.QSize(400, 260))
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/Icon/icons/comic2ebook.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
editorDialog.setMinimumSize(QSize(400, 260))
icon = QIcon()
icon.addFile(u":/Icon/icons/comic2ebook.png", QSize(), QIcon.Normal, QIcon.Off)
editorDialog.setWindowIcon(icon)
self.verticalLayout = QtWidgets.QVBoxLayout(editorDialog)
self.verticalLayout = QVBoxLayout(editorDialog)
self.verticalLayout.setObjectName(u"verticalLayout")
self.verticalLayout.setContentsMargins(-1, -1, -1, 5)
self.verticalLayout.setObjectName("verticalLayout")
self.editorWidget = QtWidgets.QWidget(editorDialog)
self.editorWidget.setObjectName("editorWidget")
self.gridLayout = QtWidgets.QGridLayout(self.editorWidget)
self.editorWidget = QWidget(editorDialog)
self.editorWidget.setObjectName(u"editorWidget")
self.gridLayout = QGridLayout(self.editorWidget)
self.gridLayout.setObjectName(u"gridLayout")
self.gridLayout.setContentsMargins(0, 0, 0, 0)
self.gridLayout.setObjectName("gridLayout")
self.label_1 = QtWidgets.QLabel(self.editorWidget)
self.label_1.setObjectName("label_1")
self.label_1 = QLabel(self.editorWidget)
self.label_1.setObjectName(u"label_1")
self.gridLayout.addWidget(self.label_1, 0, 0, 1, 1)
self.seriesLine = QtWidgets.QLineEdit(self.editorWidget)
self.seriesLine.setObjectName("seriesLine")
self.seriesLine = QLineEdit(self.editorWidget)
self.seriesLine.setObjectName(u"seriesLine")
self.gridLayout.addWidget(self.seriesLine, 0, 1, 1, 1)
self.label_2 = QtWidgets.QLabel(self.editorWidget)
self.label_2.setObjectName("label_2")
self.label_2 = QLabel(self.editorWidget)
self.label_2.setObjectName(u"label_2")
self.gridLayout.addWidget(self.label_2, 1, 0, 1, 1)
self.volumeLine = QtWidgets.QLineEdit(self.editorWidget)
self.volumeLine.setObjectName("volumeLine")
self.volumeLine = QLineEdit(self.editorWidget)
self.volumeLine.setObjectName(u"volumeLine")
self.gridLayout.addWidget(self.volumeLine, 1, 1, 1, 1)
self.label_3 = QtWidgets.QLabel(self.editorWidget)
self.label_3.setObjectName("label_3")
self.label_3 = QLabel(self.editorWidget)
self.label_3.setObjectName(u"label_3")
self.gridLayout.addWidget(self.label_3, 2, 0, 1, 1)
self.numberLine = QtWidgets.QLineEdit(self.editorWidget)
self.numberLine.setObjectName("numberLine")
self.numberLine = QLineEdit(self.editorWidget)
self.numberLine.setObjectName(u"numberLine")
self.gridLayout.addWidget(self.numberLine, 2, 1, 1, 1)
self.label_4 = QtWidgets.QLabel(self.editorWidget)
self.label_4.setObjectName("label_4")
self.label_4 = QLabel(self.editorWidget)
self.label_4.setObjectName(u"label_4")
self.gridLayout.addWidget(self.label_4, 3, 0, 1, 1)
self.writerLine = QtWidgets.QLineEdit(self.editorWidget)
self.writerLine.setObjectName("writerLine")
self.writerLine = QLineEdit(self.editorWidget)
self.writerLine.setObjectName(u"writerLine")
self.gridLayout.addWidget(self.writerLine, 3, 1, 1, 1)
self.label_5 = QtWidgets.QLabel(self.editorWidget)
self.label_5.setObjectName("label_5")
self.label_5 = QLabel(self.editorWidget)
self.label_5.setObjectName(u"label_5")
self.gridLayout.addWidget(self.label_5, 4, 0, 1, 1)
self.pencillerLine = QtWidgets.QLineEdit(self.editorWidget)
self.pencillerLine.setObjectName("pencillerLine")
self.pencillerLine = QLineEdit(self.editorWidget)
self.pencillerLine.setObjectName(u"pencillerLine")
self.gridLayout.addWidget(self.pencillerLine, 4, 1, 1, 1)
self.label_6 = QtWidgets.QLabel(self.editorWidget)
self.label_6.setObjectName("label_6")
self.label_6 = QLabel(self.editorWidget)
self.label_6.setObjectName(u"label_6")
self.gridLayout.addWidget(self.label_6, 5, 0, 1, 1)
self.inkerLine = QtWidgets.QLineEdit(self.editorWidget)
self.inkerLine.setObjectName("inkerLine")
self.inkerLine = QLineEdit(self.editorWidget)
self.inkerLine.setObjectName(u"inkerLine")
self.gridLayout.addWidget(self.inkerLine, 5, 1, 1, 1)
self.label_7 = QtWidgets.QLabel(self.editorWidget)
self.label_7.setObjectName("label_7")
self.label_7 = QLabel(self.editorWidget)
self.label_7.setObjectName(u"label_7")
self.gridLayout.addWidget(self.label_7, 6, 0, 1, 1)
self.coloristLine = QtWidgets.QLineEdit(self.editorWidget)
self.coloristLine.setObjectName("coloristLine")
self.coloristLine = QLineEdit(self.editorWidget)
self.coloristLine.setObjectName(u"coloristLine")
self.gridLayout.addWidget(self.coloristLine, 6, 1, 1, 1)
self.verticalLayout.addWidget(self.editorWidget)
self.optionWidget = QtWidgets.QWidget(editorDialog)
self.optionWidget.setObjectName("optionWidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.optionWidget)
self.optionWidget = QWidget(editorDialog)
self.optionWidget.setObjectName(u"optionWidget")
self.horizontalLayout = QHBoxLayout(self.optionWidget)
self.horizontalLayout.setObjectName(u"horizontalLayout")
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.statusLabel = QtWidgets.QLabel(self.optionWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
self.statusLabel = QLabel(self.optionWidget)
self.statusLabel.setObjectName(u"statusLabel")
sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.statusLabel.sizePolicy().hasHeightForWidth())
self.statusLabel.setSizePolicy(sizePolicy)
self.statusLabel.setText("")
self.statusLabel.setObjectName("statusLabel")
self.horizontalLayout.addWidget(self.statusLabel)
self.okButton = QtWidgets.QPushButton(self.optionWidget)
self.okButton.setMinimumSize(QtCore.QSize(0, 30))
icon1 = QtGui.QIcon()
icon1.addPixmap(QtGui.QPixmap(":/Other/icons/convert.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.okButton = QPushButton(self.optionWidget)
self.okButton.setObjectName(u"okButton")
self.okButton.setMinimumSize(QSize(0, 30))
icon1 = QIcon()
icon1.addFile(u":/Other/icons/convert.png", QSize(), QIcon.Normal, QIcon.Off)
self.okButton.setIcon(icon1)
self.okButton.setObjectName("okButton")
self.horizontalLayout.addWidget(self.okButton)
self.cancelButton = QtWidgets.QPushButton(self.optionWidget)
self.cancelButton.setMinimumSize(QtCore.QSize(0, 30))
icon2 = QtGui.QIcon()
icon2.addPixmap(QtGui.QPixmap(":/Other/icons/clear.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.cancelButton = QPushButton(self.optionWidget)
self.cancelButton.setObjectName(u"cancelButton")
self.cancelButton.setMinimumSize(QSize(0, 30))
icon2 = QIcon()
icon2.addFile(u":/Other/icons/clear.png", QSize(), QIcon.Normal, QIcon.Off)
self.cancelButton.setIcon(icon2)
self.cancelButton.setObjectName("cancelButton")
self.horizontalLayout.addWidget(self.cancelButton)
self.verticalLayout.addWidget(self.optionWidget)
self.retranslateUi(editorDialog)
QtCore.QMetaObject.connectSlotsByName(editorDialog)
QMetaObject.connectSlotsByName(editorDialog)
# setupUi
def retranslateUi(self, editorDialog):
_translate = QtCore.QCoreApplication.translate
editorDialog.setWindowTitle(_translate("editorDialog", "Metadata editor"))
self.label_1.setText(_translate("editorDialog", "Series:"))
self.label_2.setText(_translate("editorDialog", "Volume:"))
self.label_3.setText(_translate("editorDialog", "Number:"))
self.label_4.setText(_translate("editorDialog", "Writer:"))
self.label_5.setText(_translate("editorDialog", "Penciller:"))
self.label_6.setText(_translate("editorDialog", "Inker:"))
self.label_7.setText(_translate("editorDialog", "Colorist:"))
self.okButton.setText(_translate("editorDialog", "Save"))
self.cancelButton.setText(_translate("editorDialog", "Cancel"))
from . import KCC_rc
editorDialog.setWindowTitle(QCoreApplication.translate("editorDialog", u"Metadata editor", None))
self.label_1.setText(QCoreApplication.translate("editorDialog", u"Series:", None))
self.label_2.setText(QCoreApplication.translate("editorDialog", u"Volume:", None))
self.label_3.setText(QCoreApplication.translate("editorDialog", u"Number:", None))
self.label_4.setText(QCoreApplication.translate("editorDialog", u"Writer:", None))
self.label_5.setText(QCoreApplication.translate("editorDialog", u"Penciller:", None))
self.label_6.setText(QCoreApplication.translate("editorDialog", u"Inker:", None))
self.label_7.setText(QCoreApplication.translate("editorDialog", u"Colorist:", None))
self.statusLabel.setText("")
self.okButton.setText(QCoreApplication.translate("editorDialog", u"Save", None))
self.cancelButton.setText(QCoreApplication.translate("editorDialog", u"Cancel", None))
# retranslateUi

View File

@@ -1,4 +1,4 @@
__version__ = '5.6.5'
__version__ = '6.1.0'
__license__ = 'ISC'
__copyright__ = '2012-2022, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>, darodi'
__docformat__ = 'restructuredtext en'

View File

@@ -21,7 +21,6 @@
import os
import pathlib
import re
import subprocess
import sys
from argparse import ArgumentParser
from time import strftime, gmtime
@@ -36,14 +35,11 @@ from multiprocessing import Pool
from uuid import uuid4
from natsort import os_sorted
from slugify import slugify as slugify_ext
from PIL import Image
from PIL import Image, ImageFile
from subprocess import STDOUT, PIPE
from psutil import virtual_memory, disk_usage
from html import escape as hescape
try:
from PyQt5 import QtCore
except ImportError:
QtCore = None
from .shared import md5Checksum, getImageFileName, walkSort, walkLevel, sanitizeTrace, subprocess_run_silent
from . import comic2panel
from . import image
@@ -54,6 +50,8 @@ from . import metadata
from . import kindle
from . import __version__
ImageFile.LOAD_TRUNCATED_IMAGES = True
def main(argv=None):
global options
@@ -506,15 +504,18 @@ def buildEPUB(path, chapternames, tomenumber):
chapter = False
dirnames, filenames = walkSort(dirnames, filenames)
for afile in filenames:
if cover is None:
cover = os.path.join(os.path.join(path, 'OEBPS', 'Images'),
'cover' + getImageFileName(afile)[1])
options.covers.append((image.Cover(os.path.join(dirpath, afile), cover, options,
tomenumber), options.uuid))
if options.dedupecover:
os.remove(os.path.join(dirpath, afile))
continue
filelist.append(buildHTML(dirpath, afile, os.path.join(dirpath, afile)))
if not chapter:
chapterlist.append((dirpath.replace('Images', 'Text'), filelist[-1][1]))
chapter = True
if cover is None:
cover = os.path.join(os.path.join(path, 'OEBPS', 'Images'),
'cover' + getImageFileName(filelist[-1][1])[1])
options.covers.append((image.Cover(os.path.join(filelist[-1][0], filelist[-1][1]), cover, options,
tomenumber), options.uuid))
# Overwrite chapternames if tree is flat and ComicInfo.xml has bookmarks
if not chapternames and options.chapters:
chapterlist = []
@@ -646,6 +647,9 @@ def getWorkFolder(afile):
try:
cbx = comicarchive.ComicArchive(afile)
path = cbx.extract(workdir)
tdir = os.listdir(workdir)
if 'ComicInfo.xml' in tdir:
tdir.remove('ComicInfo.xml')
except OSError as e:
rmtree(workdir, True)
raise UserWarning(e)
@@ -691,7 +695,6 @@ def getOutputFilename(srcpath, wantedname, ext, tomenumber):
def getComicInfo(path, originalpath):
xmlPath = os.path.join(path, 'ComicInfo.xml')
options.authors = ['KCC']
options.chapters = []
options.summary = ''
titleSuffix = ''
@@ -703,13 +706,18 @@ def getComicInfo(path, originalpath):
options.title = os.path.splitext(os.path.basename(originalpath))[0]
else:
defaultTitle = False
if options.author == 'defaultauthor':
defaultAuthor = True
options.authors = ['KCC']
else:
defaultAuthor = False
options.authors = [options.author]
if os.path.exists(xmlPath):
try:
xml = metadata.MetadataParser(xmlPath)
except Exception:
os.remove(xmlPath)
return
options.authors = []
if xml.data['Title']:
options.title = hescape(xml.data['Title'])
elif defaultTitle:
@@ -720,14 +728,16 @@ def getComicInfo(path, originalpath):
if xml.data['Number']:
titleSuffix += ' #' + xml.data['Number'].zfill(3)
options.title += titleSuffix
for field in ['Writers', 'Pencillers', 'Inkers', 'Colorists']:
for person in xml.data[field]:
options.authors.append(hescape(person))
if len(options.authors) > 0:
options.authors = list(set(options.authors))
options.authors.sort()
else:
options.authors = ['KCC']
if defaultAuthor:
options.authors = []
for field in ['Writers', 'Pencillers', 'Inkers', 'Colorists']:
for person in xml.data[field]:
options.authors.append(hescape(person))
if len(options.authors) > 0:
options.authors = list(set(options.authors))
options.authors.sort()
else:
options.authors = ['KCC']
if xml.data['Bookmarks'] and options.batchsplit == 0:
options.chapters = xml.data['Bookmarks']
if xml.data['Summary']:
@@ -896,7 +906,7 @@ def detectCorruption(tmppath, orgpath):
GUI.addMessage.emit('Source files are probably created by KCC. The second conversion will decrease quality.'
, 'warning', False)
GUI.addMessage.emit('', '', False)
if imageSmaller > imageNumber * 0.25 and not options.upscale and not options.stretch:
if imageSmaller > imageNumber * 0.25 and not options.upscale and not options.stretch and options.profile != 'KS':
print("WARNING: More than 25% of images are smaller than target device resolution. "
"Consider enabling stretching or upscaling to improve readability.")
if GUI:
@@ -948,7 +958,7 @@ def makeParser():
main_options.add_argument("-p", "--profile", action="store", dest="profile", default="KV",
help="Device profile (Available options: K1, K2, K34, K578, KDX, KPW, KPW5, KV, KO, "
"K11, KS, KoMT, KoG, KoGHD, KoA, KoAHD, KoAH2O, KoAO, KoN, KoC, KoL, KoF, KoS, KoE)"
"K11, KS, KoMT, KoG, KoGHD, KoA, KoAHD, KoAH2O, KoAO, KoN, KoC, KoCC, KoL, KoLC, KoF, KoS, KoE)"
" [Default=KV]")
main_options.add_argument("-m", "--manga-style", action="store_true", dest="righttoleft", default=False,
help="Manga style (right-to-left reading and splitting)")
@@ -966,12 +976,16 @@ def makeParser():
help="Output generated file to specified directory or file")
output_options.add_argument("-t", "--title", action="store", dest="title", default="defaulttitle",
help="Comic title [Default=filename or directory name]")
output_options.add_argument("-a", "--author", action="store", dest="author", default="defaultauthor",
help="Author name [Default=KCC]")
output_options.add_argument("-f", "--format", action="store", dest="format", default="Auto",
help="Output format (Available options: Auto, MOBI, EPUB, CBZ, KFX, MOBI+EPUB) "
"[Default=Auto]")
output_options.add_argument("-b", "--batchsplit", type=int, dest="batchsplit", default="0",
help="Split output into multiple files. 0: Don't split 1: Automatic mode "
"2: Consider every subdirectory as separate volume [Default=0]")
output_options.add_argument("--dedupecover", action="store_true", dest="dedupecover", default=False,
help="De-duplicate the cover as the first page in the book")
processing_options.add_argument("-n", "--noprocessing", action="store_true", dest="noprocessing", default=False,
help="Do not modify image and ignore any profil or processing option")
@@ -1035,13 +1049,13 @@ def checkOptions(options):
if options.profile in ['K1', 'K2', 'K34', 'K578', 'KPW', 'KPW5', 'KV', 'KO', 'K11', 'KS']:
options.format = 'MOBI'
elif options.profile in ['OTHER', 'KoMT', 'KoG', 'KoGHD', 'KoA', 'KoAHD', 'KoAH2O', 'KoAO',
'KoN', 'KoC', 'KoL', 'KoF', 'KoS', 'KoE']:
'KoN', 'KoC', 'KoCC', 'KoL', 'KoLC', 'KoF', 'KoS', 'KoE']:
options.format = 'EPUB'
elif options.profile in ['KDX']:
options.format = 'CBZ'
if options.profile in ['K1', 'K2', 'K34', 'K578', 'KPW', 'KPW5', 'KV', 'KO', 'K11', 'KS']:
options.iskindle = True
elif options.profile in ['OTHER', 'KoMT', 'KoG', 'KoGHD', 'KoA', 'KoAHD', 'KoAH2O', 'KoAO', 'KoN', 'KoC', 'KoL', 'KoF', 'KoS', 'KoE']:
elif options.profile in ['OTHER', 'KoMT', 'KoG', 'KoGHD', 'KoA', 'KoAHD', 'KoAH2O', 'KoAO', 'KoN', 'KoC', 'KoCC', 'KoL', 'KoLC', 'KoF', 'KoS', 'KoE']:
options.isKobo = True
# Other Kobo devices probably support synthetic spreads as well, but
# they haven't been tested.
@@ -1092,10 +1106,6 @@ def checkOptions(options):
image.ProfileData.Profiles["Custom"] = newProfile
options.profile = "Custom"
options.profileData = image.ProfileData.Profiles[options.profile]
# kindle scribe conversion to mobi is limited in resolution by kindlegen, same with send to kindle and epub
if options.profile == 'KS' and (options.format == 'MOBI' or options.format == 'EPUB'):
options.profileData = list(options.profileData)
options.profileData[1] = (1440, 1920)
return options

View File

@@ -25,10 +25,6 @@ from shutil import rmtree, copytree, move
from multiprocessing import Pool
from PIL import Image, ImageChops, ImageOps, ImageDraw
from .shared import getImageFileName, walkLevel, walkSort, sanitizeTrace
try:
from PyQt5 import QtCore
except ImportError:
QtCore = None
def mergeDirectoryTick(output):

View File

@@ -23,7 +23,7 @@ import platform
import subprocess
import distro
from shutil import move
from subprocess import STDOUT, PIPE
from subprocess import STDOUT, PIPE, CalledProcessError
from xml.dom.minidom import parseString
from xml.parsers.expat import ExpatError
from .shared import subprocess_run_silent
@@ -37,7 +37,10 @@ class ComicArchive:
self.type = None
if not os.path.isfile(self.filepath):
raise OSError('File not found.')
process = subprocess_run_silent(['7z', 'l', '-y', '-p1', self.filepath], stderr=STDOUT, stdout=PIPE)
try:
process = subprocess_run_silent(['7z', 'l', '-y', '-p1', self.filepath], stderr=STDOUT, stdout=PIPE)
except FileNotFoundError:
return
for line in process.stdout.splitlines():
if b'Type =' in line:
self.type = line.rstrip().decode().split(' = ')[1].upper()
@@ -54,6 +57,12 @@ class ComicArchive:
def extract(self, targetdir):
if not os.path.isdir(targetdir):
raise OSError('Target directory doesn\'t exist.')
try:
process = subprocess_run_silent(['tar', '-xf', self.filepath, '-C', targetdir],
stdout=PIPE, stderr=STDOUT, check=True)
return targetdir
except (FileNotFoundError, CalledProcessError):
pass
process = subprocess_run_silent(['7z', 'x', '-y', '-xr!__MACOSX', '-xr!.DS_Store', '-xr!thumbs.db', '-xr!Thumbs.db', '-o' + targetdir, self.filepath],
stdout=PIPE, stderr=STDOUT)
if process.returncode != 0 and distro.id() == 'fedora':
@@ -61,14 +70,8 @@ class ComicArchive:
, stdout=PIPE, stderr=STDOUT)
if process.returncode != 0:
raise OSError(EXTRACTION_ERROR)
elif process.returncode != 0 and platform.system() == 'Darwin':
process = subprocess_run_silent(['unar', self.filepath, '-f', '-o', targetdir],
stdout=PIPE, stderr=STDOUT)
elif process.returncode != 0:
raise OSError(EXTRACTION_ERROR)
tdir = os.listdir(targetdir)
if 'ComicInfo.xml' in tdir:
tdir.remove('ComicInfo.xml')
return targetdir
def addFile(self, sourcefile):

View File

@@ -99,7 +99,9 @@ class ProfileData:
'KoAO': ("Kobo Aura ONE", (1404, 1872), Palette16, 1.8),
'KoN': ("Kobo Nia", (758, 1024), Palette16, 1.8),
'KoC': ("Kobo Clara HD/Kobo Clara 2E", (1072, 1448), Palette16, 1.8),
'KoCC': ("Kobo Clara Colour", (1072, 1448), Palette16, 1.8),
'KoL': ("Kobo Libra H2O/Kobo Libra 2", (1264, 1680), Palette16, 1.8),
'KoLC': ("Kobo Libra Colour", (1264, 1680), Palette16, 1.8),
'KoF': ("Kobo Forma", (1440, 1920), Palette16, 1.8),
'KoS': ("Kobo Sage", (1440, 1920), Palette16, 1.8),
'KoE': ("Kobo Elipsa", (1404, 1872), Palette16, 1.8),
@@ -239,6 +241,7 @@ class ComicPage:
_, self.size, self.palette, self.gamma = self.opt.profileData
if self.opt.hq:
self.size = (int(self.size[0] * 1.5), int(self.size[1] * 1.5))
self.kindle_scribe_azw3 = (options.profile == 'KS') and (options.format in ('MOBI', 'EPUB'))
self.image = image
self.color = color
self.fill = fill
@@ -308,6 +311,9 @@ class ComicPage:
self.image = self.image.quantize(palette=palImg)
def resizeImage(self):
# kindle scribe conversion to mobi is limited in resolution by kindlegen, same with send to kindle and epub
if self.kindle_scribe_azw3:
self.size = (1440, 1920)
ratio_device = float(self.size[1]) / float(self.size[0])
ratio_image = float(self.image.size[1]) / float(self.image.size[0])
method = self.resize_method()
@@ -326,14 +332,15 @@ class ComicPage:
elif self.opt.format == 'CBZ' or self.opt.kfx:
self.image = ImageOps.pad(self.image, self.size, method=method, color=self.fill)
else:
if self.kindle_scribe_azw3:
self.size = (1860, 1920)
self.image = ImageOps.contain(self.image, self.size, method=method)
def resize_method(self):
if self.image.size[0] <= self.size[0] and self.image.size[1] <= self.size[1]:
method = Image.Resampling.BICUBIC
return Image.Resampling.BICUBIC
else:
method = Image.Resampling.LANCZOS
return method
return Image.Resampling.LANCZOS
def getBoundingBox(self, tmptmg):
min_margin = [int(0.005 * i + 0.5) for i in tmptmg.size]

View File

@@ -102,11 +102,11 @@ def dependencyCheck(level):
missing = []
if level > 2:
try:
from PyQt5.QtCore import qVersion as qtVersion
if StrictVersion('5.6.0') > StrictVersion(qtVersion()):
missing.append('PyQt 5.6.0+')
from PySide6.QtCore import qVersion as qtVersion
if StrictVersion('6.5.1') > StrictVersion(qtVersion()):
missing.append('PySide 6.5.1+')
except ImportError:
missing.append('PyQt 5.6.0+')
missing.append('PySide 6.5.1+')
try:
import raven
except ImportError:

View File

@@ -1,10 +1,9 @@
PyQt5>=5.6.0
PySide6>=6.5.1
Pillow>=5.2.0
psutil>=5.0.0
psutil>=5.9.5
requests>=2.31.0
python-slugify>=1.2.1
raven>=6.0.0
# PyQt5-tools
mozjpeg-lossless-optimization>=1.1.2
natsort[fast]>=8.4.0
distro
distro>=1.8.0

View File

@@ -11,8 +11,8 @@ Create EXE/APP:
"""
import os
import platform
import sys
import shutil
import setuptools
import distutils.cmd
from kindlecomicconverter import __version__
@@ -39,7 +39,7 @@ class BuildBinaryCommand(distutils.cmd.Command):
if sys.platform == 'darwin':
os.system('pyinstaller -y -D -i icons/comic2ebook.icns -n "Kindle Comic Converter" -w -s kcc.py')
# TODO /usr/bin/codesign --force -s "$MACOS_CERTIFICATE_NAME" --options runtime dist/Applications/Kindle\ Comic\ Converter.app -v
os.system('appdmg kcc.json dist/KindleComicConverter_osx_' + VERSION + '.dmg')
os.system(f'appdmg kcc.json dist/kcc_macos_{platform.processor()}_{VERSION}.dmg')
sys.exit(0)
elif sys.platform == 'win32':
os.system('pyinstaller -y -F -i icons\\comic2ebook.ico -n KCC_' + VERSION + ' -w --noupx kcc.py')
@@ -75,9 +75,9 @@ setuptools.setup(
},
packages=['kindlecomicconverter'],
install_requires=[
'PyQt5>=5.6.0',
'pyside6>=6.5.1',
'Pillow>=5.2.0',
'psutil>=5.0.0',
'psutil>=5.9.5',
'python-slugify>=1.2.1,<9.0.0',
'raven>=6.0.0',
'requests>=2.31.0',