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

Compare commits

...

34 Commits

Author SHA1 Message Date
Alex Xu
36b91167c8 remove chapter name number expansion. 2024-02-26 11:29:09 -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
VampiroMedicado
e8502f008a hide subprocess consoles on Windows (#656) 2024-01-01 18:11:55 -08:00
inganault
169a41e7d2 Add missing dependencies to setup.py (#653) 2023-12-29 19:00:24 -08:00
Alex Xu
57cf669cdd add to credits 2023-12-28 18:55:08 -08:00
Alex Xu
0b4f089b8e add .DS_Store to .gitignore 2023-12-23 09:35:12 -08:00
Alex Xu
7eb985337c add requests to setup.py 2023-12-23 09:10:31 -08:00
Alex Xu
d62690e8bf import subprocess 2023-12-21 13:40:48 -08:00
Alex Xu
3988f2012f fix p7zip-rar error and files with ' or " by using arg lists instead of strings (#633)
* Revert "Revert "fix files with ' or " by using arg lists instead of strings (#581)" (#628)"

This reverts commit b528dab711.

* handle FileNotFoundError

* modify unar handling

* remove unneeded utf-8 encoding

* dont uft-8 encode 7z

* remove utf-8 encoding from 7z calls

* don't extract stderr

* add extraction error

* edit error message

* remove debug

* remove kindlegen location from GUI

* remove comment
2023-12-21 12:52:35 -08:00
Alex Xu
6cdd9d5909 change kobo epub filenames (#616) 2023-12-21 12:51:26 -08:00
Alex Xu
c29a4beac9 use requests library 2023-12-21 12:44:29 -08:00
Alex Xu
5f7bdef325 bump to 5.6.5 2023-12-21 09:50:34 -08:00
Alex Xu
54b5d698ee fix access denied 2023-12-21 09:43:33 -08:00
Alex Xu
a99c63acea use os_sorted over natsorted 2023-12-21 09:43:07 -08:00
dependabot[bot]
251df2e7ba Bump github/codeql-action from 2 to 3
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2 to 3.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-21 09:42:20 -08:00
dependabot[bot]
b1379b7c59 Bump actions/upload-artifact from 3 to 4
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-21 09:42:11 -08:00
Alex Xu
983bde1691 add fat to list of drives 2023-12-21 09:41:18 -08:00
dependabot[bot]
e79e5a311c Bump actions/setup-python from 4 to 5
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4 to 5.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-10 20:02:36 -08:00
jaroslawjanas
39c73dbc0f Added natsort to the dependency list in environment.yml 2023-12-10 19:59:33 -08:00
Alex Xu
915c9389ef remove kindlegen location UI 2023-12-09 17:39:01 -08:00
Alex Xu
89d887710e fix typo 2023-12-07 18:57:46 -08:00
Alex Xu
2e9bc5381a add PREREQUISITES 2023-12-07 18:56:57 -08:00
Alex Xu
ab1ce158c7 rename to prerequisites 2023-12-04 09:33:08 -08:00
Ciro Mattia Gonano
6278adfb25 Update issue templates 2023-11-29 12:40:11 +01:00
25 changed files with 12208 additions and 12062 deletions

31
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,31 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
Add a screenshot of your KCC settings.
**Desktop (please complete the following information):**
- OS: [e.g. macOS, Linux, Windows 11]
- Device [e.g. Kindle Paperwhite 3rd gen, Kobo Libra 2]
**Additional context**
Add any other context about the problem here.

View File

@@ -42,7 +42,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -56,7 +56,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
uses: github/codeql-action/autobuild@v3
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
@@ -69,6 +69,6 @@ jobs:
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"

View File

@@ -27,15 +27,15 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: 3.11
cache: 'pip'
- 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
python -m pip install --upgrade pip setuptools wheel certifi pyinstaller --no-binary pyinstaller
python -m pip install -r requirements.txt
- name: build binary
run: |
@@ -59,7 +59,7 @@ jobs:
env:
UPDATE_INFO: gh-releases-zsync|ciromattia|kcc|latest|*x86_64.AppImage.zsync
- name: upload artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: AppImage
path: './*.AppImage*'

View File

@@ -23,11 +23,14 @@ on:
jobs:
build:
runs-on: macos-latest
strategy:
matrix:
os: [ macos-latest, macos-14 ]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: 3.11
cache: 'pip'
@@ -75,9 +78,9 @@ jobs:
run: |
python setup.py build_binary
- name: upload build
uses: actions/upload-artifact@v3
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
@@ -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

@@ -43,11 +43,11 @@ jobs:
- 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.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
- name: upload build
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: windows-build
path: dist/windows/*.exe

View File

@@ -27,7 +27,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: 3.11
cache: 'pip'
@@ -42,7 +42,7 @@ jobs:
run: |
python setup.py build_binary
- name: upload build
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: windows-build
path: dist/*.exe

1
.gitignore vendored
View File

@@ -11,3 +11,4 @@ KindleComicConverter*.egg-info/
/venv/
/kindlegen*
/kcc.bat
.DS_Store

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

View File

@@ -28,6 +28,8 @@ If you find **KCC** valuable you can consider donating to the authors:
- Paweł Jastrzębski:
- [![Donate PayPal](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YTTJ4LK2JDHPS)
- [![Donate Bitcoin](https://img.shields.io/badge/Donate-Bitcoin-green.svg)](https://jastrzeb.ski/donate/)
- Alex Xu
- [![Donate PayPal](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/donate/?business=QFJVE7A6LCP6U&no_recurring=0&item_name=Kindle+Comic+Converter&currency_code=USD)
## DOWNLOADS
@@ -37,8 +39,9 @@ If you find **KCC** valuable you can consider donating to the authors:
Click on **Assets** of the latest release.
You probably want either
- `kcc_*.*.*.exe` (Windows)
- `KindleComicConverter_osx_*.*.*.dmg` (Mac)
- `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.
@@ -46,9 +49,9 @@ On Windows 11, you may need to run in compatibility mode for an older Windows ve
On Mac, right click open to get past the security warning.
For flatpak, Docker, amd AppImage versions, refer to the wiki: https://github.com/ciromattia/kcc/wiki/Installation
For flatpak, Docker, and AppImage versions, refer to the wiki: https://github.com/ciromattia/kcc/wiki/Installation
## INSTALL DEPENDENCIES
## PREREQUISITES
You'll need to install various tools to access important but optional features.
@@ -74,7 +77,7 @@ brew install unar
#### 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). KCC will automatically detect KindleGen from it.
## INPUT FORMATS
**KCC** can understand and convert, at the moment, the following input types:
@@ -209,7 +212,12 @@ OTHER:
```
## CREDITS
**KCC** is made by [Ciro Mattia Gonano](http://github.com/ciromattia), [Paweł Jastrzębski](http://github.com/AcidWeb) and [Darodi](http://github.com/darodi) .
**KCC** is made by
- [Ciro Mattia Gonano](http://github.com/ciromattia)
- [Paweł Jastrzębski](http://github.com/AcidWeb)
- [Darodi](http://github.com/darodi)
- [Alex Xu](http://github.com/axu2)
This script born as a cross-platform alternative to `KindleComicParser` by **Dc5e** (published [here](http://www.mobileread.com/forums/showthread.php?t=192783)).

View File

@@ -5,11 +5,12 @@ 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
- natsort[fast]>=8.4.0
- 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

@@ -16,25 +16,26 @@
# OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
import json
import os
import re
import subprocess
import sys
from urllib.parse import unquote
from urllib.request import urlretrieve, urlopen
from time import sleep
from shutil import move, rmtree
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 Popen, Process
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
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):
@@ -139,10 +140,7 @@ class VersionThread(QtCore.QThread):
def run(self):
try:
last_version_url = urlopen("https://api.github.com/repos/ciromattia/kcc/releases/latest")
data = last_version_url.read()
encoding = last_version_url.info().get_content_charset('utf-8')
json_parser = json.loads(data.decode(encoding))
json_parser = requests.get("https://api.github.com/repos/ciromattia/kcc/releases/latest").json()
html_url = json_parser["html_url"]
latest_version = json_parser["tag_name"]
@@ -223,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
@@ -256,13 +254,15 @@ class WorkerThread(QtCore.QThread):
options.noprocessing = True
if GUI.deleteBox.isChecked():
options.delete = True
if GUI.mozJpegBox.checkState() == 1:
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
@@ -431,7 +431,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):
@@ -440,7 +440,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)
@@ -550,7 +550,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)
@@ -558,7 +558,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)
@@ -672,7 +672,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))
@@ -690,7 +690,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,
@@ -718,7 +718,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'):
@@ -771,23 +771,23 @@ 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,
'maximizeStrips': GUI.maximizeStrips.checkState().value,
'gammaSlider': float(self.gammaValue) * 100})
self.settings.sync()
self.tray.hide()
@@ -839,32 +839,21 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
os.chmod('/usr/local/bin/kindlegen', 0o755)
except Exception:
pass
kindleGenExitCode = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
kindleGenExitCode.communicate()
if kindleGenExitCode.returncode == 0:
try:
versionCheck = subprocess_run_silent(['kindlegen', '-locale', 'en'], stdout=PIPE, stderr=STDOUT, encoding='UTF-8')
self.kindleGen = True
versionCheck = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
for line in versionCheck.stdout:
line = line.decode("utf-8")
for line in versionCheck.stdout.splitlines():
if 'Amazon kindlegen' in line:
versionCheck = line.split('V')[1].split(' ')[0]
if StrictVersion(versionCheck) < StrictVersion('2.9'):
self.addMessage('Your <a href="https://www.amazon.com/b?node=23496309011">KindleGen</a>'
' is outdated! MOBI conversion might fail.', 'warning')
break
where_command = 'where kindlegen.exe'
if os.name == 'posix':
where_command = 'which kindlegen'
process = subprocess.run(where_command, stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
locations = process.stdout.decode('utf-8').split('\n')
self.addMessage(f"<b>KindleGen Found:</b> {locations[0]}", 'info')
else:
except FileNotFoundError:
self.kindleGen = False
if startup:
self.display_kindlegen_missing()
def __init__(self, kccapp, kccwindow):
global APP, MW, GUI
APP = kccapp
@@ -873,7 +862,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)
@@ -906,10 +895,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)
@@ -924,9 +913,9 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
self.profiles = {
"Kindle Oasis 2/3": {'PVOptions': True, 'ForceExpert': False, 'DefaultFormat': 0,
"Kindle Oasis 9/10": {'PVOptions': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': True, 'Label': 'KO'},
"Kindle Oasis": {'PVOptions': True, 'ForceExpert': False, 'DefaultFormat': 0,
"Kindle Oasis 8": {'PVOptions': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': True, 'Label': 'KV'},
"Kindle Voyage": {'PVOptions': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': True, 'Label': 'KV'},
@@ -936,16 +925,16 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
"Kindle 11": {
'PVOptions': True, 'ForceExpert': False, 'DefaultFormat': 0, 'DefaultUpscale': True, 'Label': 'K11',
},
"Kindle PW 5": {
"Kindle PW 11": {
'PVOptions': True, 'ForceExpert': False, 'DefaultFormat': 0, 'DefaultUpscale': True, 'Label': 'KPW5',
},
"Kindle PW 3/4": {'PVOptions': True, 'ForceExpert': False, 'DefaultFormat': 0,
"Kindle PW 7/10": {'PVOptions': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': True, 'Label': 'KV'},
"Kindle PW 1/2": {'PVOptions': True, 'ForceExpert': False, 'DefaultFormat': 0,
"Kindle PW 5/6": {'PVOptions': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': 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,
"Kindle DX": {'PVOptions': False, 'ForceExpert': False, 'DefaultFormat': 2,
'DefaultUpscale': False, 'Label': 'KDX'},
"Kobo Mini/Touch": {'PVOptions': False, 'ForceExpert': False, 'DefaultFormat': 1,
'DefaultUpscale': False, 'Label': 'KoMT'},
@@ -989,10 +978,10 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
'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 Sage",
@@ -1002,16 +991,16 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
"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",
@@ -1029,7 +1018,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)
@@ -1039,11 +1028,10 @@ 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')
process = Popen('7z', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
process.communicate()
if process.returncode == 0 or process.returncode == 7:
try:
subprocess_run_silent(['7z'], stdout=PIPE, stderr=STDOUT)
self.sevenzip = True
else:
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')
@@ -1088,7 +1076,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":
@@ -1114,8 +1102,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()
@@ -1189,7 +1177,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,454 @@
# -*- 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.1
##
## 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 = QCheckBox(self.optionWidget)
self.upscaleBox.setObjectName(u"upscaleBox")
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 = QCheckBox(self.optionWidget)
self.rotateBox.setObjectName(u"rotateBox")
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.outputSplit = QCheckBox(self.optionWidget)
self.outputSplit.setObjectName(u"outputSplit")
self.gridLayout_2.addWidget(self.outputSplit, 2, 1, 1, 1)
self.webtoonBox = QtWidgets.QCheckBox(self.optionWidget)
self.webtoonBox.setObjectName("webtoonBox")
self.webtoonBox = QCheckBox(self.optionWidget)
self.webtoonBox.setObjectName(u"webtoonBox")
self.gridLayout_2.addWidget(self.webtoonBox, 1, 0, 1, 1)
self.colorBox = QtWidgets.QCheckBox(self.optionWidget)
self.colorBox.setObjectName("colorBox")
self.colorBox = QCheckBox(self.optionWidget)
self.colorBox.setObjectName(u"colorBox")
self.gridLayout_2.addWidget(self.colorBox, 2, 2, 1, 1)
self.gammaBox = QtWidgets.QCheckBox(self.optionWidget)
self.gammaBox.setObjectName("gammaBox")
self.gammaBox = QCheckBox(self.optionWidget)
self.gammaBox.setObjectName(u"gammaBox")
self.gridLayout_2.addWidget(self.gammaBox, 1, 2, 1, 1)
self.borderBox = QtWidgets.QCheckBox(self.optionWidget)
self.borderBox = QCheckBox(self.optionWidget)
self.borderBox.setObjectName(u"borderBox")
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.mangaBox = QCheckBox(self.optionWidget)
self.mangaBox.setObjectName(u"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 = QCheckBox(self.optionWidget)
self.mozJpegBox.setObjectName(u"mozJpegBox")
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.maximizeStrips = QCheckBox(self.optionWidget)
self.maximizeStrips.setObjectName(u"maximizeStrips")
self.gridLayout_2.addWidget(self.maximizeStrips, 3, 1, 1, 1)
self.croppingBox = QtWidgets.QCheckBox(self.optionWidget)
self.croppingBox = QCheckBox(self.optionWidget)
self.croppingBox.setObjectName(u"croppingBox")
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.disableProcessingBox = QCheckBox(self.optionWidget)
self.disableProcessingBox.setObjectName(u"disableProcessingBox")
self.gridLayout_2.addWidget(self.disableProcessingBox, 4, 2, 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.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.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.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.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.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.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.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.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.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.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.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.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.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))
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.1
##
## 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.4'
__version__ = '5.6.5'
__license__ = 'ISC'
__copyright__ = '2012-2022, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>, darodi'
__docformat__ = 'restructuredtext en'

View File

@@ -19,6 +19,9 @@
#
import os
import pathlib
import re
import subprocess
import sys
from argparse import ArgumentParser
from time import strftime, gmtime
@@ -31,17 +34,14 @@ from tempfile import mkdtemp, gettempdir, TemporaryFile
from shutil import move, copytree, rmtree, copyfile
from multiprocessing import Pool
from uuid import uuid4
from natsort import natsorted
from natsort import os_sorted
from slugify import slugify as slugify_ext
from PIL import Image
from subprocess import STDOUT, PIPE
from psutil import Popen, virtual_memory, disk_usage
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
from .shared import md5Checksum, getImageFileName, walkSort, walkLevel, sanitizeTrace, subprocess_run_silent
from . import comic2panel
from . import image
from . import comicarchive
@@ -672,11 +672,9 @@ def getOutputFilename(srcpath, wantedname, ext, tomenumber):
filename = srcpath + tomenumber + ext
else:
if 'Ko' in options.profile and options.format == 'EPUB':
path = srcpath.split(os.path.sep)
path[-1] = ''.join(e for e in path[-1].split('.')[0] if e.isalnum()) + tomenumber + ext
if not path[-1].split('.')[0]:
path[-1] = 'KCCPlaceholder' + tomenumber + ext
filename = os.path.sep.join(path)
src = pathlib.Path(srcpath)
name = re.sub(r'\W+', '_', src.stem) + tomenumber + ext
filename = src.with_name(name)
else:
filename = os.path.splitext(srcpath)[0] + tomenumber + ext
if os.path.isfile(filename):
@@ -762,7 +760,7 @@ def getPanelViewSize(deviceres, size):
def sanitizeTree(filetree):
chapterNames = {}
for root, dirs, files in os.walk(filetree, False):
for i, name in enumerate(natsorted(files)):
for i, name in enumerate(os_sorted(files)):
splitname = os.path.splitext(name)
# file needs kcc at front AND back to avoid renaming issues
@@ -913,7 +911,6 @@ def createNewTome():
def slugify(value):
value = slugify_ext(value, regex_pattern=r'[^-a-z0-9_\.]+').strip('.')
value = sub(r'0*([0-9]{4,})', r'\1', sub(r'([0-9]+)', r'0000\1', value, count=2))
return value
@@ -1102,15 +1099,15 @@ def checkTools(source):
source = source.upper()
if source.endswith('.CB7') or source.endswith('.7Z') or source.endswith('.RAR') or source.endswith('.CBR') or \
source.endswith('.ZIP') or source.endswith('.CBZ'):
process = Popen('7z', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
process.communicate()
if process.returncode != 0 and process.returncode != 7:
try:
subprocess_run_silent(['7z'], stdout=PIPE, stderr=STDOUT)
except FileNotFoundError:
print('ERROR: 7z is missing!')
sys.exit(1)
if options.format == 'MOBI':
kindleGenExitCode = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
kindleGenExitCode.communicate()
if kindleGenExitCode.returncode != 0:
try:
subprocess_run_silent(['kindlegen', '-locale', 'en'], stdout=PIPE, stderr=STDOUT)
except FileNotFoundError:
print('ERROR: KindleGen is missing!')
sys.exit(1)
@@ -1266,10 +1263,9 @@ def makeMOBIWorker(item):
kindlegenError = ''
try:
if os.path.getsize(item) < 629145600:
output = Popen('kindlegen -dont_append_source -locale en "' + item + '"',
stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
for line in output.stdout:
line = line.decode('utf-8')
output = subprocess_run_silent(['kindlegen', '-dont_append_source', '-locale', 'en', item],
stdout=PIPE, stderr=STDOUT, encoding='UTF-8')
for line in output.stdout.splitlines():
# ERROR: Generic error
if "Error(" in line:
kindlegenErrorCode = 1
@@ -1280,7 +1276,6 @@ def makeMOBIWorker(item):
if kindlegenErrorCode > 0:
break
if ":I1036: Mobi file built successfully" in line:
output.communicate()
break
else:
# ERROR: EPUB too big

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

@@ -22,11 +22,13 @@ import os
import platform
import subprocess
import distro
from psutil import Popen
from shutil import move
from subprocess import STDOUT, PIPE
from xml.dom.minidom import parseString
from xml.parsers.expat import ExpatError
from .shared import subprocess_run_silent
EXTRACTION_ERROR = 'Failed to extract archive. Try extracting file outside of KCC.'
class ComicArchive:
@@ -35,66 +37,54 @@ class ComicArchive:
self.type = None
if not os.path.isfile(self.filepath):
raise OSError('File not found.')
process = Popen('7z l -y -p1 "' + self.filepath + '"', stderr=STDOUT, stdout=PIPE, stdin=PIPE, shell=True)
for line in process.stdout:
process = subprocess_run_silent(['7z', 'l', '-y', '-p1', self.filepath], stderr=STDOUT, stdout=PIPE)
for line in process.stdout.splitlines():
if b'Type =' in line:
self.type = line.rstrip().decode().split(' = ')[1].upper()
break
process.communicate()
if process.returncode != 0 and distro.id() == 'fedora':
process = Popen('unrar l -y -p1 "' + self.filepath + '"', stderr=STDOUT, stdout=PIPE, stdin=PIPE, shell=True)
for line in process.stdout:
process = subprocess_run_silent(['unrar', 'l', '-y', '-p1', self.filepath], stderr=STDOUT, stdout=PIPE)
for line in process.stdout.splitlines():
if b'Details: ' in line:
self.type = line.rstrip().decode().split(' ')[1].upper()
break
process.communicate()
if process.returncode != 0:
raise OSError(process.stdout.strip())
raise OSError(EXTRACTION_ERROR)
def extract(self, targetdir):
if not os.path.isdir(targetdir):
raise OSError('Target directory doesn\'t exist.')
process = Popen('7z x -y -xr!__MACOSX -xr!.DS_Store -xr!thumbs.db -xr!Thumbs.db -o"' + targetdir + '" "' +
self.filepath + '"', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
process.communicate()
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':
process = Popen('unrar x -y -x__MACOSX -x.DS_Store -xthumbs.db -xThumbs.db "' + self.filepath + '" "' +
targetdir + '"', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
process.communicate()
process = subprocess_run_silent(['unrar', 'x', '-y', '-x__MACOSX', '-x.DS_Store', '-xthumbs.db', '-xThumbs.db', self.filepath, targetdir]
, stdout=PIPE, stderr=STDOUT)
if process.returncode != 0:
raise OSError('Failed to extract archive.')
raise OSError(EXTRACTION_ERROR)
elif process.returncode != 0 and platform.system() == 'Darwin':
process = subprocess.run(f"unar '{self.filepath}' -f -o '{targetdir}'",
stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
if process.returncode != 0:
raise Exception(process.stdout.decode("utf-8"))
process = subprocess_run_silent(['unar', self.filepath, '-f', '-o', targetdir],
stdout=PIPE, stderr=STDOUT)
elif process.returncode != 0:
raise OSError('Failed to extract archive. Check if p7zip-rar is installed.')
raise OSError(EXTRACTION_ERROR)
tdir = os.listdir(targetdir)
if 'ComicInfo.xml' in tdir:
tdir.remove('ComicInfo.xml')
if len(tdir) == 1 and os.path.isdir(os.path.join(targetdir, tdir[0])):
for f in os.listdir(os.path.join(targetdir, tdir[0])):
move(os.path.join(targetdir, tdir[0], f), targetdir)
os.rmdir(os.path.join(targetdir, tdir[0]))
return targetdir
def addFile(self, sourcefile):
if self.type in ['RAR', 'RAR5']:
raise NotImplementedError
process = Popen('7z a -y "' + self.filepath + '" "' + sourcefile + '"',
stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
process.communicate()
process = subprocess_run_silent(['7z', 'a', '-y', self.filepath, sourcefile],
stdout=PIPE, stderr=STDOUT)
if process.returncode != 0:
raise OSError('Failed to add the file.')
def extractMetadata(self):
process = Popen('7z x -y -so "' + self.filepath + '" ComicInfo.xml',
stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
xml = process.communicate()
process = subprocess_run_silent(['7z', 'x', '-y', '-so', self.filepath, 'ComicInfo.xml'],
stdout=PIPE, stderr=STDOUT)
if process.returncode != 0:
raise OSError('Failed to extract archive.')
raise OSError(EXTRACTION_ERROR)
try:
return parseString(xml[0])
return parseString(process.stdout)
except ExpatError:
return None

View File

@@ -31,8 +31,7 @@ class Kindle:
def findDevice(self):
for drive in reversed(psutil.disk_partitions(False)):
if (drive[2] == 'FAT32' and drive[3] == 'rw,removable') or \
(drive[2] == 'vfat' and 'rw' in drive[3]) or \
(drive[2] == 'msdos' and 'rw' in drive[3]):
(drive[2] in ('vfat', 'msdos', 'FAT') and 'rw' in drive[3]):
if os.path.isdir(os.path.join(drive[1], 'system')) and \
os.path.isdir(os.path.join(drive[1], 'documents')):
return drive[1]

View File

@@ -21,6 +21,7 @@
import os
from hashlib import md5
from html.parser import HTMLParser
import subprocess
from distutils.version import StrictVersion
from re import split
import sys
@@ -101,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:
@@ -135,3 +136,8 @@ def dependencyCheck(level):
if len(missing) > 0:
print('ERROR: ' + ', '.join(missing) + ' is not installed!')
sys.exit(1)
def subprocess_run_silent(command, **kwargs):
if (os.name == 'nt'):
kwargs.setdefault('creationflags', subprocess.CREATE_NO_WINDOW)
return subprocess.run(command, **kwargs)

View File

@@ -1,9 +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,12 +75,15 @@ 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',
'mozjpeg-lossless-optimization>=1.1.2',
'natsort[fast]>=8.4.0',
'distro',
],
classifiers=[],
zip_safe=False,