mirror of
https://github.com/ciromattia/kcc
synced 2026-04-15 13:38:46 +00:00
Compare commits
446 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
28e170f1d2 | ||
|
|
7120c76025 | ||
|
|
4891913b5c | ||
|
|
cd83b2899c | ||
|
|
535c2c220b | ||
|
|
409f077c3e | ||
|
|
3ecb2ba877 | ||
|
|
c07a9657ef | ||
|
|
7f719a22ad | ||
|
|
332d3d455e | ||
|
|
2070a977ae | ||
|
|
8f8d0d68a3 | ||
|
|
5a8deb4623 | ||
|
|
a7ea795df5 | ||
|
|
a2ffd259b8 | ||
|
|
93e6b51466 | ||
|
|
7904662f25 | ||
|
|
6792c2d366 | ||
|
|
ef4a91e44d | ||
|
|
a2a405e5f5 | ||
|
|
a63a46a741 | ||
|
|
2591b53a09 | ||
|
|
1c615ffc20 | ||
|
|
6eb05b3a8f | ||
|
|
968b083fb2 | ||
|
|
205907ef1e | ||
|
|
33ef8275c3 | ||
|
|
eec2099515 | ||
|
|
9027265b7c | ||
|
|
34e2af3389 | ||
|
|
5ecddaceab | ||
|
|
fe554c20aa | ||
|
|
6acf1a1802 | ||
|
|
ac81a6be4b | ||
|
|
829a5f25e7 | ||
|
|
a695a4c151 | ||
|
|
7c0b78350d | ||
|
|
aa978ab246 | ||
|
|
7524c50657 | ||
|
|
9d8663a925 | ||
|
|
08ed304f8e | ||
|
|
658d2f3281 | ||
|
|
f44bf5993e | ||
|
|
458c28281f | ||
|
|
968a1afa1d | ||
|
|
2c875673bd | ||
|
|
1a0be83d63 | ||
|
|
36a7dc49ec | ||
|
|
40d1ae63da | ||
|
|
3d3621c6ec | ||
|
|
d77f04a84e | ||
|
|
ec51d6fc51 | ||
|
|
b7861d9d9e | ||
|
|
0b4503af21 | ||
|
|
437ffb9b10 | ||
|
|
066d1401bd | ||
|
|
9babe68d2a | ||
|
|
67de77538c | ||
|
|
c3e950f2ec | ||
|
|
ac2934aba2 | ||
|
|
a5064a0c0a | ||
|
|
2d712e796d | ||
|
|
cc3da40fd7 | ||
|
|
a53c272bd0 | ||
|
|
6526b139fd | ||
|
|
283d6101cd | ||
|
|
02dab3c6ee | ||
|
|
1895aa127d | ||
|
|
c01ff83fce | ||
|
|
4b670f3754 | ||
|
|
23b1560fa2 | ||
|
|
62350608dc | ||
|
|
8048b91fa8 | ||
|
|
2e9b3389e4 | ||
|
|
40e1ab4cf3 | ||
|
|
d2c12c89e6 | ||
|
|
4647fd1f1d | ||
|
|
010ad3c88c | ||
|
|
4b0a94a8a0 | ||
|
|
807a2d1dff | ||
|
|
e1470cca15 | ||
|
|
02b9081e37 | ||
|
|
495db88a9e | ||
|
|
2bea546a9d | ||
|
|
ee042ef98d | ||
|
|
aea7c0fafb | ||
|
|
45c1afcad4 | ||
|
|
b8e314f6ca | ||
|
|
d76eea9f43 | ||
|
|
2e55f22355 | ||
|
|
30b8770e34 | ||
|
|
9ad161489f | ||
|
|
bdb459cfab | ||
|
|
2e85556543 | ||
|
|
93ebbbd0af | ||
|
|
dd5c907bad | ||
|
|
64fb4a9eca | ||
|
|
284c577894 | ||
|
|
c68c9892e4 | ||
|
|
aa00ea3aa2 | ||
|
|
88f005824c | ||
|
|
2a2bfae112 | ||
|
|
583eec787f | ||
|
|
9ce691aecb | ||
|
|
d1a07d7ffa | ||
|
|
b545f7ad48 | ||
|
|
9e01797d28 | ||
|
|
c68c5f25bf | ||
|
|
a04bf5262f | ||
|
|
b09b2527d9 | ||
|
|
94b372f47d | ||
|
|
b978adcc7c | ||
|
|
9dee4432ad | ||
|
|
15055c6c0c | ||
|
|
3f948a10b0 | ||
|
|
1c942d81db | ||
|
|
b36a5a0a93 | ||
|
|
2ca07430a0 | ||
|
|
3132aa8a21 | ||
|
|
e4dccfe603 | ||
|
|
4c56141b80 | ||
|
|
73c2e4b136 | ||
|
|
c28e9a6ef0 | ||
|
|
558bf07f7f | ||
|
|
eaa458a9c7 | ||
|
|
91b6869638 | ||
|
|
25331f5d81 | ||
|
|
9b25182393 | ||
|
|
189c03529a | ||
|
|
c9cf635229 | ||
|
|
f78dc3cd8f | ||
|
|
4079314b61 | ||
|
|
04cf732d50 | ||
|
|
9015614b1a | ||
|
|
e817c8b258 | ||
|
|
cb9059c231 | ||
|
|
75d8be0951 | ||
|
|
161abdab18 | ||
|
|
4b1c7b3124 | ||
|
|
5481c0cfe5 | ||
|
|
9543b573e3 | ||
|
|
df0bafe4b6 | ||
|
|
b2e58127cb | ||
|
|
21174338ff | ||
|
|
241801f9cb | ||
|
|
a2086618a2 | ||
|
|
7d81de6834 | ||
|
|
7305ccffc5 | ||
|
|
72b5027021 | ||
|
|
1152655061 | ||
|
|
f25c25a121 | ||
|
|
fff7eeca2b | ||
|
|
a93da2136b | ||
|
|
dc3498b74c | ||
|
|
f317a5c430 | ||
|
|
3bedc3b928 | ||
|
|
a2651747cd | ||
|
|
af2c4e7250 | ||
|
|
f93ced8939 | ||
|
|
8a0ba682c3 | ||
|
|
1a7b6baaf3 | ||
|
|
0f8daaf9f3 | ||
|
|
1fa6d315b1 | ||
|
|
112917754a | ||
|
|
65774c6f12 | ||
|
|
7b3ce8827f | ||
|
|
b12825045b | ||
|
|
ac9f3a5d87 | ||
|
|
00969a3739 | ||
|
|
21f738b44a | ||
|
|
f2238b16a6 | ||
|
|
14f677ec68 | ||
|
|
7b3bf4618f | ||
|
|
eab63a0f74 | ||
|
|
2128104db7 | ||
|
|
c6179b0064 | ||
|
|
1d4319be2e | ||
|
|
f5a738e2d4 | ||
|
|
477d834a91 | ||
|
|
c8698f6d99 | ||
|
|
0988601842 | ||
|
|
57e9637c81 | ||
|
|
a7440e06a9 | ||
|
|
a9ed1e7610 | ||
|
|
b1bc140ad3 | ||
|
|
9014ed53d4 | ||
|
|
cad05904f3 | ||
|
|
10386d8af3 | ||
|
|
c991feb9ce | ||
|
|
d26eb7cdcd | ||
|
|
351084b703 | ||
|
|
e861e7f6e8 | ||
|
|
370c9d4df7 | ||
|
|
8e5704683c | ||
|
|
c65e1c8dea | ||
|
|
677622c103 | ||
|
|
af0ebb85a0 | ||
|
|
8af029ac92 | ||
|
|
a268e12a90 | ||
|
|
d621335e6c | ||
|
|
ec1d9c2d93 | ||
|
|
85b9dbbf83 | ||
|
|
feeced44bf | ||
|
|
cbea18398b | ||
|
|
4c9857f14d | ||
|
|
6b58ef4557 | ||
|
|
24d697c965 | ||
|
|
8b07d4eb69 | ||
|
|
e6c5ac915f | ||
|
|
b22e4757a3 | ||
|
|
91b06016bb | ||
|
|
5631391245 | ||
|
|
c33887b7b7 | ||
|
|
8d82f58f09 | ||
|
|
36985f5169 | ||
|
|
9d190c1585 | ||
|
|
3834850317 | ||
|
|
84fc23b979 | ||
|
|
77748afdbd | ||
|
|
431e2ffaf2 | ||
|
|
16df4cd083 | ||
|
|
1aa34347c1 | ||
|
|
561af90b06 | ||
|
|
00d239e1d8 | ||
|
|
26bd2d3ed0 | ||
|
|
e7aa49b70c | ||
|
|
da41edc2f1 | ||
|
|
ecbf60fb28 | ||
|
|
57b571b6c2 | ||
|
|
44bdc0245b | ||
|
|
1ec07fe4ec | ||
|
|
5f8f7e0919 | ||
|
|
f404b9090d | ||
|
|
68521f7c63 | ||
|
|
f5dd813c4c | ||
|
|
7924c492b3 | ||
|
|
2fc21c33e2 | ||
|
|
cb76504acb | ||
|
|
db6b0eddfe | ||
|
|
7d529a2acc | ||
|
|
ad3ff35aaa | ||
|
|
c62eeeb712 | ||
|
|
5a36a13105 | ||
|
|
12684d6562 | ||
|
|
c5f68ae12a | ||
|
|
7bd9c766cc | ||
|
|
c6b1417d9c | ||
|
|
98bf28a713 | ||
|
|
f2d6d5b458 | ||
|
|
5de492ffb6 | ||
|
|
5c2c6ed825 | ||
|
|
c2730ab01c | ||
|
|
bfba66d47d | ||
|
|
b5bc2f8e00 | ||
|
|
917eaef548 | ||
|
|
3187ebb054 | ||
|
|
b9276e9ede | ||
|
|
147d815057 | ||
|
|
180123fee2 | ||
|
|
2768e622f2 | ||
|
|
b629b45d46 | ||
|
|
f66c83425c | ||
|
|
68b4b7114d | ||
|
|
36f8c82eaf | ||
|
|
bd665c3261 | ||
|
|
94586fa590 | ||
|
|
89806dfcfc | ||
|
|
c9eb73ab90 | ||
|
|
2edcc0369a | ||
|
|
bc0a52b848 | ||
|
|
5ae72bf06d | ||
|
|
24c32643c1 | ||
|
|
40b988f964 | ||
|
|
ac794eff85 | ||
|
|
eaa387a9d6 | ||
|
|
d0f5d6dac4 | ||
|
|
b174534c1c | ||
|
|
19d486a4ee | ||
|
|
652762b709 | ||
|
|
e6df87f8fd | ||
|
|
1a9cd0beb5 | ||
|
|
108e351126 | ||
|
|
dfe3e10470 | ||
|
|
787ad9fa66 | ||
|
|
f10e8869a9 | ||
|
|
715ada328f | ||
|
|
56f23ab488 | ||
|
|
996af59e00 | ||
|
|
37aa84c4aa | ||
|
|
50574632e6 | ||
|
|
0afb9e8c0b | ||
|
|
7511c7eed6 | ||
|
|
836a4146f9 | ||
|
|
15a240ccea | ||
|
|
0722ddf8b0 | ||
|
|
b3159b94e7 | ||
|
|
ef5207c990 | ||
|
|
db77d89817 | ||
|
|
4571fadadb | ||
|
|
94f56238ae | ||
|
|
5efb5d6dbb | ||
|
|
623f615dd9 | ||
|
|
39fbbc42b3 | ||
|
|
99405ab8a6 | ||
|
|
aadfca8306 | ||
|
|
5450502c2a | ||
|
|
c976b06413 | ||
|
|
b6facda95b | ||
|
|
3f608eb602 | ||
|
|
104cd04994 | ||
|
|
b323204628 | ||
|
|
56195d301d | ||
|
|
287723ca6f | ||
|
|
90490149c7 | ||
|
|
2210f484df | ||
|
|
d5502e85b0 | ||
|
|
59b26cfc8b | ||
|
|
a722e5fa49 | ||
|
|
fce3072dca | ||
|
|
f53cdf9cd7 | ||
|
|
de74318c69 | ||
|
|
b137e69510 | ||
|
|
888663fa4c | ||
|
|
8a2ba96ac5 | ||
|
|
cb6b0e0a7b | ||
|
|
49d2a7fbab | ||
|
|
3d84b27d58 | ||
|
|
e98a23d0c0 | ||
|
|
7f80dacea8 | ||
|
|
6efb3dcef3 | ||
|
|
942a828b7e | ||
|
|
df5ee1badf | ||
|
|
e3ab28642d | ||
|
|
a1831c45d5 | ||
|
|
52bea9957a | ||
|
|
a71339ec34 | ||
|
|
c5f09c44b8 | ||
|
|
64b199ef74 | ||
|
|
8dd0b0e694 | ||
|
|
181a2e8ab4 | ||
|
|
3fdff845b7 | ||
|
|
2ee5dc310b | ||
|
|
f32e9560b5 | ||
|
|
621827c1c2 | ||
|
|
dc312f36c2 | ||
|
|
4573ff6ec2 | ||
|
|
d77498405b | ||
|
|
e491fca445 | ||
|
|
d22ee1a488 | ||
|
|
7ebcccd8a2 | ||
|
|
9a691c3c63 | ||
|
|
2b04a0298e | ||
|
|
9867f63d00 | ||
|
|
866f8898be | ||
|
|
9f2ac7a176 | ||
|
|
634213f380 | ||
|
|
ce82b5ec66 | ||
|
|
062b239f2f | ||
|
|
f5f5c05f1e | ||
|
|
a229ba44bf | ||
|
|
27e5cc3b00 | ||
|
|
63d752280a | ||
|
|
60b7a90589 | ||
|
|
63413fa4ba | ||
|
|
3a536df626 | ||
|
|
35bc4a2987 | ||
|
|
3bb8cc7778 | ||
|
|
bd53c6108d | ||
|
|
3d8bcb4020 | ||
|
|
162c146bed | ||
|
|
e4750fc965 | ||
|
|
ebe7d910de | ||
|
|
aa96381eb5 | ||
|
|
a2b9b5aa8b | ||
|
|
1e5bfc9f66 | ||
|
|
25a68ebdea | ||
|
|
786d2a9e1f | ||
|
|
4133cd21ba | ||
|
|
237ef728e1 | ||
|
|
991bf5d4a9 | ||
|
|
aa8b78b4e4 | ||
|
|
c2e6a0b791 | ||
|
|
42cf9e099f | ||
|
|
d99064596a | ||
|
|
b1e7a88353 | ||
|
|
f8610e1cd7 | ||
|
|
562dad02fa | ||
|
|
66b867c1ca | ||
|
|
b46ada9596 | ||
|
|
aaa2de81fc | ||
|
|
b0c6315fee | ||
|
|
509d78c0a6 | ||
|
|
65ef77bace | ||
|
|
170064853c | ||
|
|
c7e9d883fa | ||
|
|
a8521dbc9a | ||
|
|
0f44629273 | ||
|
|
f12361e7cf | ||
|
|
450076e6e8 | ||
|
|
6d445ae151 | ||
|
|
921511dcf2 | ||
|
|
d76a624a82 | ||
|
|
cf3df581e1 | ||
|
|
87009f27a6 | ||
|
|
cccbd36463 | ||
|
|
19b438844d | ||
|
|
878e92b527 | ||
|
|
116dce09fd | ||
|
|
3af30faee9 | ||
|
|
cf0b6b3484 | ||
|
|
96a8c1d354 | ||
|
|
20712b6c42 | ||
|
|
84d836bf0e | ||
|
|
d944d6385e | ||
|
|
a38013eabc | ||
|
|
def9e42a61 | ||
|
|
34aaeab8b1 | ||
|
|
eaff6cc633 | ||
|
|
54f48d2156 | ||
|
|
42d845cf07 | ||
|
|
e5e53d3aa7 | ||
|
|
f952634971 | ||
|
|
19ff6a51cc | ||
|
|
8fbe558f65 | ||
|
|
6bdb0ab942 | ||
|
|
7656a85708 | ||
|
|
d016bade8e | ||
|
|
3cc99c6221 | ||
|
|
93f5d105cf | ||
|
|
c1c44bdf88 | ||
|
|
72132ea908 | ||
|
|
29f901f92a | ||
|
|
22b7258aa3 | ||
|
|
c0f788bd67 | ||
|
|
8f10e93c08 | ||
|
|
4a473e3716 | ||
|
|
89d31cb8e5 | ||
|
|
80b65b12b7 | ||
|
|
e835502837 | ||
|
|
5bcdc78725 | ||
|
|
acb4dfad8f | ||
|
|
7f5de29174 | ||
|
|
11007402cd | ||
|
|
fa94e18a6a | ||
|
|
9f68e009f1 | ||
|
|
d33c53b691 |
9
.gitignore
vendored
9
.gitignore
vendored
@@ -1,12 +1,15 @@
|
||||
*.pyc
|
||||
*.cbz
|
||||
*.cbr
|
||||
*.spec
|
||||
.idea
|
||||
.DS_Store
|
||||
.python-version
|
||||
Thumbs.db
|
||||
build
|
||||
dist
|
||||
Output
|
||||
test
|
||||
solaio
|
||||
kindlegen*
|
||||
setup.bat
|
||||
kindlecomicconverter/sentry.py
|
||||
build/
|
||||
KindleComicConverter.egg-info/
|
||||
|
||||
37
.travis.yml
Normal file
37
.travis.yml
Normal file
@@ -0,0 +1,37 @@
|
||||
matrix:
|
||||
include:
|
||||
- os: osx
|
||||
language: generic
|
||||
osx_image: xcode9.2
|
||||
|
||||
before_install:
|
||||
- brew update
|
||||
- brew upgrade python3
|
||||
- brew uninstall node
|
||||
- travis_wait 30 brew install node@6
|
||||
- brew link node@6 --force --overwrite
|
||||
- pip3 install --upgrade pip setuptools wheel
|
||||
- openssl aes-256-cbc -K $encrypted_a95564d8ff0d_key -iv $encrypted_a95564d8ff0d_iv -in other/osx/sentry.py.enc -out kindlecomicconverter/sentry.py -d
|
||||
|
||||
install:
|
||||
- pip3 install -r requirements.txt
|
||||
- pip3 install certifi https://github.com/pyinstaller/pyinstaller/archive/develop.zip
|
||||
- npm install -g appdmg
|
||||
|
||||
script: python3 setup.py build_binary
|
||||
|
||||
before_deploy:
|
||||
- shopt -s extglob
|
||||
- rm -r dist/!(*.deb|*.dmg)
|
||||
|
||||
deploy:
|
||||
provider: s3
|
||||
skip_cleanup: true
|
||||
access_key_id: AKIAIQNL5R4FI4C4NJYQ
|
||||
secret_access_key:
|
||||
secure: X66hYplxB4QSueljwvDfamNH/MQmHjo3mCofBcaTHAr7n2fp+yd2NzD2yy9h8NbsL0LWwx9wtJa/jpkIE02ZDfi9NrMLvKKFazzdpiyTMN5Yh85lHHyD1XIOCZRd4igaZ+O8975tJAEaEOPS+PE9XGZcRBh+y/eSJ+fMEgohaJ1MtDFbQR7X1cEw3iqbjrV2rlghZNCk/9mZEfObzAEjQiSDpv5G0IuIPRvYg/BgZt8chHVAe03B6oqcBa7uCBCTlfHIiNh1MWtP0B3NNBq3dcu9QHOFri1YqoZKuaPVCf6TFQL/NW5dFihegev2t9IwFyaBxytiT8fBkgQhP0VX8cuCwBAfnQGIogAu0eLSPp+E6dB/7Cpt2GDCk39+As8WKqt9hCRHmrvYhPA1Mq9QyEgKy/TKKKfDby3qVTIqYOQYpuQ1B7sIU651L5A+hBvZ1dqWIUz25h0zqjjeSFrcfNnf1e4tkk0QJvvnKqz0xsVaJxA2p07VJMRn8SlZQIJ2GEbMDeB5jxYtf5JzXywChP9adlPNjLna9G8ScnGSU1f7ZhsBQUEgY5jBlnX1lveyl3DUe6NP+qOTyljLWYwjx3AF4Zg10LYSecRS6hnqAUrGRmibDCIYclUzlJkVyjKGJ9uEyrUiCp0P0IsAzE1XhPVAWEyGUcWWGJG+jgmohSk=
|
||||
bucket: kcc-deploy
|
||||
region: eu-central-1
|
||||
local_dir: dist
|
||||
on:
|
||||
repo: AcidWeb/kcc
|
||||
365
CHANGELOG.md
Normal file
365
CHANGELOG.md
Normal file
@@ -0,0 +1,365 @@
|
||||
# CHANGELOG
|
||||
#### 5.5.0:
|
||||
* Added support for WebP format
|
||||
* Added profiles for Kindle Paperwhite 4 and Kobo Forma
|
||||
* All archives are now handled by 7z
|
||||
* Removed MCD support
|
||||
* Fixed multiple smaller issues
|
||||
|
||||
#### 5.4.5:
|
||||
* Fixed EPUB output for non-Kindle devices
|
||||
|
||||
#### 5.4.4:
|
||||
* Minor bug fixes
|
||||
|
||||
#### 5.4.3:
|
||||
* Fixed conversion crash on Windows
|
||||
|
||||
#### 5.4.2:
|
||||
* Added Kindle Oasis 2 profile
|
||||
* Allowed metadata editor to edit directories
|
||||
* Fixed image stretching when HQ Panel View option was enabled
|
||||
* Fixed possible problem with directory sort order
|
||||
|
||||
#### 5.4.1:
|
||||
* Minor bug fixes and tweaks
|
||||
* Implemented new binary build pipeline
|
||||
|
||||
#### 5.4:
|
||||
* Reimplemented high quality Panel View option
|
||||
* Improved webtoon splitter
|
||||
* Fixed page splitter
|
||||
|
||||
#### 5.3.1:
|
||||
* Small increase of output quality
|
||||
* Improved error reporting
|
||||
* Internal changes and tweaks
|
||||
|
||||
#### 5.3:
|
||||
* Vastly improved output compatibility for non-Kindle devices
|
||||
* Enabled old pinch zoom for Kindle devices
|
||||
* Re-enabled Panel View support for Kindle Keyboard
|
||||
* Partially re-enabled OS X file association mechanism
|
||||
* Fixed multiple smaller issues
|
||||
|
||||
#### 5.2.1:
|
||||
* Improved directory parsing
|
||||
* Tweaked margin detection algorithm
|
||||
* Improved error reporting
|
||||
|
||||
#### 5.2:
|
||||
* Added new Panel View options
|
||||
* Implemented new margin detection algorithm
|
||||
* Removed HQ Panel View mode
|
||||
* Fixed multiple smaller issues
|
||||
|
||||
#### 5.1.3:
|
||||
* Added Kobo Aura ONE profile
|
||||
* Fixed few small bugs
|
||||
|
||||
#### 5.1.2:
|
||||
* Fixed error reporting
|
||||
|
||||
#### 5.1.1:
|
||||
* Fixed multiple GUI bugs
|
||||
|
||||
#### 5.1:
|
||||
* GUI now can be resized and high DPI support was somewhat improved
|
||||
* Added profile for Kindle Oasis
|
||||
* Implemented new error reporting mechanism
|
||||
* CLI version now support additional cropping options
|
||||
* Fixed permission issues on Windows
|
||||
* Fixed multiple smaller issues
|
||||
|
||||
#### 5.0.1:
|
||||
* Fixed Panel View placement issues
|
||||
* Decreased application startup time
|
||||
* Fixed multiple smaller issues
|
||||
|
||||
#### 5.0:
|
||||
* Major overhaul of internal mechanisms and GUI
|
||||
* Added cover upload feature
|
||||
* Tweaked Webtoon parsing mode
|
||||
* Fixed multiple smaller issues
|
||||
* Migrated build enviroment to PyInstaller
|
||||
|
||||
#### 4.6.5:
|
||||
* Fixed multiple Windows and OS X issues
|
||||
* Allowed Linux release to use older PyQT5 version
|
||||
|
||||
#### 4.6.4:
|
||||
* Fixed multiple Windows specific problems
|
||||
* Improved error handling
|
||||
* Improved color detection algorithm
|
||||
* New, slimmer OS X release
|
||||
|
||||
#### 4.6.3:
|
||||
* Implemented remote bug reporting
|
||||
* Minor bug fixes and GUI tweaks
|
||||
|
||||
#### 4.6.2:
|
||||
* Fixed critical MOBI header bug
|
||||
* Fixed metadata encoding error
|
||||
|
||||
#### 4.6.1:
|
||||
* Fixed KEPUB TOC generator
|
||||
* Added warning about too small input files
|
||||
* ComicRack Summary metadata field is now parsed
|
||||
* Small tweaks of KEPUB output
|
||||
|
||||
#### 4.6:
|
||||
* KEPUB is now default output for all Kobo profiles
|
||||
* EPUB output now produce fully valid EPUB 3.0.1
|
||||
* Added profile for Kindle Paperwhite 3
|
||||
* Dropped official support of all Kindle Fire models and Kindle for Android
|
||||
* Other minor tweaks
|
||||
|
||||
#### 4.5.1:
|
||||
* Added Kobo Glo HD profile
|
||||
* Fixed RAR/CBR parsing anomalies
|
||||
* Minor bug fixes and tweaks
|
||||
|
||||
#### 4.5:
|
||||
* Added simple ComicRack metadata editor
|
||||
* Re-enabled Manga Cover Database support
|
||||
* ComicRack bookmarks are now parsed
|
||||
* Fixed glitches in Kindle Voyage profile
|
||||
* Fixed problems with directory locks on Windows
|
||||
* Fixed sorting anomalies
|
||||
* Improved conversion speed
|
||||
|
||||
#### 4.4.1:
|
||||
* Fixed problems with OSX GUI
|
||||
* Added one missing DLL to Windows installer
|
||||
|
||||
#### 4.4:
|
||||
* Improved speed and quality of conversion
|
||||
* Added RAR5 support
|
||||
* Dropped BMP and TIFF support
|
||||
* Fixed some WebToon mode bugs
|
||||
* Fixed CBR parsing on OSX
|
||||
|
||||
#### 4.3.1:
|
||||
* Fixed Kindle Voyage profile
|
||||
* Fixed some bugs in OS X release
|
||||
* CLI version now support multiple input files at once
|
||||
* Disabled MCB support
|
||||
* Other minor tweaks
|
||||
|
||||
#### 4.3:
|
||||
* Added profiles for Kindle Voyage and Kobo Aura H2O
|
||||
* Added missing features to CLI version
|
||||
* Other minor bug fixes
|
||||
|
||||
#### 4.2.1:
|
||||
* Improved margin color detection
|
||||
* Fixed random crashes of MOBI processing step
|
||||
* Fixed resizing problems in high quality mode
|
||||
* Fixed some MCD support bugs
|
||||
* Default output format for Kindle DX is now CBZ
|
||||
|
||||
#### 4.2:
|
||||
* Added [Manga Cover Database](http://manga.joentjuh.nl/) support
|
||||
* Officially dropped Windows XP support
|
||||
* Fixed _Other_ profile
|
||||
* Fixed problems with page order on stock KOBO CBZ reader
|
||||
* Many other small bug fixes and tweaks
|
||||
|
||||
#### 4.1:
|
||||
* Thanks to code contributed by Kevin Hendricks speed of MOBI creation was greatly increased
|
||||
* Improved performance on Windows
|
||||
* Improved MOBI splitting and changed maximal size of output file
|
||||
* Fixed _No optimization_ mode
|
||||
* Multiple small tweaks nad minor bug fixes
|
||||
|
||||
#### 4.0.2:
|
||||
* Fixed some Windows and OSX specific bugs
|
||||
* Fixed problem with marigns when using HQ mode
|
||||
|
||||
#### 4.0.1:
|
||||
* Fixed file lock problems that plagued some Windows users
|
||||
* Fixed content server failing to start on Windows
|
||||
* Improved performance of WebToon splitter
|
||||
* Tweaked margin color detection
|
||||
|
||||
#### 4.0:
|
||||
* KCC now use Python 3.3 and Qt 5.2
|
||||
* Full UTF-8 awareness
|
||||
* CBZ output now support Manga mode
|
||||
* Improved Panel View support and margin color detection
|
||||
* Added drag&drop support
|
||||
* Output directory can be now selected
|
||||
* Windows release now have auto-updater
|
||||
* Names of chapters on Kindle should be now more user friendly
|
||||
* Fixed OSX file association support
|
||||
* Many extensive internal changes and tweaks
|
||||
|
||||
#### 3.7.2:
|
||||
* Fixed problems with HQ mode
|
||||
|
||||
#### 3.7.1:
|
||||
* Hotfixed Kobo profiles
|
||||
|
||||
#### 3.7:
|
||||
* Added profiles for KOBO devices
|
||||
* Improved Panel View support
|
||||
* Improved WebToon splitter
|
||||
* Improved margin color autodetection
|
||||
* Tweaked EPUB output
|
||||
* Fixed stretching option
|
||||
* GUI tweaks and minor bugfixes
|
||||
|
||||
#### 3.6.2:
|
||||
* Fixed previous PNG output fix
|
||||
* Fixed Panel View anomalies
|
||||
|
||||
#### 3.6.1:
|
||||
* Fixed PNG output
|
||||
|
||||
#### 3.6:
|
||||
* Increased quality of Panel View zoom
|
||||
* Creation of multipart MOBI output is now faster on machines with 4GB+ RAM
|
||||
* Automatic gamma correction now distinguishes color and grayscale images
|
||||
* Added ComicRack metadata parser
|
||||
* Implemented new method to detect border color in non-webtoon comics
|
||||
* Upscaling is now enabled by default for Kindle Fire HD/HDX
|
||||
* Windows nad Linux releases now have tray icon
|
||||
* Fixed Kindle Fire HDX 7" output
|
||||
* Increased target resolution for Kindle DX/DXG CBZ output
|
||||
|
||||
#### 3.5:
|
||||
* Added simple content server - Converted files can be now delivered wireless
|
||||
* Added proper Windows installer
|
||||
* Improved multiprocessing speed
|
||||
* GUI tweaks and minor bug fixes
|
||||
|
||||
#### 3.4:
|
||||
* Improved PNG output
|
||||
* Increased quality of upscaling
|
||||
* Added support of file association - KCC can now open CBZ, CBR, CB7, ZIP, RAR, 7Z and PDF files directly
|
||||
* Paths that contain UTF-8 characters are now supported
|
||||
* Migrated to new version of Pillow library
|
||||
* Merged DX and DXG profiles
|
||||
* Many other minor bug fixes and GUI tweaks
|
||||
|
||||
#### 3.3:
|
||||
* Margins are now automatically omitted in Panel View mode
|
||||
* Margin color fill is now autodetected
|
||||
* Created MOBI files are not longer marked as _Personal_ on newer Kindle models
|
||||
* Layout of panels in Panel View mode is now automatically adjusted to content
|
||||
* Fixed Kindle 2/DX/DXG profiles - no more blank pages
|
||||
* All Kindle Fire profiles now support hiqh quality Panel View
|
||||
* Added support of 7z/CB7 files
|
||||
* Added Kindle Fire HDX profile
|
||||
* Support for Virtual Panel View was removed
|
||||
* Profiles for Kindle Keyboard, Touch and Non-Touch are now merged
|
||||
* Windows release is now bundled with UnRAR and 7za
|
||||
* Small GUI tweaks
|
||||
|
||||
#### 3.2:
|
||||
* Too big EPUB files are now splitted before conversion to MOBI
|
||||
* Added experimental parser of manga webtoons
|
||||
* Improved error handling
|
||||
|
||||
#### 3.2.1:
|
||||
* Hotfixed crash occurring on OS with Russian locale
|
||||
|
||||
#### 3.1:
|
||||
* Added profile: Kindle for Android
|
||||
* Add file/directory dialogs now support multiselect
|
||||
* Many small fixes and tweaks
|
||||
|
||||
#### 3.0:
|
||||
* New QT GUI
|
||||
* Merge with AWKCC
|
||||
* Added ultra quality mode
|
||||
* Added support for custom width/height
|
||||
* Added option to disable color conversion
|
||||
|
||||
#### 2.10:
|
||||
* Multiprocessing support
|
||||
* Kindle Fire support (color EPUB/MOBI)
|
||||
* Panel View support for horizontal content
|
||||
* Fixed panel order for horizontal pages when --rotate is enabled
|
||||
* Disabled cropping and page number cutting for blank pages
|
||||
* Fixed some slugify issues with specific file naming conventions (#50, #51)
|
||||
|
||||
#### 2.9
|
||||
* Added support for generating a plain CBZ (skipping all the EPUB/MOBI generation) (#45)
|
||||
* Prevent output file overwriting the source one: if a duplicate name is detected, append _kcc to the name
|
||||
* Rarfile library updated to 2.6
|
||||
* Added GIF, TIFF and BMP to supported formats (#42)
|
||||
* Filenames slugifications (#28, #31, #9, #8)
|
||||
|
||||
#### 2.8
|
||||
* Updated rarfile library
|
||||
* Panel View support + HQ support (#36) - new option: --nopanelviewhq
|
||||
* Split profiles for K4NT and K4T
|
||||
* Rewrite of Landscape Mode support (huge readability improvement for KPW)
|
||||
* Upscale use now BILINEAR method
|
||||
* Added generic CSS file
|
||||
* Optimized archive extraction for zip/rar files (#40)
|
||||
|
||||
#### 2.7
|
||||
* Lots of GUI improvements (#27, #13)
|
||||
* Added gamma support within --gamma option (defaults to profile-specified gamma) (#26, #27)
|
||||
* Added --nodithering option to prevent dithering optimizations (#27)
|
||||
* EPUB margins support (#30)
|
||||
* Fixed no file added if file has no spaces on Windows (#25)
|
||||
* Gracefully exit if unrar missing (#15)
|
||||
* Do not call kindlegen if source EPUB is bigger than 320MB (#17)
|
||||
* Get filetype from magic number (#14)
|
||||
* PDF conversion works again
|
||||
|
||||
#### 2.6
|
||||
* Added --rotate option to rotate landscape images instead of splitting them (#16, #24)
|
||||
* Added --output option to customize EPUB output dir/file (#22)
|
||||
* Add rendition:layout and rendition:orientation EPUB meta tags (supported by new kindlegen 2.8)
|
||||
* Fixed natural sorting for files (#18)
|
||||
|
||||
#### 2.5
|
||||
* Added --black-borders option to set added borders black when page's ratio is not the device's one (#11).
|
||||
* Fixes EPUB containing zipped itself (#10)
|
||||
|
||||
#### 2.4
|
||||
* Use temporary directory as workdir (fixes converting from external volumes and zipfiles renaming)
|
||||
* Fixed "add folders" from GUI.
|
||||
|
||||
#### 2.3
|
||||
* Fixed win32 EPUB generation, folder handling, filenames with spaces and subfolders
|
||||
|
||||
#### 2.2:
|
||||
* Added (valid!) EPUB 2.0 output
|
||||
* Rename .zip files to .cbz to avoid overwriting
|
||||
|
||||
#### 2.1
|
||||
* Added basic error reporting
|
||||
|
||||
#### 2.0
|
||||
* GUI! AppleScript is gone and Tk is used to provide cross-platform GUI support.
|
||||
|
||||
#### 1.5
|
||||
* Added subfolder support for multiple chapters.
|
||||
|
||||
#### 1.4.1
|
||||
* Fixed a serious bug on resizing when img ratio was bigger than device one
|
||||
|
||||
#### 1.4
|
||||
* Added some options for controlling image optimization
|
||||
* Further optimization (ImageOps, page numbering cut, autocontrast)
|
||||
|
||||
#### 1.3
|
||||
* Fixed an issue in OPF generation for device resolution
|
||||
* Reworked options system (call with -h option to get the inline help)
|
||||
|
||||
#### 1.2
|
||||
* Comic optimizations! Split pages not target-oriented (landscape with portrait target or portrait with landscape target), add palette and other image optimizations from Mangle. WARNING: PIL is required for all image mangling!
|
||||
|
||||
#### 1.1.1
|
||||
* Added support for CBZ/CBR files in Kindle Comic Converter
|
||||
|
||||
#### 1.1
|
||||
* Added support for CBZ/CBR files in comic2ebook.py
|
||||
|
||||
#### 1.0
|
||||
* Initial version
|
||||
823
KCC-Linux.ui
823
KCC-Linux.ui
@@ -1,823 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>KCC</class>
|
||||
<widget class="QMainWindow" name="KCC">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>420</width>
|
||||
<height>397</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>420</width>
|
||||
<height>397</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>420</width>
|
||||
<height>397</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Kindle Comic Converter</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="KCC.qrc">
|
||||
<normaloff>:/Icon/icons/comic2ebook.png</normaloff>:/Icon/icons/comic2ebook.png</iconset>
|
||||
</property>
|
||||
<property name="locale">
|
||||
<locale language="C" country="AnyCountry"/>
|
||||
</property>
|
||||
<widget class="QWidget" name="Form">
|
||||
<widget class="QFrame" name="OptionsAdvanced">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>1</x>
|
||||
<y>254</y>
|
||||
<width>421</width>
|
||||
<height>61</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="ProcessingBox">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Disable image optimizations.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>No optimisation</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="UpscaleBox">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><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></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Stretch/Upscale</string>
|
||||
</property>
|
||||
<property name="tristate">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="WebtoonBox">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Enable auto-splitting of webtoons like <span style=" font-style:italic;">Tower of God</span> or <span style=" font-style:italic;">Noblesse</span>.<br/>Pages with a low width, high height and vertical panel flow.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Webtoon mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QCheckBox" name="NoDitheringBox">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Create PNG files instead JPEG.<br/>Quality increase is not noticeable on most of devices.<br/>Output files <span style=" font-weight:600;">might</span> be smaller.<br/><span style=" font-weight:600;">MOBI conversion will be much slower.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PNG output</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="BorderBox">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-weight:600; text-decoration: underline;">Unchecked - Autodetection<br/></span>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></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>W/B margins</string>
|
||||
</property>
|
||||
<property name="tristate">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QCheckBox" name="NoRotateBox">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Disable splitting and rotation.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>No split/rotate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QComboBox" name="DeviceBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>200</y>
|
||||
<width>141</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Target device.</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QComboBox" name="FormatBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>260</x>
|
||||
<y>200</y>
|
||||
<width>151</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Output format.</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="ConvertButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>160</x>
|
||||
<y>200</y>
|
||||
<width>91</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Convert</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="KCC.qrc">
|
||||
<normaloff>:/Other/icons/convert.png</normaloff>:/Other/icons/convert.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="DirectoryButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>160</y>
|
||||
<width>141</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add directory</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="KCC.qrc">
|
||||
<normaloff>:/Other/icons/folder_new.png</normaloff>:/Other/icons/folder_new.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="FileButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>260</x>
|
||||
<y>160</y>
|
||||
<width>151</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add file</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="KCC.qrc">
|
||||
<normaloff>:/Other/icons/document_new.png</normaloff>:/Other/icons/document_new.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="ClearButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>160</x>
|
||||
<y>160</y>
|
||||
<width>91</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Clear list</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="KCC.qrc">
|
||||
<normaloff>:/Other/icons/clear.png</normaloff>:/Other/icons/clear.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QFrame" name="OptionsBasic">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>1</x>
|
||||
<y>230</y>
|
||||
<width>421</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<widget class="QCheckBox" name="MangaBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>9</x>
|
||||
<y>10</y>
|
||||
<width>130</width>
|
||||
<height>18</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Enable right-to-left reading.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Manga mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QCheckBox" name="QualityBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>282</x>
|
||||
<y>10</y>
|
||||
<width>135</width>
|
||||
<height>18</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600; text-decoration: underline;">Unchecked - Normal quality mode<br /></span><span style=" font-family:'MS Shell Dlg 2'; font-style:italic;">Use it when Panel View support is not needed.</span><span style=" font-family:'MS Shell Dlg 2'; font-weight:600; text-decoration: underline;"><br /></span><span style=" font-family:'MS Shell Dlg 2';">- Maximum quality when zoom is not enabled.<br />- Poor quality when zoom is enabled.<br />- Lowest file size.</span></p>
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600; text-decoration: underline;">Indeterminate - High quality mode<br /></span><span style=" font-family:'MS Shell Dlg 2'; font-style:italic;">Not zoomed image </span><span style=" font-family:'MS Shell Dlg 2'; font-weight:600; font-style:italic;">might </span><span style=" font-family:'MS Shell Dlg 2'; font-style:italic;">be a little blurry.</span><span style=" font-family:'MS Shell Dlg 2'; font-weight:600; text-decoration: underline;"><br /></span><span style=" font-family:'MS Shell Dlg 2';">- Medium/High quality when zoom is not enabled.<br />- Maximum quality when zoom is enabled.</span></p>
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600; text-decoration: underline;">Checked - Ultra quality mode<br /></span><span style=" font-family:'MS Shell Dlg 2'; font-style:italic;">Maximum possible quality.</span><span style=" font-family:'MS Shell Dlg 2'; font-weight:600; text-decoration: underline;"><br /></span><span style=" font-family:'MS Shell Dlg 2';">- Maximum quality when zoom is not enabled.<br />- Maximum quality when zoom is enabled.<br />- Very high file size.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>High/Ultra quality</string>
|
||||
</property>
|
||||
<property name="tristate">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QCheckBox" name="RotateBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>145</x>
|
||||
<y>10</y>
|
||||
<width>130</width>
|
||||
<height>18</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Disable page spliting.<br/>They will be rotated instead.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Horizontal mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
<zorder>RotateBox</zorder>
|
||||
<zorder>MangaBox</zorder>
|
||||
<zorder>QualityBox</zorder>
|
||||
</widget>
|
||||
<widget class="QListWidget" name="JobList">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>50</y>
|
||||
<width>401</width>
|
||||
<height>101</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
<pointsize>8</pointsize>
|
||||
<italic>false</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}</string>
|
||||
</property>
|
||||
<property name="showDropIndicator" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::NoSelection</enum>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>18</width>
|
||||
<height>18</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="BasicModeButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>195</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Basic</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="AdvModeButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>217</x>
|
||||
<y>10</y>
|
||||
<width>195</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Advanced</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QFrame" name="OptionsAdvancedGamma">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>305</y>
|
||||
<width>401</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<widget class="QLabel" name="GammaLabel">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>15</x>
|
||||
<y>0</y>
|
||||
<width>100</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Gamma: Auto</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QSlider" name="GammaSlider">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>110</x>
|
||||
<y>10</y>
|
||||
<width>275</width>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::ClickFocus</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>500</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QProgressBar" name="ProgressBar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>401</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
<pointsize>10</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignJustify|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="format">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QFrame" name="OptionsExpert">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>1</x>
|
||||
<y>337</y>
|
||||
<width>421</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<widget class="QCheckBox" name="ColorBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>9</x>
|
||||
<y>11</y>
|
||||
<width>130</width>
|
||||
<height>18</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Do not convert images to grayscale.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Color mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QFrame" name="OptionsExpertInternal">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>105</x>
|
||||
<y>0</y>
|
||||
<width>295</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="wLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Resolution of target device.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Custom width: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="customWidth">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::ClickFocus</enum>
|
||||
</property>
|
||||
<property name="acceptDrops">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Resolution of target device.</string>
|
||||
</property>
|
||||
<property name="inputMask">
|
||||
<string>0000; </string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>4</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="hLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Resolution of target device.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Custom height: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QLineEdit" name="customHeight">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::ClickFocus</enum>
|
||||
</property>
|
||||
<property name="acceptDrops">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Resolution of target device.</string>
|
||||
</property>
|
||||
<property name="inputMask">
|
||||
<string>0000; </string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>4</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<zorder>OptionsAdvanced</zorder>
|
||||
<zorder>DeviceBox</zorder>
|
||||
<zorder>FormatBox</zorder>
|
||||
<zorder>ConvertButton</zorder>
|
||||
<zorder>DirectoryButton</zorder>
|
||||
<zorder>FileButton</zorder>
|
||||
<zorder>ClearButton</zorder>
|
||||
<zorder>OptionsBasic</zorder>
|
||||
<zorder>JobList</zorder>
|
||||
<zorder>BasicModeButton</zorder>
|
||||
<zorder>AdvModeButton</zorder>
|
||||
<zorder>OptionsAdvancedGamma</zorder>
|
||||
<zorder>OptionsExpert</zorder>
|
||||
<zorder>ProgressBar</zorder>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusBar">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="sizeGripEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<action name="ActionBasic">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Basic</string>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font/>
|
||||
</property>
|
||||
</action>
|
||||
<action name="ActionAdvanced">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Advanced</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>DirectoryButton</tabstop>
|
||||
<tabstop>FileButton</tabstop>
|
||||
<tabstop>ConvertButton</tabstop>
|
||||
<tabstop>ClearButton</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="KCC.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
837
KCC-OSX.ui
837
KCC-OSX.ui
@@ -1,837 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>KCC</class>
|
||||
<widget class="QMainWindow" name="KCC">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>420</width>
|
||||
<height>397</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>420</width>
|
||||
<height>397</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>420</width>
|
||||
<height>397</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Kindle Comic Converter</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="KCC.qrc">
|
||||
<normaloff>:/Icon/icons/comic2ebook.png</normaloff>:/Icon/icons/comic2ebook.png</iconset>
|
||||
</property>
|
||||
<property name="locale">
|
||||
<locale language="C" country="AnyCountry"/>
|
||||
</property>
|
||||
<widget class="QWidget" name="Form">
|
||||
<widget class="QFrame" name="OptionsAdvanced">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>4</x>
|
||||
<y>253</y>
|
||||
<width>421</width>
|
||||
<height>61</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="ProcessingBox">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-size:12pt;">Disable image optimizations.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>No optimisation</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="UpscaleBox">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-size:12pt; font-weight:600; text-decoration: underline;">Unchecked - Nothing<br/></span><span style=" font-size:12pt;">Images smaller than device resolution will not be resized.</span></p><p><span style=" font-size:12pt; font-weight:600; text-decoration: underline;">Indeterminate - Stretching<br/></span><span style=" font-size:12pt;">Images smaller than device resolution will be resized. Aspect ratio will be not preserved.</span></p><p><span style=" font-size:12pt; font-weight:600; text-decoration: underline;">Checked - Upscaling<br/></span><span style=" font-size:12pt;">Images smaller than device resolution will be resized. Aspect ratio will be preserved.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Stretch/Upscale</string>
|
||||
</property>
|
||||
<property name="tristate">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="WebtoonBox">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-size:12pt;">Enable auto-splitting of webtoons like </span><span style=" font-size:12pt; font-style:italic;">Tower of God</span><span style=" font-size:12pt;"> or </span><span style=" font-size:12pt; font-style:italic;">Noblesse</span><span style=" font-size:12pt;">.<br/>Pages with a low width, high height and vertical panel flow.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Webtoon mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QCheckBox" name="NoDitheringBox">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-size:12pt;">Create PNG files instead JPEG.<br/>Quality increase is not noticeable on most of devices.<br/>Output files </span><span style=" font-size:12pt; font-weight:600;">might</span><span style=" font-size:12pt;"> be smaller.<br/></span><span style=" font-size:12pt; font-weight:600;">MOBI conversion will be much slower.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PNG output</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="BorderBox">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-size:12pt; font-weight:600; text-decoration: underline;">Unchecked - Autodetection<br/></span><span style=" font-size:12pt;">Color of margins fill will be detected automatically.</span></p><p><span style=" font-size:12pt; font-weight:600; text-decoration: underline;">Indeterminate - White<br/></span><span style=" font-size:12pt;">Margins will be filled with white color.</span></p><p><span style=" font-size:12pt; font-weight:600; text-decoration: underline;">Checked - Black<br/></span><span style=" font-size:12pt;">Margins will be filled with black color.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>W/B margins</string>
|
||||
</property>
|
||||
<property name="tristate">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QCheckBox" name="NoRotateBox">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-size:12pt;">Disable splitting and rotation.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>No split/rotate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QComboBox" name="DeviceBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>8</x>
|
||||
<y>201</y>
|
||||
<width>151</width>
|
||||
<height>34</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-size:12pt;">Target device.</span></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QComboBox" name="FormatBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>262</x>
|
||||
<y>201</y>
|
||||
<width>152</width>
|
||||
<height>34</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-size:12pt;">Output format.</span></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="ConvertButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>160</x>
|
||||
<y>200</y>
|
||||
<width>101</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>11</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Convert</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="KCC.qrc">
|
||||
<normaloff>:/Other/icons/convert.png</normaloff>:/Other/icons/convert.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="DirectoryButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>5</x>
|
||||
<y>160</y>
|
||||
<width>156</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add directory</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="KCC.qrc">
|
||||
<normaloff>:/Other/icons/folder_new.png</normaloff>:/Other/icons/folder_new.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="FileButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>260</x>
|
||||
<y>160</y>
|
||||
<width>157</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add file</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="KCC.qrc">
|
||||
<normaloff>:/Other/icons/document_new.png</normaloff>:/Other/icons/document_new.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="ClearButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>160</x>
|
||||
<y>160</y>
|
||||
<width>101</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Clear list</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="KCC.qrc">
|
||||
<normaloff>:/Other/icons/clear.png</normaloff>:/Other/icons/clear.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QFrame" name="OptionsBasic">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>5</x>
|
||||
<y>233</y>
|
||||
<width>421</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<widget class="QCheckBox" name="MangaBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>9</x>
|
||||
<y>10</y>
|
||||
<width>130</width>
|
||||
<height>18</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-size:12pt;">Enable right-to-left reading.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Manga mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QCheckBox" name="QualityBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>282</x>
|
||||
<y>10</y>
|
||||
<width>135</width>
|
||||
<height>18</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style="font-size:12pt; font-weight:600; text-decoration: underline;">Unchecked - Normal quality mode<br/></span><span style="font-size:12pt; font-style:italic;">Use it when Panel View support is not needed.</span><span style="font-size:12pt; font-weight:600; text-decoration: underline;"><br/></span><span style="font-size:12pt;">- Maximum quality when zoom is not enabled.<br/>- Poor quality when zoom is enabled.<br/>- Lowest file size.</span></p><p><span style="font-size:12pt; font-weight:600; text-decoration: underline;">Indeterminate - High quality mode<br/></span><span style="font-size:12pt; font-style:italic;">Not zoomed image </span><span style="font-size:12pt; font-weight:600; font-style:italic;">might </span><span style="font-size:12pt; font-style:italic;">be a little blurry.</span><span style="font-size:12pt; font-weight:600; text-decoration: underline;"><br/></span><span style="font-size:12pt;">- Medium/High quality when zoom is not enabled.<br/>- Maximum quality when zoom is enabled.</span></p><p><span style="font-size:12pt; font-weight:600; text-decoration: underline;">Checked - Ultra quality mode<br/></span><span style="font-size:12pt; font-style:italic;">Maximum possible quality.</span><span style="font-size:12pt; font-weight:600; text-decoration: underline;"><br/></span><span style="font-size:12pt;">- Maximum quality when zoom is not enabled.<br/>- Maximum quality when zoom is enabled.<br/>- Very high file size.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>High/Ultra quality</string>
|
||||
</property>
|
||||
<property name="tristate">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QCheckBox" name="RotateBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>145</x>
|
||||
<y>10</y>
|
||||
<width>130</width>
|
||||
<height>18</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-size:12pt;">Disable page spliting.<br/>They will be rotated instead.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Horizontal mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
<zorder>RotateBox</zorder>
|
||||
<zorder>MangaBox</zorder>
|
||||
<zorder>QualityBox</zorder>
|
||||
</widget>
|
||||
<widget class="QListWidget" name="JobList">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>50</y>
|
||||
<width>401</width>
|
||||
<height>101</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}</string>
|
||||
</property>
|
||||
<property name="showDropIndicator" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::NoSelection</enum>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="BasicModeButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>5</x>
|
||||
<y>10</y>
|
||||
<width>210</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Basic</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="AdvModeButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>207</x>
|
||||
<y>10</y>
|
||||
<width>210</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Advanced</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QFrame" name="OptionsAdvancedGamma">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>5</x>
|
||||
<y>303</y>
|
||||
<width>401</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<widget class="QLabel" name="GammaLabel">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>0</y>
|
||||
<width>100</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Gamma: Auto</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QSlider" name="GammaSlider">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>110</x>
|
||||
<y>10</y>
|
||||
<width>290</width>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::ClickFocus</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>500</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QProgressBar" name="ProgressBar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>401</width>
|
||||
<height>35</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>10</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignJustify|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="format">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QFrame" name="OptionsExpert">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>5</x>
|
||||
<y>335</y>
|
||||
<width>421</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<widget class="QCheckBox" name="ColorBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>9</x>
|
||||
<y>11</y>
|
||||
<width>130</width>
|
||||
<height>18</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-size:12pt;">Do not convert images to grayscale.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Color mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QFrame" name="OptionsExpertInternal">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>95</x>
|
||||
<y>0</y>
|
||||
<width>315</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
</font>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="wLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-size:12pt;">Resolution of target device.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Custom width: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="customWidth">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>45</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::ClickFocus</enum>
|
||||
</property>
|
||||
<property name="acceptDrops">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-size:12pt;">Resolution of target device.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="inputMask">
|
||||
<string>0000; </string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>4</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="hLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-size:12pt;">Resolution of target device.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Custom height: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QLineEdit" name="customHeight">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>45</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::ClickFocus</enum>
|
||||
</property>
|
||||
<property name="acceptDrops">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-size:12pt;">Resolution of target device.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="inputMask">
|
||||
<string>0000; </string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>4</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<zorder>BasicModeButton</zorder>
|
||||
<zorder>AdvModeButton</zorder>
|
||||
<zorder>ProgressBar</zorder>
|
||||
<zorder>JobList</zorder>
|
||||
<zorder>OptionsAdvanced</zorder>
|
||||
<zorder>DeviceBox</zorder>
|
||||
<zorder>FormatBox</zorder>
|
||||
<zorder>ConvertButton</zorder>
|
||||
<zorder>DirectoryButton</zorder>
|
||||
<zorder>FileButton</zorder>
|
||||
<zorder>ClearButton</zorder>
|
||||
<zorder>OptionsBasic</zorder>
|
||||
<zorder>OptionsAdvancedGamma</zorder>
|
||||
<zorder>OptionsExpert</zorder>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusBar">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Aharoni</family>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="sizeGripEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<action name="ActionBasic">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Basic</string>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
</action>
|
||||
<action name="ActionAdvanced">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Advanced</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>DirectoryButton</tabstop>
|
||||
<tabstop>FileButton</tabstop>
|
||||
<tabstop>ConvertButton</tabstop>
|
||||
<tabstop>ClearButton</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="KCC.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
26
KCC.qrc
26
KCC.qrc
@@ -1,26 +0,0 @@
|
||||
<RCC>
|
||||
<qresource prefix="Icon">
|
||||
<file>icons/comic2ebook.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="Devices">
|
||||
<file>icons/Other.png</file>
|
||||
<file>icons/Kindle.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="Formats">
|
||||
<file>icons/CBZ.png</file>
|
||||
<file>icons/EPUB.png</file>
|
||||
<file>icons/MOBI.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="Status">
|
||||
<file>icons/error.png</file>
|
||||
<file>icons/info.png</file>
|
||||
<file>icons/warning.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="Other">
|
||||
<file>icons/list_background.png</file>
|
||||
<file>icons/clear.png</file>
|
||||
<file>icons/convert.png</file>
|
||||
<file>icons/document_new.png</file>
|
||||
<file>icons/folder_new.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
714
KCC.ui
714
KCC.ui
@@ -1,714 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>KCC</class>
|
||||
<widget class="QMainWindow" name="KCC">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>420</width>
|
||||
<height>397</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>420</width>
|
||||
<height>397</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>420</width>
|
||||
<height>397</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Kindle Comic Converter</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="KCC.qrc">
|
||||
<normaloff>:/Icon/icons/comic2ebook.png</normaloff>:/Icon/icons/comic2ebook.png</iconset>
|
||||
</property>
|
||||
<property name="locale">
|
||||
<locale language="C" country="AnyCountry"/>
|
||||
</property>
|
||||
<widget class="QWidget" name="Form">
|
||||
<widget class="QFrame" name="OptionsAdvanced">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>254</y>
|
||||
<width>421</width>
|
||||
<height>61</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="ProcessingBox">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Disable image optimizations.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>No optimisation</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="UpscaleBox">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><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></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Stretch/Upscale</string>
|
||||
</property>
|
||||
<property name="tristate">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="WebtoonBox">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Enable auto-splitting of webtoons like <span style=" font-style:italic;">Tower of God</span> or <span style=" font-style:italic;">Noblesse</span>.<br/>Pages with a low width, high height and vertical panel flow.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Webtoon mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QCheckBox" name="NoDitheringBox">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Create PNG files instead JPEG.<br/>Quality increase is not noticeable on most of devices.<br/>Output files <span style=" font-weight:600;">might</span> be smaller.<br/><span style=" font-weight:600;">MOBI conversion will be much slower.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PNG output</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="BorderBox">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-weight:600; text-decoration: underline;">Unchecked - Autodetection<br/></span>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></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>W/B margins</string>
|
||||
</property>
|
||||
<property name="tristate">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QCheckBox" name="NoRotateBox">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Disable splitting and rotation.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>No split/rotate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QComboBox" name="DeviceBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>200</y>
|
||||
<width>141</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Target device.</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QComboBox" name="FormatBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>260</x>
|
||||
<y>200</y>
|
||||
<width>151</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Output format.</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="ConvertButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>160</x>
|
||||
<y>200</y>
|
||||
<width>91</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Convert</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="KCC.qrc">
|
||||
<normaloff>:/Other/icons/convert.png</normaloff>:/Other/icons/convert.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="DirectoryButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>160</y>
|
||||
<width>141</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add directory</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="KCC.qrc">
|
||||
<normaloff>:/Other/icons/folder_new.png</normaloff>:/Other/icons/folder_new.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="FileButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>260</x>
|
||||
<y>160</y>
|
||||
<width>151</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add file</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="KCC.qrc">
|
||||
<normaloff>:/Other/icons/document_new.png</normaloff>:/Other/icons/document_new.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="ClearButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>160</x>
|
||||
<y>160</y>
|
||||
<width>91</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Clear list</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="KCC.qrc">
|
||||
<normaloff>:/Other/icons/clear.png</normaloff>:/Other/icons/clear.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QFrame" name="OptionsBasic">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>230</y>
|
||||
<width>421</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<widget class="QCheckBox" name="MangaBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>9</x>
|
||||
<y>10</y>
|
||||
<width>130</width>
|
||||
<height>18</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Enable right-to-left reading.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Manga mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QCheckBox" name="QualityBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>282</x>
|
||||
<y>10</y>
|
||||
<width>130</width>
|
||||
<height>18</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">Unchecked - Normal quality mode<br /></span><span style=" font-style:italic;">Use it when Panel View support is not needed.</span><span style=" font-weight:600; text-decoration: underline;"><br /></span>- Maximum quality when zoom is not enabled.<br />- Poor quality when zoom is enabled.<br />- Lowest file size.</p>
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">Indeterminate - High quality mode<br /></span><span style=" font-style:italic;">Not zoomed image </span><span style=" font-weight:600; font-style:italic;">might </span><span style=" font-style:italic;">be </span><span style=" font-style:italic;">a little blurry.</span><span style=" font-weight:600; text-decoration: underline;"><br /></span>- Medium/High quality when zoom is not enabled.<br />- Maximum quality when zoom is enabled.</p>
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">Checked - Ultra quality mode<br /></span><span style=" font-style:italic;">Maximum possible quality.</span><span style=" font-weight:600; text-decoration: underline;"><br /></span>- Maximum quality when zoom is not enabled.<br />- Maximum quality when zoom is enabled.<br />- Very high file size.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>High/Ultra quality</string>
|
||||
</property>
|
||||
<property name="tristate">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QCheckBox" name="RotateBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>145</x>
|
||||
<y>10</y>
|
||||
<width>130</width>
|
||||
<height>18</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Disable page spliting.<br/>They will be rotated instead.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Horizontal mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
<zorder>RotateBox</zorder>
|
||||
<zorder>MangaBox</zorder>
|
||||
<zorder>QualityBox</zorder>
|
||||
</widget>
|
||||
<widget class="QListWidget" name="JobList">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>50</y>
|
||||
<width>401</width>
|
||||
<height>101</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}</string>
|
||||
</property>
|
||||
<property name="showDropIndicator" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::NoSelection</enum>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="BasicModeButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>195</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Basic</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="AdvModeButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>217</x>
|
||||
<y>10</y>
|
||||
<width>195</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Advanced</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QFrame" name="OptionsAdvancedGamma">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>305</y>
|
||||
<width>401</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<widget class="QLabel" name="GammaLabel">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>15</x>
|
||||
<y>0</y>
|
||||
<width>100</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Gamma: Auto</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QSlider" name="GammaSlider">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>110</x>
|
||||
<y>10</y>
|
||||
<width>270</width>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::ClickFocus</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>500</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QProgressBar" name="ProgressBar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>401</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignJustify|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="format">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QFrame" name="OptionsExpert">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>337</y>
|
||||
<width>421</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<widget class="QCheckBox" name="ColorBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>9</x>
|
||||
<y>11</y>
|
||||
<width>130</width>
|
||||
<height>18</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Do not convert images to grayscale.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Color mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QFrame" name="OptionsExpertInternal">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>100</x>
|
||||
<y>0</y>
|
||||
<width>295</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="wLabel">
|
||||
<property name="toolTip">
|
||||
<string>Resolution of target device.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Custom width: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="customWidth">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::ClickFocus</enum>
|
||||
</property>
|
||||
<property name="acceptDrops">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Resolution of target device.</string>
|
||||
</property>
|
||||
<property name="inputMask">
|
||||
<string>0000; </string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>4</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="hLabel">
|
||||
<property name="toolTip">
|
||||
<string>Resolution of target device.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Custom height: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QLineEdit" name="customHeight">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::ClickFocus</enum>
|
||||
</property>
|
||||
<property name="acceptDrops">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Resolution of target device.</string>
|
||||
</property>
|
||||
<property name="inputMask">
|
||||
<string>0000; </string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>4</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<zorder>OptionsAdvanced</zorder>
|
||||
<zorder>DeviceBox</zorder>
|
||||
<zorder>FormatBox</zorder>
|
||||
<zorder>ConvertButton</zorder>
|
||||
<zorder>DirectoryButton</zorder>
|
||||
<zorder>FileButton</zorder>
|
||||
<zorder>ClearButton</zorder>
|
||||
<zorder>OptionsBasic</zorder>
|
||||
<zorder>JobList</zorder>
|
||||
<zorder>BasicModeButton</zorder>
|
||||
<zorder>AdvModeButton</zorder>
|
||||
<zorder>OptionsAdvancedGamma</zorder>
|
||||
<zorder>OptionsExpert</zorder>
|
||||
<zorder>ProgressBar</zorder>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusBar">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>MS Shell Dlg 2</family>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="sizeGripEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<action name="ActionBasic">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Basic</string>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
</action>
|
||||
<action name="ActionAdvanced">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Advanced</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>DirectoryButton</tabstop>
|
||||
<tabstop>FileButton</tabstop>
|
||||
<tabstop>ConvertButton</tabstop>
|
||||
<tabstop>ClearButton</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="KCC.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,7 +1,7 @@
|
||||
ISC LICENSE
|
||||
|
||||
Copyright (c) 2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||
Copyright (c) 2013 Paweł Jastrzębski <pawelj@vulturis.eu>
|
||||
Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||
Copyright (c) 2013-2019 Paweł Jastrzębski <pawelj@iosphe.re>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for
|
||||
any purpose with or without fee is hereby granted, provided that the
|
||||
|
||||
1
MANIFEST.in
Normal file
1
MANIFEST.in
Normal file
@@ -0,0 +1 @@
|
||||
exclude kindlecomicconverter/sentry.py
|
||||
343
README.md
343
README.md
@@ -1,88 +1,92 @@
|
||||
# KCC
|
||||
# KCC
|
||||
|
||||
**Kindle Comic Converter** is a Python app to convert comic files or folders to ePub or Panel View MOBI.
|
||||
It was initally developed for Kindle but since v2.2 it outputs valid ePub 2.0 so _**despite its name, KCC is
|
||||
actually a comic to EPUB converter that every e-reader owner can happily use**_.
|
||||
[](https://github.com/ciromattia/kcc/releases) [](https://pypi.python.org/pypi/KindleComicConverter) [](https://aur.archlinux.org/packages/kcc/)
|
||||
|
||||
**Kindle Comic Converter** is a Python app to convert comic/manga files or folders to EPUB, Panel View MOBI or E-Ink optimized CBZ.
|
||||
It was initially developed for Kindle but since version 4.6 it outputs valid EPUB 3.0 so _**despite its name, KCC is
|
||||
actually a comic/manga to EPUB converter that every e-reader owner can happily use**_.
|
||||
It can also optionally optimize images by applying a number of transformations.
|
||||
|
||||
### A word of warning
|
||||
**KCC** _is not_ [Amazon's Kindle Comic Creator](http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1001103761) nor is in any way endorsed by Amazon.
|
||||
Amazon's tool is for comic publishers and involves a lot of manual effort, while **KCC** is for comic readers.
|
||||
**KCC** _is not_ [Amazon's Kindle Comic Creator](http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1001103761) nor is in any way endorsed by Amazon.
|
||||
Amazon's tool is for comic publishers and involves a lot of manual effort, while **KCC** is for comic/manga readers.
|
||||
_KC2_ in no way is a replacement for **KCC** so you can be quite confident we'll going to carry on developing our little monster ;-)
|
||||
|
||||
### Issues / new features / donations
|
||||
If you have some problems using KCC please [file an issue here](https://github.com/ciromattia/kcc/issues/new).
|
||||
If you can fix an open issue, fork & make a pull request.
|
||||
If you want more chances an issue is fixes or your wanted feature added, consider [placing a bounty](https://www.bountysource.com/trackers/65571-ciromattia-kcc)!
|
||||
If you have general questions about usage, feedback etc. please [post it here](http://www.mobileread.com/forums/showthread.php?t=207461).
|
||||
If you have some **technical** problems using KCC please [file an issue here](https://github.com/ciromattia/kcc/issues/new).
|
||||
If you can fix an open issue, fork & make a pull request.
|
||||
|
||||
If you find **KCC** valuable you can consider donating to the authors:
|
||||
* Ciro Mattia Gonano: [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=D8WNYNPBGDAS2) [](http://flattr.com/thing/2260449/ciromattiakcc-on-GitHub)
|
||||
* Paweł Jastrzębski: [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YTTJ4LK2JDHPS) [](bitcoin:1W15wwqsfd7wbaZ6wvSJf1LW1bz6q5L8b?label=KCC) [1W15wwqsfd7wbaZ6wvSJf1LW1bz6q5L8b](bitcoin:1W15wwqsfd7wbaZ6wvSJf1LW1bz6q5L8b?label=KCC)
|
||||
- Ciro Mattia Gonano:
|
||||
- [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=D8WNYNPBGDAS2)
|
||||
- [](http://flattr.com/thing/2260449/ciromattiakcc-on-GitHub)
|
||||
- Paweł Jastrzębski:
|
||||
- [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YTTJ4LK2JDHPS)
|
||||
- [](https://jastrzeb.ski/donate/)
|
||||
|
||||
## BINARY RELEASES
|
||||
You can find the latest released binary at the following links:
|
||||
- **Windows:** [http://kcc.vulturis.eu/Windows/](http://kcc.vulturis.eu/Windows/)
|
||||
- **Linux:** [http://kcc.vulturis.eu/Linux/](http://kcc.vulturis.eu/Linux/)
|
||||
- **OS X (10.8 or later):** [http://kcc.vulturis.eu/OSX/](http://kcc.vulturis.eu/OSX/)
|
||||
- **OS X (10.7 or earlier):** Soon™
|
||||
- **[Windows](http://kcc.iosphe.re/Windows/) (64-bit only)**
|
||||
- **[macOS](http://kcc.iosphe.re/OSX/) (10.12+)**
|
||||
- **Linux:** Currently unavailable.
|
||||
|
||||
## PYPI
|
||||
**KCC** is also available on PyPI.
|
||||
```
|
||||
pip install KindleComicConverter
|
||||
```
|
||||
|
||||
## DEPENDENCIES
|
||||
Following software is required to run Linux version of **KCC** and/or bare sources:
|
||||
- Python 3.3+
|
||||
- [PyQt5](https://pypi.python.org/pypi/PyQt5) 5.6.0+
|
||||
- [Pillow](https://pypi.python.org/pypi/Pillow/) 4.0.0+
|
||||
- [psutil](https://pypi.python.org/pypi/psutil) 5.0.0+
|
||||
- [python-slugify](https://pypi.python.org/pypi/python-slugify) 1.2.1+
|
||||
- [raven](https://pypi.python.org/pypi/raven) 6.0.0+
|
||||
|
||||
On Debian based distributions these two commands should install all needed dependencies:
|
||||
```
|
||||
sudo apt-get install python3 python3-dev python3-pip libpng-dev libjpeg-dev p7zip-full
|
||||
sudo pip3 install --upgrade pillow python-slugify psutil pyqt5 raven
|
||||
```
|
||||
|
||||
### Optional dependencies
|
||||
- [KindleGen](http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1000765211) v2.9+ in a directory reachable by your _PATH_ or in _KCC_ directory *(For MOBI generation)*
|
||||
- [7z](http://www.7-zip.org/download.html) *(For CBZ/ZIP, CBR/RAR, 7z/CB7 support)*
|
||||
|
||||
## INPUT FORMATS
|
||||
**KCC** can understand and convert, at the moment, the following file types:
|
||||
- PNG, JPG, GIF, TIFF, BMP
|
||||
- Folders
|
||||
- CBZ, ZIP
|
||||
- CBR, RAR *(With `unrar` executable)*
|
||||
- CB7, 7Z *(With `7za` executable)*
|
||||
- PDF *(Extracting only contained JPG images)*
|
||||
|
||||
## OPTIONAL REQUIREMENTS
|
||||
- [KindleGen](http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1000765211) v2.9+ in a directory reachable by your _PATH_ or in _KCC_ directory *(For .mobi generation)*
|
||||
- [UnRAR](http://www.rarlab.com/download.htm) *(For CBR/RAR support)*
|
||||
- [7za](http://www.7-zip.org/download.html) *(For 7z/CB7 support)*
|
||||
|
||||
### For compiling/running from source:
|
||||
- Python 2.7 - Included in MacOS and Linux, follow the [official documentation](http://www.python.org/getit/windows/) to install on Windows.
|
||||
- [PyQt4](http://www.riverbankcomputing.co.uk/software/pyqt/download) - Please refer to official documentation for installing into your system.
|
||||
- [Pillow](http://pypi.python.org/pypi/Pillow/) 2.2.1+ - For comic optimizations. Please refer to official documentation for installing into your system.
|
||||
- [Psutil](https://code.google.com/p/psutil/) - Please refer to official documentation for installing into your system.
|
||||
- **To build OS X release you need a modified QT:** [patch](https://github.com/ciromattia/kcc/blob/master/other/QT-4.8.5-QListWidget.patch)
|
||||
**KCC** can understand and convert, at the moment, the following input types:
|
||||
- Folders containing: PNG, JPG, GIF or WebP files
|
||||
- CBZ, ZIP *(With `7z` executable)*
|
||||
- CBR, RAR *(With `7z` executable)*
|
||||
- CB7, 7Z *(With `7z` executable)*
|
||||
- PDF *(Only extracting JPG images)*
|
||||
|
||||
## USAGE
|
||||
|
||||
### Important tips:
|
||||
* Use high quality source files. **This little detail have a major impact on the final result.**
|
||||
* Read tooltip of _High/Ultra quality_ option. There are many important informations there.
|
||||
* When converting images smaller than device resolution remember to enable upscaling.
|
||||
* Panel View (auto zooming every part of page) can be disabled directly on Kindle. There is no KCC option to do that.
|
||||
* Check our [wiki](https://github.com/ciromattia/kcc/wiki/Other-devices) for a list of tested Non-Kindle E-Readers.
|
||||
* The first image found will be set as the comic's cover.
|
||||
* All files/directories will be added to EPUB in alphabetical order.
|
||||
* Using high/ultra quality output option with Kindle Fire HD/HDX in most cases is just waste of space.
|
||||
* ComicRack metadata will be parsed only if they are saved in *ComicInfo.xml* file.
|
||||
Should be pretty self-explanatory. All options have detailed information in tooltips.
|
||||
After completed conversion, you should find ready file alongside the original input file (same directory).
|
||||
|
||||
### Calibre:
|
||||
* Calibre can be used to upload files created by KCC.
|
||||
* Uploading KCC output with Calibre will remove *Personal* tag from cover.
|
||||
* **Don't convert files created by KCC with Calibre!** Any conversion process will corrupt the file!
|
||||
* Don't use Calibre reader to preview files created by KCC. It can't parse them correctly.
|
||||
Please check [our wiki](https://github.com/ciromattia/kcc/wiki/) for more details.
|
||||
|
||||
### GUI
|
||||
CLI version of **KCC** is intended for power users. It allows using options that might not be compatible and decrease the quality of output.
|
||||
|
||||
Should be pretty self-explanatory. All options have detailed informations in tooltips.
|
||||
After completed conversion you should find ready file alongside the original input file (same directory).
|
||||
|
||||
### Standalone `comic2ebook.py` usage:
|
||||
### Standalone `kcc-c2e.py` usage:
|
||||
|
||||
```
|
||||
Usage: comic2ebook.py [options] comic_file|comic_folder
|
||||
Usage: kcc-c2e [options] comic_file|comic_folder
|
||||
|
||||
Options:
|
||||
MAIN:
|
||||
-p PROFILE, --profile=PROFILE
|
||||
Device profile (Choose one among K1, K2, K345, KDX, KHD, KF, KFHD, KFHD8, KFHDX, KFHDX8, KFA) [Default=KHD]
|
||||
-q QUALITY, --quality=QUALITY
|
||||
Quality of Panel View. 0 - Normal 1 - High 2 - Ultra [Default=0]
|
||||
-m, --manga-style Manga style (Right-to-left reading and splitting)
|
||||
Device profile (Available options: K1, K2, K34, K578,
|
||||
KDX, KPW, KV, KO, KoMT, KoG, KoGHD, KoA, KoAHD, KoAH2O,
|
||||
KoAO, KoF) [Default=KV]
|
||||
-m, --manga-style Manga style (right-to-left reading and splitting)
|
||||
-q, --hq Try to increase the quality of magnification
|
||||
-2, --two-panel Display two not four panels in Panel View mode
|
||||
-w, --webtoon Webtoon processing mode
|
||||
|
||||
OUTPUT SETTINGS:
|
||||
@@ -90,21 +94,32 @@ Options:
|
||||
Output generated file to specified directory or file
|
||||
-t TITLE, --title=TITLE
|
||||
Comic title [Default=filename or directory name]
|
||||
--cbz-output Outputs a CBZ archive and does not generate EPUB
|
||||
--batchsplit Split output into multiple files
|
||||
-f FORMAT, --format=FORMAT
|
||||
Output format (Available options: Auto, MOBI, EPUB,
|
||||
CBZ, KFX) [Default=Auto]
|
||||
-b BATCHSPLIT, --batchsplit=BATCHSPLIT
|
||||
Split output into multiple files. 0: Don't split 1:
|
||||
Automatic mode 2: Consider every subdirectory as
|
||||
separate volume [Default=0]
|
||||
|
||||
PROCESSING:
|
||||
-u, --upscale Resize images smaller than device's resolution
|
||||
-s, --stretch Stretch images to device's resolution
|
||||
-r SPLITTER, --splitter=SPLITTER
|
||||
Double page parsing mode. 0: Split 1: Rotate 2: Both
|
||||
[Default=0]
|
||||
-g GAMMA, --gamma=GAMMA
|
||||
Apply gamma correction to linearize the image
|
||||
[Default=Auto]
|
||||
-c CROPPING, --cropping=CROPPING
|
||||
Set cropping mode. 0: Disabled 1: Margins 2: Margins +
|
||||
page numbers [Default=2]
|
||||
--cp=CROPPINGP, --croppingpower=CROPPINGP
|
||||
Set cropping power [Default=1.0]
|
||||
--blackborders Disable autodetection and force black borders
|
||||
--whiteborders Disable autodetection and force white borders
|
||||
--forcecolor Don't convert images to grayscale
|
||||
--forcepng Create PNG files instead JPEG
|
||||
--gamma=GAMMA Apply gamma correction to linearize the image [Default=Auto]
|
||||
--nocutpagenumbers Don't try to cut page numbering on images
|
||||
--noprocessing Don't apply image preprocessing
|
||||
--nosplitrotate Disable splitting and rotation
|
||||
--rotate Rotate landscape pages instead of splitting them
|
||||
--stretch Stretch images to device's resolution
|
||||
--upscale Resize images smaller than device's resolution
|
||||
|
||||
CUSTOM PROFILE:
|
||||
--customwidth=CUSTOMWIDTH
|
||||
@@ -113,198 +128,56 @@ Options:
|
||||
Replace screen height provided by device profile
|
||||
|
||||
OTHER:
|
||||
-v, --verbose Verbose output
|
||||
-h, --help Show this help message and exit
|
||||
```
|
||||
|
||||
### Standalone `comic2panel.py` usage:
|
||||
### Standalone `kcc-c2p.py` usage:
|
||||
|
||||
```
|
||||
Usage: comic2panel.py [options] comic_folder
|
||||
Usage: kcc-c2p [options] comic_folder
|
||||
|
||||
Options:
|
||||
MANDATORY:
|
||||
-y HEIGHT, --height=HEIGHT
|
||||
Height of the target device screen
|
||||
-i, --in-place Overwrite source directory
|
||||
-m, --merge Combine every directory into a single image before splitting
|
||||
|
||||
OTHER:
|
||||
-d, --debug Create debug file for every splitted image
|
||||
-d, --debug Create debug file for every split image
|
||||
-h, --help Show this help message and exit
|
||||
```
|
||||
|
||||
## CREDITS
|
||||
**KCC** is made by [Ciro Mattia Gonano](http://github.com/ciromattia) and [Paweł Jastrzębski](http://github.com/AcidWeb)
|
||||
**KCC** is made by [Ciro Mattia Gonano](http://github.com/ciromattia) and [Paweł Jastrzębski](http://github.com/AcidWeb).
|
||||
|
||||
This script born as a cross-platform alternative to `KindleComicParser` by **Dc5e** (published [here](http://www.mobileread.com/forums/showthread.php?t=192783))
|
||||
This script born as a cross-platform alternative to `KindleComicParser` by **Dc5e** (published [here](http://www.mobileread.com/forums/showthread.php?t=192783)).
|
||||
|
||||
The app relies and includes the following scripts/binaries:
|
||||
The app relies and includes the following scripts:
|
||||
|
||||
- `KindleUnpack` script by Charles **M. Hannum, P. Durrant, K. Hendricks, S. Siebert, fandrieu, DiapDealer, nickredding**. Released with GPLv3 License.
|
||||
- `rarfile.py` script © 2005-2011 **Marko Kreen** <markokr@gmail.com>. Released with ISC License.
|
||||
- `image.py` class from **Alex Yatskov**'s [Mangle](http://foosoft.net/mangle/) with subsequent [proDOOMman](https://github.com/proDOOMman/Mangle)'s and [Birua](https://github.com/Birua/Mangle)'s patches.
|
||||
- `DualMetaFix` script by **K. Hendricks**. Released with GPL-3 License.
|
||||
- `image.py` class from **Alex Yatskov**'s [Mangle](https://github.com/FooSoft/mangle/) with subsequent [proDOOMman](https://github.com/proDOOMman/Mangle)'s and [Birua](https://github.com/Birua/Mangle)'s patches.
|
||||
- Icon is by **Nikolay Verin** ([http://ncrow.deviantart.com/](http://ncrow.deviantart.com/)) and released under [CC BY-NC-SA 3.0](http://creativecommons.org/licenses/by-nc-sa/3.0/) License.
|
||||
|
||||
## SAMPLE FILES CREATED BY KCC
|
||||
* [Kindle Paperwhite](http://kcc.vulturis.eu/Samples/Ubunchu!-KPW.mobi)
|
||||
* [Kindle](http://kcc.vulturis.eu/Samples/Ubunchu!-K345.mobi)
|
||||
* [Kindle DX/DXG](http://kcc.vulturis.eu/Samples/Ubunchu!-KDX.mobi)
|
||||
* [Kindle Fire](http://kcc.vulturis.eu/Samples/Ubunchu!-KF.mobi)
|
||||
* [Kindle Fire HD](http://kcc.vulturis.eu/Samples/Ubunchu!-KFHD.mobi)
|
||||
* [Kindle Fire HD 8.9"](http://kcc.vulturis.eu/Samples/Ubunchu!-KFHD8.mobi)
|
||||
* [Kindle Fire HDX](http://kcc.vulturis.eu/Samples/Ubunchu!-KFHDX.mobi)
|
||||
* [Kindle Fire HDX 8.9"](http://kcc.vulturis.eu/Samples/Ubunchu!-KFHDX8.mobi)
|
||||
* [Kindle Oasis 2](http://kcc.iosphe.re/Samples/Ubunchu!-KO.mobi)
|
||||
* [Kindle Paperwhite 3 / 4 / Voyage / Oasis](http://kcc.iosphe.re/Samples/Ubunchu!-KV.mobi)
|
||||
* [Kindle Paperwhite 1 / 2](http://kcc.iosphe.re/Samples/Ubunchu!-KPW.mobi)
|
||||
* [Kindle](http://kcc.iosphe.re/Samples/Ubunchu!-K578.mobi)
|
||||
* [Kobo Aura](http://kcc.iosphe.re/Samples/Ubunchu-KoA.kepub.epub)
|
||||
* [Kobo Aura HD](http://kcc.iosphe.re/Samples/Ubunchu-KoAHD.kepub.epub)
|
||||
* [Kobo Aura H2O](http://kcc.iosphe.re/Samples/Ubunchu-KoAH2O.kepub.epub)
|
||||
* [Kobo Aura ONE](http://kcc.iosphe.re/Samples/Ubunchu-KoAO.kepub.epub)
|
||||
* [Kobo Forma](http://kcc.iosphe.re/Samples/Ubunchu-KoF.kepub.epub)
|
||||
|
||||
## CHANGELOG
|
||||
####1.0
|
||||
* Initial version
|
||||
## PRIVACY
|
||||
**KCC** is initiating internet connections in two cases:
|
||||
* During startup - Version check.
|
||||
* When error occurs - Automatic reporting on Windows and MacOS.
|
||||
|
||||
####1.1
|
||||
* Added support for CBZ/CBR files in comic2ebook.py
|
||||
|
||||
####1.1.1
|
||||
* Added support for CBZ/CBR files in Kindle Comic Converter
|
||||
|
||||
####1.2
|
||||
* Comic optimizations! Split pages not target-oriented (landscape with portrait target or portrait with landscape target), add palette and other image optimizations from Mangle. WARNING: PIL is required for all image mangling!
|
||||
|
||||
####1.3
|
||||
* Fixed an issue in OPF generation for device resolution
|
||||
* Reworked options system (call with -h option to get the inline help)
|
||||
|
||||
####1.4
|
||||
* Added some options for controlling image optimization
|
||||
* Further optimization (ImageOps, page numbering cut, autocontrast)
|
||||
|
||||
####1.4.1
|
||||
* Fixed a serious bug on resizing when img ratio was bigger than device one
|
||||
|
||||
####1.5
|
||||
* Added subfolder support for multiple chapters.
|
||||
|
||||
####2.0
|
||||
* GUI! AppleScript is gone and Tk is used to provide cross-platform GUI support.
|
||||
|
||||
####2.1
|
||||
* Added basic error reporting
|
||||
|
||||
####2.2:
|
||||
* Added (valid!) ePub 2.0 output
|
||||
* Rename .zip files to .cbz to avoid overwriting
|
||||
|
||||
####2.3
|
||||
* Fixed win32 ePub generation, folder handling, filenames with spaces and subfolders
|
||||
|
||||
####2.4
|
||||
* Use temporary directory as workdir (fixes converting from external volumes and zipfiles renaming)
|
||||
* Fixed "add folders" from GUI.
|
||||
|
||||
####2.5
|
||||
* Added --black-borders option to set added borders black when page's ratio is not the device's one (#11).
|
||||
* Fixes epub containing zipped itself (#10)
|
||||
|
||||
####2.6
|
||||
* Added --rotate option to rotate landscape images instead of splitting them (#16, #24)
|
||||
* Added --output option to customize ePub output dir/file (#22)
|
||||
* Add rendition:layout and rendition:orientation ePub meta tags (supported by new kindlegen 2.8)
|
||||
* Fixed natural sorting for files (#18)
|
||||
|
||||
####2.7
|
||||
* Lots of GUI improvements (#27, #13)
|
||||
* Added gamma support within --gamma option (defaults to profile-specified gamma) (#26, #27)
|
||||
* Added --nodithering option to prevent dithering optimizations (#27)
|
||||
* Epub margins support (#30)
|
||||
* Fixed no file added if file has no spaces on Windows (#25)
|
||||
* Gracefully exit if unrar missing (#15)
|
||||
* Do not call kindlegen if source epub is bigger than 320MB (#17)
|
||||
* Get filetype from magic number (#14)
|
||||
* PDF conversion works again
|
||||
|
||||
####2.8
|
||||
* Updated rarfile library
|
||||
* Panel View support + HQ support (#36) - new option: --nopanelviewhq
|
||||
* Split profiles for K4NT and K4T
|
||||
* Rewrite of Landscape Mode support (huge readability improvement for KPW)
|
||||
* Upscale use now BILINEAR method
|
||||
* Added generic CSS file
|
||||
* Optimized archive extraction for zip/rar files (#40)
|
||||
|
||||
####2.9
|
||||
* Added support for generating a plain CBZ (skipping all the EPUB/Mobi generation) (#45)
|
||||
* Prevent output file overwriting the source one: if a duplicate name is detected, append _kcc to the name
|
||||
* Rarfile library updated to 2.6
|
||||
* Added GIF, TIFF and BMP to supported formats (#42)
|
||||
* Filenames slugifications (#28, #31, #9, #8)
|
||||
|
||||
####2.10:
|
||||
* Multiprocessing support
|
||||
* Kindle Fire support (color ePub/Mobi)
|
||||
* Panel View support for horizontal content
|
||||
* Fixed panel order for horizontal pages when --rotate is enabled
|
||||
* Disabled cropping and page number cutting for blank pages
|
||||
* Fixed some slugify issues with specific file naming conventions (#50, #51)
|
||||
|
||||
####3.0:
|
||||
* New QT GUI
|
||||
* Merge with AWKCC
|
||||
* Added ultra quality mode
|
||||
* Added support for custom width/height
|
||||
* Added option to disable color conversion
|
||||
|
||||
####3.1:
|
||||
* Added profile: Kindle for Android
|
||||
* Add file/directory dialogs now support multiselect
|
||||
* Many small fixes and tweaks
|
||||
|
||||
####3.2:
|
||||
* Too big EPUB files are now splitted before conversion to MOBI
|
||||
* Added experimental parser of manga webtoons
|
||||
* Improved error handling
|
||||
|
||||
####3.2.1:
|
||||
* Hotfixed crash occurring on OS with Russian locale
|
||||
|
||||
####3.3:
|
||||
* Margins are now automatically omitted in Panel View mode
|
||||
* Margin color fill is now autodetected
|
||||
* Created MOBI files are not longer marked as _Personal_ on newer Kindle models
|
||||
* Layout of panels in Panel View mode is now automatically adjusted to content
|
||||
* Fixed Kindle 2/DX/DXG profiles - no more blank pages
|
||||
* All Kindle Fire profiles now support hiqh quality Panel View
|
||||
* Added support of 7z/CB7 files
|
||||
* Added Kindle Fire HDX profile
|
||||
* Support for Virtual Panel View was removed
|
||||
* Profiles for Kindle Keyboard, Touch and Non-Touch are now merged
|
||||
* Windows release is now bundled with UnRAR and 7za
|
||||
* Small GUI tweaks
|
||||
|
||||
####3.4:
|
||||
* Improved PNG output
|
||||
* Increased quality of upscaling
|
||||
* Added support of file association - KCC can now open CBZ, CBR, CB7, ZIP, RAR, 7Z and PDF files directly
|
||||
* Paths that contain UTF-8 characters are now supported
|
||||
* Migrated to new version of Pillow library
|
||||
* Merged DX and DXG profiles
|
||||
* Many other minor bug fixes and GUI tweaks
|
||||
|
||||
####3.5:
|
||||
* Added simple content server - Converted files can be now delivered wireless
|
||||
* Added proper Windows installer
|
||||
* Improved multiprocessing speed
|
||||
* GUI tweaks and minor bug fixes
|
||||
|
||||
####3.6:
|
||||
* Increased quality of Panel View zoom
|
||||
* Creation of multipart MOBI output is now faster on machines with 4GB+ RAM
|
||||
* Automatic gamma correction now distinguishes color and grayscale images
|
||||
* Added ComicRack metadata parser
|
||||
* Implemented new method to detect border color in non-webtoon comics
|
||||
* Upscaling is now enabled by default for Kindle Fire HD/HDX
|
||||
* Windows nad Linux releases now have tray icon
|
||||
* Fixed Kindle Fire HDX 7" output
|
||||
* Increased target resolution for Kindle DX/DXG CBZ output
|
||||
## KNOWN ISSUES
|
||||
Please check [wiki page](https://github.com/ciromattia/kcc/wiki/Known-issues).
|
||||
|
||||
## COPYRIGHT
|
||||
|
||||
Copyright (c) 2012-2013 Ciro Mattia Gonano and Paweł Jastrzębski.
|
||||
Copyright (c) 2012-2019 Ciro Mattia Gonano and Paweł Jastrzębski.
|
||||
**KCC** is released under ISC LICENSE; see LICENSE.txt for further details.
|
||||
|
||||
25
appveyor.yml
Normal file
25
appveyor.yml
Normal file
@@ -0,0 +1,25 @@
|
||||
environment:
|
||||
PYTHON: "C:\\Python37-x64"
|
||||
|
||||
install:
|
||||
- set PATH="%PYTHON%\\Scripts";"C:\\Program Files (x86)\\Inno Setup 5";%PATH%
|
||||
- "%PYTHON%\\python.exe -m pip install --upgrade pip setuptools wheel"
|
||||
- "%PYTHON%\\python.exe -m pip install -r requirements.txt"
|
||||
- "%PYTHON%\\python.exe -m pip install certifi https://github.com/pyinstaller/pyinstaller/archive/develop.zip"
|
||||
- nuget install secure-file -ExcludeVersion
|
||||
- secure-file\tools\secure-file -decrypt other\windows\sentry.py.enc -out kindlecomicconverter\sentry.py -secret %ENCRYPTION%
|
||||
|
||||
build_script:
|
||||
- "%PYTHON%\\python.exe setup.py build_binary"
|
||||
|
||||
after_build:
|
||||
- ps: Get-ChildItem .\dist\KCC* | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
|
||||
|
||||
deploy:
|
||||
provider: S3
|
||||
access_key_id:
|
||||
secure: pWfyU8wtAHt354mBILwM41TemOjb+My9n3CRMnrpLzI=
|
||||
secret_access_key:
|
||||
secure: G0Xpxe355LMqV3s8v+TsdJYdmhFoKKA+mxK37Tlu8yNwKXKJgcnY7pcFKSdX5xS5
|
||||
bucket: kcc-deploy
|
||||
region: eu-central-1
|
||||
29
gui/KCC.qrc
Normal file
29
gui/KCC.qrc
Normal file
@@ -0,0 +1,29 @@
|
||||
<RCC>
|
||||
<qresource prefix="Icon">
|
||||
<file>../icons/comic2ebook.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="Devices">
|
||||
<file>../icons/Kobo.png</file>
|
||||
<file>../icons/Other.png</file>
|
||||
<file>../icons/Kindle.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="Formats">
|
||||
<file>../icons/CBZ.png</file>
|
||||
<file>../icons/EPUB.png</file>
|
||||
<file>../icons/MOBI.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="Status">
|
||||
<file>../icons/error.png</file>
|
||||
<file>../icons/info.png</file>
|
||||
<file>../icons/warning.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="Other">
|
||||
<file>../icons/wiki.png</file>
|
||||
<file>../icons/editor.png</file>
|
||||
<file>../icons/list_background.png</file>
|
||||
<file>../icons/clear.png</file>
|
||||
<file>../icons/convert.png</file>
|
||||
<file>../icons/document_new.png</file>
|
||||
<file>../icons/folder_new.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
532
gui/KCC.ui
Normal file
532
gui/KCC.ui
Normal file
@@ -0,0 +1,532 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>mainWindow</class>
|
||||
<widget class="QMainWindow" name="mainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>450</width>
|
||||
<height>400</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Kindle Comic Converter</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="KCC.qrc">
|
||||
<normaloff>:/Icon/icons/comic2ebook.png</normaloff>:/Icon/icons/comic2ebook.png</iconset>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignJustify|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QListWidget" name="jobList">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">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);}</string>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::NoSelection</enum>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2">
|
||||
<widget class="QWidget" name="customWidget" native="true">
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="hLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p style='white-space:pre'>Resolution of the target device.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Custom height:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="widthBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p style='white-space:pre'>Resolution of the target device.</p></body></html></string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>2160</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="wLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p style='white-space:pre'>Resolution of the target device.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Custom width:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QSpinBox" name="heightBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p style='white-space:pre'>Resolution of the target device.</p></body></html></string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>3840</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QWidget" name="optionWidget" native="true">
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="mangaBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p style='white-space:pre'>Enable right-to-left reading.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Manga mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="rotateBox">
|
||||
<property name="toolTip">
|
||||
<string><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></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Spread splitter</string>
|
||||
</property>
|
||||
<property name="tristate">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QCheckBox" name="qualityBox">
|
||||
<property name="toolTip">
|
||||
<string><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></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Panel View 4/2/HQ</string>
|
||||
</property>
|
||||
<property name="tristate">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="webtoonBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p style='white-space:pre'>Enable special parsing mode for Korean Webtoons.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Webtoon mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="upscaleBox">
|
||||
<property name="toolTip">
|
||||
<string><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></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Stretch/Upscale</string>
|
||||
</property>
|
||||
<property name="tristate">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QCheckBox" name="gammaBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p style='white-space:pre'>Disable automatic gamma correction.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Custom gamma</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="borderBox">
|
||||
<property name="toolTip">
|
||||
<string><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></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>W/B margins</string>
|
||||
</property>
|
||||
<property name="tristate">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="outputSplit">
|
||||
<property name="toolTip">
|
||||
<string><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></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Output split</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QCheckBox" name="colorBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p style='white-space:pre'>Disable conversion to grayscale.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Color mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QWidget" name="gammaWidget" native="true">
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="gammaLabel">
|
||||
<property name="text">
|
||||
<string>Gamma: Auto</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="gammaSlider">
|
||||
<property name="maximum">
|
||||
<number>250</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QWidget" name="toolWidget" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="editorButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Editor</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p style='white-space:pre'>Shift+Click to edit directory.</p></body></html></string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="KCC.qrc">
|
||||
<normaloff>:/Other/icons/editor.png</normaloff>:/Other/icons/editor.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="wikiButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Wiki</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="KCC.qrc">
|
||||
<normaloff>:/Other/icons/wiki.png</normaloff>:/Other/icons/wiki.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QWidget" name="buttonWidget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QPushButton" name="directoryButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><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></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add directory</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="KCC.qrc">
|
||||
<normaloff>:/Other/icons/folder_new.png</normaloff>:/Other/icons/folder_new.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QPushButton" name="fileButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p style='white-space:pre'>Add CBR, CBZ, CB7 or PDF file to queue.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add file</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="KCC.qrc">
|
||||
<normaloff>:/Other/icons/document_new.png</normaloff>:/Other/icons/document_new.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QComboBox" name="deviceBox">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>28</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p style='white-space:pre'>Target device.</p></body></html></string>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QComboBox" name="formatBox">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>28</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p style='white-space:pre'>Output format.</p></body></html></string>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="convertButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p style='white-space:pre'>Shift+Click to select the output directory.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Convert</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="KCC.qrc">
|
||||
<normaloff>:/Other/icons/convert.png</normaloff>:/Other/icons/convert.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="clearButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Clear list</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="KCC.qrc">
|
||||
<normaloff>:/Other/icons/clear.png</normaloff>:/Other/icons/clear.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<zorder>directoryButton</zorder>
|
||||
<zorder>clearButton</zorder>
|
||||
<zorder>fileButton</zorder>
|
||||
<zorder>deviceBox</zorder>
|
||||
<zorder>convertButton</zorder>
|
||||
<zorder>formatBox</zorder>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusBar">
|
||||
<property name="sizeGripEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>convertButton</tabstop>
|
||||
<tabstop>clearButton</tabstop>
|
||||
<tabstop>directoryButton</tabstop>
|
||||
<tabstop>fileButton</tabstop>
|
||||
<tabstop>deviceBox</tabstop>
|
||||
<tabstop>formatBox</tabstop>
|
||||
<tabstop>mangaBox</tabstop>
|
||||
<tabstop>rotateBox</tabstop>
|
||||
<tabstop>qualityBox</tabstop>
|
||||
<tabstop>webtoonBox</tabstop>
|
||||
<tabstop>upscaleBox</tabstop>
|
||||
<tabstop>gammaBox</tabstop>
|
||||
<tabstop>borderBox</tabstop>
|
||||
<tabstop>outputSplit</tabstop>
|
||||
<tabstop>colorBox</tabstop>
|
||||
<tabstop>editorButton</tabstop>
|
||||
<tabstop>wikiButton</tabstop>
|
||||
<tabstop>jobList</tabstop>
|
||||
<tabstop>gammaSlider</tabstop>
|
||||
<tabstop>widthBox</tabstop>
|
||||
<tabstop>heightBox</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="KCC.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
189
gui/MetaEditor.ui
Normal file
189
gui/MetaEditor.ui
Normal file
@@ -0,0 +1,189 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>editorDialog</class>
|
||||
<widget class="QDialog" name="editorDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>260</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>260</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Metadata editor</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="KCC.qrc">
|
||||
<normaloff>:/Icon/icons/comic2ebook.png</normaloff>:/Icon/icons/comic2ebook.png</iconset>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QWidget" name="editorWidget" native="true">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_1">
|
||||
<property name="text">
|
||||
<string>Series:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="seriesLine"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Volume:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="volumeLine"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Number:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="numberLine"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Writer:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="writerLine"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Penciller:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="pencillerLine"/>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Inker:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLineEdit" name="inkerLine"/>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Colorist:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLineEdit" name="coloristLine"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="optionWidget" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="statusLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="okButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="KCC.qrc">
|
||||
<normaloff>:/Other/icons/convert.png</normaloff>:/Other/icons/convert.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="cancelButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="KCC.qrc">
|
||||
<normaloff>:/Other/icons/clear.png</normaloff>:/Other/icons/clear.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="KCC.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
BIN
icons/Kobo.png
Normal file
BIN
icons/Kobo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
BIN
icons/WizardOSX.png
Normal file
BIN
icons/WizardOSX.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 328 KiB |
BIN
icons/editor.png
Normal file
BIN
icons/editor.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 23 KiB |
Binary file not shown.
BIN
icons/wiki.png
Normal file
BIN
icons/wiki.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
31
kcc-c2e.py
Executable file
31
kcc-c2e.py
Executable file
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||
# Copyright (c) 2013-2019 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for
|
||||
# any purpose with or without fee is hereby granted, provided that the
|
||||
# above copyright notice and this permission notice appear in all
|
||||
# copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
# AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
|
||||
# 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 sys
|
||||
if sys.version_info[0] != 3:
|
||||
print('ERROR: This is Python 3 script!')
|
||||
exit(1)
|
||||
|
||||
from multiprocessing import freeze_support
|
||||
from kindlecomicconverter.startup import startC2E
|
||||
|
||||
if __name__ == "__main__":
|
||||
freeze_support()
|
||||
startC2E()
|
||||
31
kcc-c2p.py
Executable file
31
kcc-c2p.py
Executable file
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||
# Copyright (c) 2013-2019 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for
|
||||
# any purpose with or without fee is hereby granted, provided that the
|
||||
# above copyright notice and this permission notice appear in all
|
||||
# copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
# AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
|
||||
# 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 sys
|
||||
if sys.version_info[0] != 3:
|
||||
print('ERROR: This is Python 3 script!')
|
||||
exit(1)
|
||||
|
||||
from multiprocessing import freeze_support
|
||||
from kindlecomicconverter.startup import startC2P
|
||||
|
||||
if __name__ == "__main__":
|
||||
freeze_support()
|
||||
startC2P()
|
||||
119
kcc.iss
119
kcc.iss
@@ -1,7 +1,7 @@
|
||||
#define MyAppName "Kindle Comic Converter"
|
||||
#define MyAppVersion "3.6"
|
||||
#define MyAppVersion "5.5.0"
|
||||
#define MyAppPublisher "Ciro Mattia Gonano, Paweł Jastrzębski"
|
||||
#define MyAppURL "http://kcc.vulturis.eu/"
|
||||
#define MyAppURL "http://kcc.iosphe.re/"
|
||||
#define MyAppExeName "KCC.exe"
|
||||
|
||||
[Setup]
|
||||
@@ -12,7 +12,8 @@ AppPublisher={#MyAppPublisher}
|
||||
AppPublisherURL={#MyAppURL}
|
||||
AppSupportURL={#MyAppURL}
|
||||
AppUpdatesURL={#MyAppURL}
|
||||
AppCopyright=Copyright (C) 2012-2013 Ciro Mattia Gonano and Paweł Jastrzębski
|
||||
AppCopyright=Copyright (C) 2012-2019 Ciro Mattia Gonano and Paweł Jastrzębski
|
||||
ArchitecturesAllowed=x64
|
||||
DefaultDirName={pf}\{#MyAppName}
|
||||
DefaultGroupName={#MyAppName}
|
||||
AllowNoIcons=yes
|
||||
@@ -20,7 +21,6 @@ LicenseFile=LICENSE.txt
|
||||
OutputBaseFilename=KindleComicConverter_win_{#MyAppVersion}
|
||||
SetupIconFile=icons\comic2ebook.ico
|
||||
SolidCompression=yes
|
||||
ArchitecturesInstallIn64BitMode=x64
|
||||
ShowLanguageDialog=no
|
||||
LanguageDetectionMethod=none
|
||||
WizardImageFile=icons\Wizard.bmp
|
||||
@@ -28,8 +28,11 @@ WizardSmallImageFile=icons\Wizard-Small.bmp
|
||||
UninstallDisplayName={#MyAppName}
|
||||
UninstallDisplayIcon={app}\{#MyAppExeName}
|
||||
ChangesAssociations=True
|
||||
InfoAfterFile=other\InstallWarning.rtf
|
||||
InfoAfterFile=other\windows\InstallWarning.rtf
|
||||
SignTool=SignTool /d $q{#MyAppName}$q /du $q{#MyAppURL}$q $f
|
||||
MinVersion=0,6.0
|
||||
OutputDir=dist
|
||||
ArchitecturesInstallIn64BitMode=x64
|
||||
|
||||
[Languages]
|
||||
Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||
@@ -41,61 +44,11 @@ Name: "CBRassociation"; Description: "CBR"; GroupDescription: "File associations
|
||||
Name: "CB7association"; Description: "CB7"; GroupDescription: "File associations:"
|
||||
|
||||
[Files]
|
||||
; x64 files
|
||||
Source: "build\exe.win-amd64-2.7\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
|
||||
Source: "build\exe.win-amd64-2.7\_ctypes.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
|
||||
Source: "build\exe.win-amd64-2.7\_hashlib.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
|
||||
Source: "build\exe.win-amd64-2.7\_multiprocessing.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
|
||||
Source: "build\exe.win-amd64-2.7\_socket.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
|
||||
Source: "build\exe.win-amd64-2.7\_ssl.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
|
||||
Source: "build\exe.win-amd64-2.7\bz2.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
|
||||
Source: "build\exe.win-amd64-2.7\LIBEAY32.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
|
||||
Source: "build\exe.win-amd64-2.7\library.zip"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
|
||||
Source: "build\exe.win-amd64-2.7\PIL._imaging.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
|
||||
Source: "build\exe.win-amd64-2.7\PIL._imagingft.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
|
||||
Source: "build\exe.win-amd64-2.7\pyexpat.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
|
||||
Source: "build\exe.win-amd64-2.7\PyQt4.QtCore.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
|
||||
Source: "build\exe.win-amd64-2.7\PyQt4.QtGui.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
|
||||
Source: "build\exe.win-amd64-2.7\PyQt4.QtNetwork.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
|
||||
Source: "build\exe.win-amd64-2.7\python27.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
|
||||
Source: "build\exe.win-amd64-2.7\QtCore4.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
|
||||
Source: "build\exe.win-amd64-2.7\QtGui4.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
|
||||
Source: "build\exe.win-amd64-2.7\QtNetwork4.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
|
||||
Source: "build\exe.win-amd64-2.7\select.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
|
||||
Source: "build\exe.win-amd64-2.7\sip.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
|
||||
Source: "build\exe.win-amd64-2.7\SSLEAY32.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
|
||||
Source: "build\exe.win-amd64-2.7\unicodedata.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
|
||||
Source: "build\exe.win-amd64-2.7\_psutil_mswindows.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
|
||||
; x86 files
|
||||
Source: "build\exe.win32-2.7\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion solidbreak; Check: not Is64BitInstallMode
|
||||
Source: "build\exe.win32-2.7\_ctypes.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
|
||||
Source: "build\exe.win32-2.7\_hashlib.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
|
||||
Source: "build\exe.win32-2.7\_multiprocessing.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
|
||||
Source: "build\exe.win32-2.7\_socket.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
|
||||
Source: "build\exe.win32-2.7\_ssl.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
|
||||
Source: "build\exe.win32-2.7\bz2.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
|
||||
Source: "build\exe.win32-2.7\LIBEAY32.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
|
||||
Source: "build\exe.win32-2.7\library.zip"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
|
||||
Source: "build\exe.win32-2.7\PIL._imaging.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
|
||||
Source: "build\exe.win32-2.7\PIL._imagingft.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
|
||||
Source: "build\exe.win32-2.7\pyexpat.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
|
||||
Source: "build\exe.win32-2.7\PyQt4.QtCore.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
|
||||
Source: "build\exe.win32-2.7\PyQt4.QtGui.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
|
||||
Source: "build\exe.win32-2.7\PyQt4.QtNetwork.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
|
||||
Source: "build\exe.win32-2.7\python27.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
|
||||
Source: "build\exe.win32-2.7\QtCore4.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
|
||||
Source: "build\exe.win32-2.7\QtGui4.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
|
||||
Source: "build\exe.win32-2.7\QtNetwork4.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
|
||||
Source: "build\exe.win32-2.7\select.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
|
||||
Source: "build\exe.win32-2.7\sip.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
|
||||
Source: "build\exe.win32-2.7\SSLEAY32.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
|
||||
Source: "build\exe.win32-2.7\unicodedata.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
|
||||
Source: "build\exe.win32-2.7\_psutil_mswindows.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
|
||||
; Common files
|
||||
Source: "dist\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "LICENSE.txt"; DestDir: "{app}"; Flags: ignoreversion solidbreak
|
||||
Source: "other\Additional-LICENSE.txt"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "other\UnRAR.exe"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "other\7za.exe"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "other\windows\Additional-LICENSE.txt"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "other\windows\7z.exe"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "other\windows\7z.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||
|
||||
[Icons]
|
||||
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
|
||||
@@ -103,7 +56,7 @@ Name: "{group}\Readme"; Filename: "https://github.com/ciromattia/kcc#kcc"
|
||||
Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
|
||||
|
||||
[Run]
|
||||
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
|
||||
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall
|
||||
|
||||
[Messages]
|
||||
WelcomeLabel1=Welcome to the KCC Setup Wizard
|
||||
@@ -122,3 +75,49 @@ Root: HKCR; SubKey: ".cb7"; ValueType: string; ValueData: "KCCCB7"; Flags: unins
|
||||
Root: HKCR; SubKey: "KCCCB7"; ValueType: string; ValueData: "KCC 7z Archive"; Flags: uninsdeletekey; Tasks: CB7association
|
||||
Root: HKCR; SubKey: "KCCCB7\Shell\Open\Command"; ValueType: string; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey; Tasks: CB7association
|
||||
Root: HKCR; Subkey: "KCCCB7\DefaultIcon"; ValueType: string; ValueData: "{app}\{#MyAppExeName},0"; Flags: uninsdeletevalue; Tasks: CB7association
|
||||
|
||||
[Code]
|
||||
function GetUninstallString(): String;
|
||||
var
|
||||
sUnInstPath: String;
|
||||
sUnInstallString: String;
|
||||
begin
|
||||
sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#emit SetupSetting("AppId")}_is1');
|
||||
sUnInstallString := '';
|
||||
if not RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString) then
|
||||
RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString);
|
||||
Result := sUnInstallString;
|
||||
end;
|
||||
|
||||
function IsUpgrade(): Boolean;
|
||||
begin
|
||||
Result := (GetUninstallString() <> '');
|
||||
end;
|
||||
|
||||
function UnInstallOldVersion(): Integer;
|
||||
var
|
||||
sUnInstallString: String;
|
||||
iResultCode: Integer;
|
||||
begin
|
||||
Result := 0;
|
||||
sUnInstallString := GetUninstallString();
|
||||
if sUnInstallString <> '' then begin
|
||||
sUnInstallString := RemoveQuotes(sUnInstallString);
|
||||
if Exec(sUnInstallString, '/SILENT /NORESTART /SUPPRESSMSGBOXES','', SW_HIDE, ewWaitUntilTerminated, iResultCode) then
|
||||
Result := 3
|
||||
else
|
||||
Result := 2;
|
||||
end else
|
||||
Result := 1;
|
||||
end;
|
||||
|
||||
procedure CurStepChanged(CurStep: TSetupStep);
|
||||
begin
|
||||
if (CurStep=ssInstall) then
|
||||
begin
|
||||
if (IsUpgrade()) then
|
||||
begin
|
||||
UnInstallOldVersion();
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
10
kcc.json
Normal file
10
kcc.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"title": "Kindle Comic Converter",
|
||||
"icon": "icons/comic2ebook.icns",
|
||||
"background": "icons/WizardOSX.png",
|
||||
"icon-size": 160,
|
||||
"contents": [
|
||||
{ "x": 180, "y": 300, "type": "file", "path": "dist/Kindle Comic Converter.app" },
|
||||
{ "x": 520, "y": 300, "type": "link", "path": "/Applications" }
|
||||
]
|
||||
}
|
||||
109
kcc.py
Normal file → Executable file
109
kcc.py
Normal file → Executable file
@@ -1,8 +1,8 @@
|
||||
#!/usr/bin/env python2
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2012-2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||
# Copyright (c) 2013 Pawel Jastrzebski <pawelj@vulturis.eu>
|
||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||
# Copyright (c) 2013-2019 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for
|
||||
# any purpose with or without fee is hereby granted, provided that the
|
||||
@@ -18,97 +18,38 @@
|
||||
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
__version__ = '3.6'
|
||||
__license__ = 'ISC'
|
||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import sys
|
||||
import os
|
||||
try:
|
||||
#noinspection PyUnresolvedReferences
|
||||
from PyQt4 import QtCore, QtGui, QtNetwork
|
||||
except ImportError:
|
||||
print "ERROR: PyQT4 is not installed!"
|
||||
if sys.platform.startswith('linux'):
|
||||
import Tkinter
|
||||
import tkMessageBox
|
||||
importRoot = Tkinter.Tk()
|
||||
importRoot.withdraw()
|
||||
tkMessageBox.showerror("KCC - Error", "PyQT4 is not installed!")
|
||||
if sys.version_info[0] != 3:
|
||||
print('ERROR: This is Python 3 script!')
|
||||
exit(1)
|
||||
from kcc import KCC_gui
|
||||
from multiprocessing import freeze_support
|
||||
|
||||
# OS specific PATH variable workarounds
|
||||
# OS specific workarounds
|
||||
import os
|
||||
if sys.platform.startswith('darwin'):
|
||||
if 'RESOURCEPATH' in os.environ:
|
||||
os.environ['PATH'] = os.environ['RESOURCEPATH'] + ':' + os.environ['PATH']
|
||||
if getattr(sys, 'frozen', False):
|
||||
os.environ['PATH'] = os.path.dirname(os.path.abspath(sys.executable)) + \
|
||||
'/../Resources:/usr/local/bin:/usr/bin:/bin'
|
||||
os.system('defaults write com.kindlecomicconverter.KindleComicConverter ApplePersistenceIgnoreState YES')
|
||||
os.system('defaults write com.kindlecomicconverter.KindleComicConverter NSInitialToolTipDelay -int 1000')
|
||||
else:
|
||||
os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + '/other/:' + os.environ['PATH']
|
||||
os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + '/other/osx/:' + os.environ['PATH']
|
||||
elif sys.platform.startswith('win'):
|
||||
if getattr(sys, 'frozen', False):
|
||||
os.chdir(os.path.dirname(os.path.abspath(sys.executable)))
|
||||
else:
|
||||
os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + '/other/;' + os.environ['PATH']
|
||||
os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + '/other/windows/;' + os.environ['PATH']
|
||||
os.chdir(os.path.dirname(os.path.abspath(__file__)))
|
||||
# Load additional Sentry configuration
|
||||
if getattr(sys, 'frozen', False):
|
||||
try:
|
||||
import kindlecomicconverter.sentry
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
from multiprocessing import freeze_support
|
||||
from kindlecomicconverter.startup import start
|
||||
|
||||
# Implementing detection of already running KCC instance and forwarding argv to it
|
||||
class QApplicationMessaging(QtGui.QApplication):
|
||||
def __init__(self, argv):
|
||||
QtGui.QApplication.__init__(self, argv)
|
||||
self._memory = QtCore.QSharedMemory(self)
|
||||
self._memory.setKey('KCC')
|
||||
if self._memory.attach():
|
||||
self._running = True
|
||||
else:
|
||||
self._running = False
|
||||
if not self._memory.create(1):
|
||||
raise RuntimeError(self._memory.errorString().toLocal8Bit().data())
|
||||
self._key = 'KCC'
|
||||
self._timeout = 1000
|
||||
self._server = QtNetwork.QLocalServer(self)
|
||||
if not self.isRunning():
|
||||
self._server.newConnection.connect(self.handleMessage)
|
||||
self._server.listen(self._key)
|
||||
if __name__ == "__main__":
|
||||
freeze_support()
|
||||
start()
|
||||
|
||||
def isRunning(self):
|
||||
return self._running
|
||||
|
||||
def handleMessage(self):
|
||||
socket = self._server.nextPendingConnection()
|
||||
if socket.waitForReadyRead(self._timeout):
|
||||
self.emit(QtCore.SIGNAL('messageFromOtherInstance'), socket.readAll().data().decode('utf8'))
|
||||
|
||||
def sendMessage(self, message):
|
||||
if self.isRunning():
|
||||
socket = QtNetwork.QLocalSocket(self)
|
||||
socket.connectToServer(self._key, QtCore.QIODevice.WriteOnly)
|
||||
if not socket.waitForConnected(self._timeout):
|
||||
return False
|
||||
socket.write(message.encode('utf8'))
|
||||
if not socket.waitForBytesWritten(self._timeout):
|
||||
return False
|
||||
socket.disconnectFromServer()
|
||||
return True
|
||||
return False
|
||||
|
||||
freeze_support()
|
||||
KCCAplication = QApplicationMessaging(sys.argv)
|
||||
if KCCAplication.isRunning():
|
||||
if len(sys.argv) > 1:
|
||||
KCCAplication.sendMessage(sys.argv[1].decode(sys.getfilesystemencoding()))
|
||||
sys.exit(0)
|
||||
else:
|
||||
messageBox = QtGui.QMessageBox()
|
||||
icon = QtGui.QIcon()
|
||||
icon.addPixmap(QtGui.QPixmap(':/Icon/icons/comic2ebook.png'), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
messageBox.setWindowIcon(icon)
|
||||
QtGui.QMessageBox.critical(messageBox, 'KCC - Error', 'KCC is already running!', QtGui.QMessageBox.Ok)
|
||||
sys.exit(1)
|
||||
KCCWindow = QtGui.QMainWindow()
|
||||
KCCUI = KCC_gui.KCCGUI(KCCAplication, KCCWindow)
|
||||
if len(sys.argv) > 1:
|
||||
KCCUI.handleMessage(sys.argv[1].decode(sys.getfilesystemencoding()))
|
||||
sys.exit(KCCAplication.exec_())
|
||||
|
||||
1101
kcc/KCC_gui.py
1101
kcc/KCC_gui.py
File diff suppressed because it is too large
Load Diff
@@ -1,225 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Resources used by content server
|
||||
|
||||
|
||||
class WebContent:
|
||||
def __init__(self):
|
||||
self.favicon = 'data:image/x-icon;base64,AAABAAEAEBAAAAAAAABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAAAAAAA' \
|
||||
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACalpVpycW64O7q20wAAAAAAAAAAAA' \
|
||||
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVlNNSJiWj//i39b11dHDKAAAAAAAAAAAAAA' \
|
||||
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEpGP0eKh4L/19fU/9DLvo4AAAAAAAAAAAAAAAAAAAA' \
|
||||
'AAAAAAJCOdiqRkIprr6yhfrSxpom4tauRu7mvl8C+s52opJvFvLu3/6nq7v/P087i0c7AVtLPwi4AAAAAAAAAALm1hTK' \
|
||||
'NinTvv723/9rZ0P/g3NH/39rT/+Db1//e3Nr/497b/8Tb3/8s4/z/yObp/9zRy//R0MnnAAAAAAAAAAC4tImElJGF/9v' \
|
||||
'b0/+8udn/bpnl/2ax+v9Rru//OMTi/zXc9v8i5///AOD//1Tf9P/W5ez/2dXS8AAAAAAAAAAAubSOprayqf/p5tv/dI3' \
|
||||
'g/wNh2/8Rd+f/Dn7d/waO2/8AxOj/AKvW/wC+4P8Akdb/oMzt/+fg2e0AAAAAAAAAAKymhr3Bvrf/6Ojj/z5F0P8DH8H' \
|
||||
'/GG/a/yKQ//8RleT/FInf/xuD6f8QfMf/EpL//4Kx5P/m4NftAAAAAAAAAACinIPK0c/F/9jX6f8ZIuz/BinM/xFQ2/8' \
|
||||
'il///IIz4/yKP//8fivf/IIr7/xN+8P9ff7D/49/Y7QAAAAAAAAAAnJaB1OLh1P+6uuf/AQLt/wEH+v8bffv/G3jf/w5' \
|
||||
'Gxv8eifP/CSzL/xp35P8HReH/TVKz/+Ti1+0AAAAAAAAAAJeRgdzw7+D/nJ3f/wAA+f8FGuT/Ci/F/wAD3P8FGtj/CS7' \
|
||||
'd/wAA8P8NQMX/AA7//01Lxv/o6NftAAAAAAAAAACTjYHj+/rm/3t89/8AAO7/AAC8/wAA9P8AAP//AADz/wAA/f8AAP/' \
|
||||
'/AAPi/wAA9v9aWrz/7e3e7QAAAAAAAAAAk42D5/v68f+op9b/NTVx/w8PkP8AAPz/AADU/wAA8v8AAP//AADn/wAA//8' \
|
||||
'AAJb/cnKP//X07e0AAAAAAAAAAJmUi+/5+Pj//f72//f37v/b2/T/t7bw/5GRv/9ycvT/Xl7v/1NTu/9QUPX/VlaJ/8D' \
|
||||
'Avv/z8vDuAAAAAAAAAAB7dGrWqKSe/83Kx//l5OL/9/fx////+P/////////7////+v////v////3/////f/9/fz/8/L' \
|
||||
'x9gAAAAAAAAAAbGVaGmhhVWBsZVqTd3FmtYmDesublo7YrKih4rq3sebFwr3nzMnE5M7MyN7PzMjUxsO/xNzb2IEAAAA' \
|
||||
'A/98AAP/PAAD/xwAA+AcAAMABAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAA4AEAAA%3D%3D'
|
||||
self.logo = 'data:image/jpeg;base64,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' \
|
||||
'ruooAoSOUAUAUAUAUAUB/9k%3D'
|
||||
322
kcc/KCC_ui.py
322
kcc/KCC_ui.py
@@ -1,322 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'KCC.ui'
|
||||
#
|
||||
# Created: Wed Dec 04 18:28:13 2013
|
||||
# by: PyQt4 UI code generator 4.10.3
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
try:
|
||||
_fromUtf8 = QtCore.QString.fromUtf8
|
||||
except AttributeError:
|
||||
def _fromUtf8(s):
|
||||
return s
|
||||
|
||||
try:
|
||||
_encoding = QtGui.QApplication.UnicodeUTF8
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
||||
except AttributeError:
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig)
|
||||
|
||||
class Ui_KCC(object):
|
||||
def setupUi(self, KCC):
|
||||
KCC.setObjectName(_fromUtf8("KCC"))
|
||||
KCC.resize(420, 397)
|
||||
KCC.setMinimumSize(QtCore.QSize(420, 397))
|
||||
KCC.setMaximumSize(QtCore.QSize(420, 397))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(9)
|
||||
KCC.setFont(font)
|
||||
icon = QtGui.QIcon()
|
||||
icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/Icon/icons/comic2ebook.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
KCC.setWindowIcon(icon)
|
||||
KCC.setLocale(QtCore.QLocale(QtCore.QLocale.C, QtCore.QLocale.AnyCountry))
|
||||
self.Form = QtGui.QWidget(KCC)
|
||||
self.Form.setObjectName(_fromUtf8("Form"))
|
||||
self.OptionsAdvanced = QtGui.QFrame(self.Form)
|
||||
self.OptionsAdvanced.setEnabled(True)
|
||||
self.OptionsAdvanced.setGeometry(QtCore.QRect(10, 254, 421, 61))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(9)
|
||||
self.OptionsAdvanced.setFont(font)
|
||||
self.OptionsAdvanced.setObjectName(_fromUtf8("OptionsAdvanced"))
|
||||
self.gridLayout = QtGui.QGridLayout(self.OptionsAdvanced)
|
||||
self.gridLayout.setContentsMargins(9, -1, -1, -1)
|
||||
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
|
||||
self.ProcessingBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
self.ProcessingBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.ProcessingBox.setObjectName(_fromUtf8("ProcessingBox"))
|
||||
self.gridLayout.addWidget(self.ProcessingBox, 1, 0, 1, 1)
|
||||
self.UpscaleBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
self.UpscaleBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.UpscaleBox.setTristate(True)
|
||||
self.UpscaleBox.setObjectName(_fromUtf8("UpscaleBox"))
|
||||
self.gridLayout.addWidget(self.UpscaleBox, 1, 1, 1, 1)
|
||||
self.WebtoonBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
self.WebtoonBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.WebtoonBox.setObjectName(_fromUtf8("WebtoonBox"))
|
||||
self.gridLayout.addWidget(self.WebtoonBox, 3, 1, 1, 1)
|
||||
self.NoDitheringBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
self.NoDitheringBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.NoDitheringBox.setObjectName(_fromUtf8("NoDitheringBox"))
|
||||
self.gridLayout.addWidget(self.NoDitheringBox, 3, 2, 1, 1)
|
||||
self.BorderBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
self.BorderBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.BorderBox.setTristate(True)
|
||||
self.BorderBox.setObjectName(_fromUtf8("BorderBox"))
|
||||
self.gridLayout.addWidget(self.BorderBox, 3, 0, 1, 1)
|
||||
self.NoRotateBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
self.NoRotateBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.NoRotateBox.setObjectName(_fromUtf8("NoRotateBox"))
|
||||
self.gridLayout.addWidget(self.NoRotateBox, 1, 2, 1, 1)
|
||||
self.DeviceBox = QtGui.QComboBox(self.Form)
|
||||
self.DeviceBox.setGeometry(QtCore.QRect(10, 200, 141, 31))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(8)
|
||||
self.DeviceBox.setFont(font)
|
||||
self.DeviceBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.DeviceBox.setObjectName(_fromUtf8("DeviceBox"))
|
||||
self.FormatBox = QtGui.QComboBox(self.Form)
|
||||
self.FormatBox.setGeometry(QtCore.QRect(260, 200, 151, 31))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(8)
|
||||
self.FormatBox.setFont(font)
|
||||
self.FormatBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.FormatBox.setObjectName(_fromUtf8("FormatBox"))
|
||||
self.ConvertButton = QtGui.QPushButton(self.Form)
|
||||
self.ConvertButton.setGeometry(QtCore.QRect(160, 200, 91, 32))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(9)
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
self.ConvertButton.setFont(font)
|
||||
self.ConvertButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
icon1 = QtGui.QIcon()
|
||||
icon1.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/convert.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
self.ConvertButton.setIcon(icon1)
|
||||
self.ConvertButton.setObjectName(_fromUtf8("ConvertButton"))
|
||||
self.DirectoryButton = QtGui.QPushButton(self.Form)
|
||||
self.DirectoryButton.setGeometry(QtCore.QRect(10, 160, 141, 32))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(8)
|
||||
self.DirectoryButton.setFont(font)
|
||||
self.DirectoryButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
icon2 = QtGui.QIcon()
|
||||
icon2.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/folder_new.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
self.DirectoryButton.setIcon(icon2)
|
||||
self.DirectoryButton.setObjectName(_fromUtf8("DirectoryButton"))
|
||||
self.FileButton = QtGui.QPushButton(self.Form)
|
||||
self.FileButton.setGeometry(QtCore.QRect(260, 160, 151, 32))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(8)
|
||||
self.FileButton.setFont(font)
|
||||
self.FileButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
icon3 = QtGui.QIcon()
|
||||
icon3.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/document_new.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
self.FileButton.setIcon(icon3)
|
||||
self.FileButton.setObjectName(_fromUtf8("FileButton"))
|
||||
self.ClearButton = QtGui.QPushButton(self.Form)
|
||||
self.ClearButton.setGeometry(QtCore.QRect(160, 160, 91, 32))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(8)
|
||||
self.ClearButton.setFont(font)
|
||||
self.ClearButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
icon4 = QtGui.QIcon()
|
||||
icon4.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/clear.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
self.ClearButton.setIcon(icon4)
|
||||
self.ClearButton.setObjectName(_fromUtf8("ClearButton"))
|
||||
self.OptionsBasic = QtGui.QFrame(self.Form)
|
||||
self.OptionsBasic.setGeometry(QtCore.QRect(10, 230, 421, 41))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(9)
|
||||
self.OptionsBasic.setFont(font)
|
||||
self.OptionsBasic.setObjectName(_fromUtf8("OptionsBasic"))
|
||||
self.MangaBox = QtGui.QCheckBox(self.OptionsBasic)
|
||||
self.MangaBox.setGeometry(QtCore.QRect(9, 10, 130, 18))
|
||||
self.MangaBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.MangaBox.setObjectName(_fromUtf8("MangaBox"))
|
||||
self.QualityBox = QtGui.QCheckBox(self.OptionsBasic)
|
||||
self.QualityBox.setGeometry(QtCore.QRect(282, 10, 130, 18))
|
||||
self.QualityBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.QualityBox.setTristate(True)
|
||||
self.QualityBox.setObjectName(_fromUtf8("QualityBox"))
|
||||
self.RotateBox = QtGui.QCheckBox(self.OptionsBasic)
|
||||
self.RotateBox.setGeometry(QtCore.QRect(145, 10, 130, 18))
|
||||
self.RotateBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.RotateBox.setObjectName(_fromUtf8("RotateBox"))
|
||||
self.JobList = QtGui.QListWidget(self.Form)
|
||||
self.JobList.setGeometry(QtCore.QRect(10, 50, 401, 101))
|
||||
self.JobList.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.JobList.setStyleSheet(_fromUtf8("QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}"))
|
||||
self.JobList.setProperty("showDropIndicator", False)
|
||||
self.JobList.setSelectionMode(QtGui.QAbstractItemView.NoSelection)
|
||||
self.JobList.setVerticalScrollMode(QtGui.QAbstractItemView.ScrollPerPixel)
|
||||
self.JobList.setHorizontalScrollMode(QtGui.QAbstractItemView.ScrollPerPixel)
|
||||
self.JobList.setObjectName(_fromUtf8("JobList"))
|
||||
self.BasicModeButton = QtGui.QPushButton(self.Form)
|
||||
self.BasicModeButton.setGeometry(QtCore.QRect(10, 10, 195, 32))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(9)
|
||||
self.BasicModeButton.setFont(font)
|
||||
self.BasicModeButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.BasicModeButton.setObjectName(_fromUtf8("BasicModeButton"))
|
||||
self.AdvModeButton = QtGui.QPushButton(self.Form)
|
||||
self.AdvModeButton.setGeometry(QtCore.QRect(217, 10, 195, 32))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(9)
|
||||
self.AdvModeButton.setFont(font)
|
||||
self.AdvModeButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.AdvModeButton.setObjectName(_fromUtf8("AdvModeButton"))
|
||||
self.OptionsAdvancedGamma = QtGui.QFrame(self.Form)
|
||||
self.OptionsAdvancedGamma.setEnabled(True)
|
||||
self.OptionsAdvancedGamma.setGeometry(QtCore.QRect(10, 305, 401, 41))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(9)
|
||||
self.OptionsAdvancedGamma.setFont(font)
|
||||
self.OptionsAdvancedGamma.setObjectName(_fromUtf8("OptionsAdvancedGamma"))
|
||||
self.GammaLabel = QtGui.QLabel(self.OptionsAdvancedGamma)
|
||||
self.GammaLabel.setGeometry(QtCore.QRect(15, 0, 100, 40))
|
||||
self.GammaLabel.setObjectName(_fromUtf8("GammaLabel"))
|
||||
self.GammaSlider = QtGui.QSlider(self.OptionsAdvancedGamma)
|
||||
self.GammaSlider.setGeometry(QtCore.QRect(110, 10, 270, 22))
|
||||
self.GammaSlider.setFocusPolicy(QtCore.Qt.ClickFocus)
|
||||
self.GammaSlider.setMaximum(500)
|
||||
self.GammaSlider.setSingleStep(5)
|
||||
self.GammaSlider.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.GammaSlider.setObjectName(_fromUtf8("GammaSlider"))
|
||||
self.ProgressBar = QtGui.QProgressBar(self.Form)
|
||||
self.ProgressBar.setGeometry(QtCore.QRect(10, 10, 401, 31))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(10)
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
self.ProgressBar.setFont(font)
|
||||
self.ProgressBar.setProperty("value", 0)
|
||||
self.ProgressBar.setAlignment(QtCore.Qt.AlignJustify|QtCore.Qt.AlignVCenter)
|
||||
self.ProgressBar.setFormat(_fromUtf8(""))
|
||||
self.ProgressBar.setObjectName(_fromUtf8("ProgressBar"))
|
||||
self.OptionsExpert = QtGui.QFrame(self.Form)
|
||||
self.OptionsExpert.setGeometry(QtCore.QRect(10, 337, 421, 41))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(9)
|
||||
self.OptionsExpert.setFont(font)
|
||||
self.OptionsExpert.setObjectName(_fromUtf8("OptionsExpert"))
|
||||
self.ColorBox = QtGui.QCheckBox(self.OptionsExpert)
|
||||
self.ColorBox.setGeometry(QtCore.QRect(9, 11, 130, 18))
|
||||
self.ColorBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.ColorBox.setObjectName(_fromUtf8("ColorBox"))
|
||||
self.OptionsExpertInternal = QtGui.QFrame(self.OptionsExpert)
|
||||
self.OptionsExpertInternal.setGeometry(QtCore.QRect(100, 0, 295, 40))
|
||||
self.OptionsExpertInternal.setObjectName(_fromUtf8("OptionsExpertInternal"))
|
||||
self.gridLayout_2 = QtGui.QGridLayout(self.OptionsExpertInternal)
|
||||
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
|
||||
self.wLabel = QtGui.QLabel(self.OptionsExpertInternal)
|
||||
self.wLabel.setObjectName(_fromUtf8("wLabel"))
|
||||
self.gridLayout_2.addWidget(self.wLabel, 0, 0, 1, 1)
|
||||
self.customWidth = QtGui.QLineEdit(self.OptionsExpertInternal)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.customWidth.sizePolicy().hasHeightForWidth())
|
||||
self.customWidth.setSizePolicy(sizePolicy)
|
||||
self.customWidth.setMaximumSize(QtCore.QSize(40, 16777215))
|
||||
self.customWidth.setFocusPolicy(QtCore.Qt.ClickFocus)
|
||||
self.customWidth.setAcceptDrops(False)
|
||||
self.customWidth.setMaxLength(4)
|
||||
self.customWidth.setObjectName(_fromUtf8("customWidth"))
|
||||
self.gridLayout_2.addWidget(self.customWidth, 0, 1, 1, 1)
|
||||
self.hLabel = QtGui.QLabel(self.OptionsExpertInternal)
|
||||
self.hLabel.setObjectName(_fromUtf8("hLabel"))
|
||||
self.gridLayout_2.addWidget(self.hLabel, 0, 2, 1, 1)
|
||||
self.customHeight = QtGui.QLineEdit(self.OptionsExpertInternal)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.customHeight.sizePolicy().hasHeightForWidth())
|
||||
self.customHeight.setSizePolicy(sizePolicy)
|
||||
self.customHeight.setMaximumSize(QtCore.QSize(40, 16777215))
|
||||
self.customHeight.setFocusPolicy(QtCore.Qt.ClickFocus)
|
||||
self.customHeight.setAcceptDrops(False)
|
||||
self.customHeight.setMaxLength(4)
|
||||
self.customHeight.setObjectName(_fromUtf8("customHeight"))
|
||||
self.gridLayout_2.addWidget(self.customHeight, 0, 3, 1, 1)
|
||||
KCC.setCentralWidget(self.Form)
|
||||
self.statusBar = QtGui.QStatusBar(KCC)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("MS Shell Dlg 2"))
|
||||
font.setPointSize(8)
|
||||
self.statusBar.setFont(font)
|
||||
self.statusBar.setSizeGripEnabled(False)
|
||||
self.statusBar.setObjectName(_fromUtf8("statusBar"))
|
||||
KCC.setStatusBar(self.statusBar)
|
||||
self.ActionBasic = QtGui.QAction(KCC)
|
||||
self.ActionBasic.setCheckable(True)
|
||||
self.ActionBasic.setChecked(False)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(9)
|
||||
self.ActionBasic.setFont(font)
|
||||
self.ActionBasic.setObjectName(_fromUtf8("ActionBasic"))
|
||||
self.ActionAdvanced = QtGui.QAction(KCC)
|
||||
self.ActionAdvanced.setCheckable(True)
|
||||
self.ActionAdvanced.setObjectName(_fromUtf8("ActionAdvanced"))
|
||||
|
||||
self.retranslateUi(KCC)
|
||||
QtCore.QMetaObject.connectSlotsByName(KCC)
|
||||
KCC.setTabOrder(self.DirectoryButton, self.FileButton)
|
||||
KCC.setTabOrder(self.FileButton, self.ConvertButton)
|
||||
KCC.setTabOrder(self.ConvertButton, self.ClearButton)
|
||||
|
||||
def retranslateUi(self, KCC):
|
||||
KCC.setWindowTitle(_translate("KCC", "Kindle Comic Converter", None))
|
||||
self.ProcessingBox.setToolTip(_translate("KCC", "Disable image optimizations.", None))
|
||||
self.ProcessingBox.setText(_translate("KCC", "No optimisation", None))
|
||||
self.UpscaleBox.setToolTip(_translate("KCC", "<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))
|
||||
self.UpscaleBox.setText(_translate("KCC", "Stretch/Upscale", None))
|
||||
self.WebtoonBox.setToolTip(_translate("KCC", "<html><head/><body><p>Enable auto-splitting of webtoons like <span style=\" font-style:italic;\">Tower of God</span> or <span style=\" font-style:italic;\">Noblesse</span>.<br/>Pages with a low width, high height and vertical panel flow.</p></body></html>", None))
|
||||
self.WebtoonBox.setText(_translate("KCC", "Webtoon mode", None))
|
||||
self.NoDitheringBox.setToolTip(_translate("KCC", "<html><head/><body><p>Create PNG files instead JPEG.<br/>Quality increase is not noticeable on most of devices.<br/>Output files <span style=\" font-weight:600;\">might</span> be smaller.<br/><span style=\" font-weight:600;\">MOBI conversion will be much slower.</span></p></body></html>", None))
|
||||
self.NoDitheringBox.setText(_translate("KCC", "PNG output", None))
|
||||
self.BorderBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Autodetection<br/></span>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))
|
||||
self.BorderBox.setText(_translate("KCC", "W/B margins", None))
|
||||
self.NoRotateBox.setToolTip(_translate("KCC", "<html><head/><body><p>Disable splitting and rotation.</p></body></html>", None))
|
||||
self.NoRotateBox.setText(_translate("KCC", "No split/rotate", None))
|
||||
self.DeviceBox.setToolTip(_translate("KCC", "Target device.", None))
|
||||
self.FormatBox.setToolTip(_translate("KCC", "Output format.", None))
|
||||
self.ConvertButton.setText(_translate("KCC", "Convert", None))
|
||||
self.DirectoryButton.setText(_translate("KCC", "Add directory", None))
|
||||
self.FileButton.setText(_translate("KCC", "Add file", None))
|
||||
self.ClearButton.setText(_translate("KCC", "Clear list", None))
|
||||
self.MangaBox.setToolTip(_translate("KCC", "Enable right-to-left reading.", None))
|
||||
self.MangaBox.setText(_translate("KCC", "Manga mode", None))
|
||||
self.QualityBox.setToolTip(_translate("KCC", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
|
||||
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
|
||||
"p, li { white-space: pre-wrap; }\n"
|
||||
"</style></head><body style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt; font-weight:400; font-style:normal;\">\n"
|
||||
"<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Normal quality mode<br /></span><span style=\" font-style:italic;\">Use it when Panel View support is not needed.</span><span style=\" font-weight:600; text-decoration: underline;\"><br /></span>- Maximum quality when zoom is not enabled.<br />- Poor quality when zoom is enabled.<br />- Lowest file size.</p>\n"
|
||||
"<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - High quality mode<br /></span><span style=\" font-style:italic;\">Not zoomed image </span><span style=\" font-weight:600; font-style:italic;\">might </span><span style=\" font-style:italic;\">be </span><span style=\" font-style:italic;\">a little blurry.</span><span style=\" font-weight:600; text-decoration: underline;\"><br /></span>- Medium/High quality when zoom is not enabled.<br />- Maximum quality when zoom is enabled.</p>\n"
|
||||
"<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-weight:600; text-decoration: underline;\">Checked - Ultra quality mode<br /></span><span style=\" font-style:italic;\">Maximum possible quality.</span><span style=\" font-weight:600; text-decoration: underline;\"><br /></span>- Maximum quality when zoom is not enabled.<br />- Maximum quality when zoom is enabled.<br />- Very high file size.</p></body></html>", None))
|
||||
self.QualityBox.setText(_translate("KCC", "High/Ultra quality", None))
|
||||
self.RotateBox.setToolTip(_translate("KCC", "<html><head/><body><p>Disable page spliting.<br/>They will be rotated instead.</p></body></html>", None))
|
||||
self.RotateBox.setText(_translate("KCC", "Horizontal mode", None))
|
||||
self.BasicModeButton.setText(_translate("KCC", "Basic", None))
|
||||
self.AdvModeButton.setText(_translate("KCC", "Advanced", None))
|
||||
self.GammaLabel.setText(_translate("KCC", "Gamma: Auto", None))
|
||||
self.ColorBox.setToolTip(_translate("KCC", "Do not convert images to grayscale.", None))
|
||||
self.ColorBox.setText(_translate("KCC", "Color mode", None))
|
||||
self.wLabel.setToolTip(_translate("KCC", "Resolution of target device.", None))
|
||||
self.wLabel.setText(_translate("KCC", "Custom width: ", None))
|
||||
self.customWidth.setToolTip(_translate("KCC", "Resolution of target device.", None))
|
||||
self.customWidth.setInputMask(_translate("KCC", "0000; ", None))
|
||||
self.hLabel.setToolTip(_translate("KCC", "Resolution of target device.", None))
|
||||
self.hLabel.setText(_translate("KCC", "Custom height: ", None))
|
||||
self.customHeight.setToolTip(_translate("KCC", "Resolution of target device.", None))
|
||||
self.customHeight.setInputMask(_translate("KCC", "0000; ", None))
|
||||
self.ActionBasic.setText(_translate("KCC", "Basic", None))
|
||||
self.ActionAdvanced.setText(_translate("KCC", "Advanced", None))
|
||||
|
||||
import KCC_rc
|
||||
@@ -1,391 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'KCC-Linux.ui'
|
||||
#
|
||||
# Created: Wed Dec 04 18:27:52 2013
|
||||
# by: PyQt4 UI code generator 4.10.3
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
try:
|
||||
_fromUtf8 = QtCore.QString.fromUtf8
|
||||
except AttributeError:
|
||||
def _fromUtf8(s):
|
||||
return s
|
||||
|
||||
try:
|
||||
_encoding = QtGui.QApplication.UnicodeUTF8
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
||||
except AttributeError:
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig)
|
||||
|
||||
class Ui_KCC(object):
|
||||
def setupUi(self, KCC):
|
||||
KCC.setObjectName(_fromUtf8("KCC"))
|
||||
KCC.resize(420, 397)
|
||||
KCC.setMinimumSize(QtCore.QSize(420, 397))
|
||||
KCC.setMaximumSize(QtCore.QSize(420, 397))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(9)
|
||||
KCC.setFont(font)
|
||||
icon = QtGui.QIcon()
|
||||
icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/Icon/icons/comic2ebook.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
KCC.setWindowIcon(icon)
|
||||
KCC.setLocale(QtCore.QLocale(QtCore.QLocale.C, QtCore.QLocale.AnyCountry))
|
||||
self.Form = QtGui.QWidget(KCC)
|
||||
self.Form.setObjectName(_fromUtf8("Form"))
|
||||
self.OptionsAdvanced = QtGui.QFrame(self.Form)
|
||||
self.OptionsAdvanced.setEnabled(True)
|
||||
self.OptionsAdvanced.setGeometry(QtCore.QRect(1, 254, 421, 61))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
font.setPointSize(9)
|
||||
self.OptionsAdvanced.setFont(font)
|
||||
self.OptionsAdvanced.setObjectName(_fromUtf8("OptionsAdvanced"))
|
||||
self.gridLayout = QtGui.QGridLayout(self.OptionsAdvanced)
|
||||
self.gridLayout.setContentsMargins(9, -1, -1, -1)
|
||||
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
|
||||
self.ProcessingBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.ProcessingBox.setFont(font)
|
||||
self.ProcessingBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.ProcessingBox.setObjectName(_fromUtf8("ProcessingBox"))
|
||||
self.gridLayout.addWidget(self.ProcessingBox, 1, 0, 1, 1)
|
||||
self.UpscaleBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.UpscaleBox.setFont(font)
|
||||
self.UpscaleBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.UpscaleBox.setTristate(True)
|
||||
self.UpscaleBox.setObjectName(_fromUtf8("UpscaleBox"))
|
||||
self.gridLayout.addWidget(self.UpscaleBox, 1, 1, 1, 1)
|
||||
self.WebtoonBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.WebtoonBox.setFont(font)
|
||||
self.WebtoonBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.WebtoonBox.setObjectName(_fromUtf8("WebtoonBox"))
|
||||
self.gridLayout.addWidget(self.WebtoonBox, 3, 1, 1, 1)
|
||||
self.NoDitheringBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.NoDitheringBox.setFont(font)
|
||||
self.NoDitheringBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.NoDitheringBox.setObjectName(_fromUtf8("NoDitheringBox"))
|
||||
self.gridLayout.addWidget(self.NoDitheringBox, 3, 2, 1, 1)
|
||||
self.BorderBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.BorderBox.setFont(font)
|
||||
self.BorderBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.BorderBox.setTristate(True)
|
||||
self.BorderBox.setObjectName(_fromUtf8("BorderBox"))
|
||||
self.gridLayout.addWidget(self.BorderBox, 3, 0, 1, 1)
|
||||
self.NoRotateBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.NoRotateBox.setFont(font)
|
||||
self.NoRotateBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.NoRotateBox.setObjectName(_fromUtf8("NoRotateBox"))
|
||||
self.gridLayout.addWidget(self.NoRotateBox, 1, 2, 1, 1)
|
||||
self.DeviceBox = QtGui.QComboBox(self.Form)
|
||||
self.DeviceBox.setGeometry(QtCore.QRect(10, 200, 141, 31))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
font.setPointSize(8)
|
||||
self.DeviceBox.setFont(font)
|
||||
self.DeviceBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.DeviceBox.setObjectName(_fromUtf8("DeviceBox"))
|
||||
self.FormatBox = QtGui.QComboBox(self.Form)
|
||||
self.FormatBox.setGeometry(QtCore.QRect(260, 200, 151, 31))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
font.setPointSize(8)
|
||||
self.FormatBox.setFont(font)
|
||||
self.FormatBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.FormatBox.setObjectName(_fromUtf8("FormatBox"))
|
||||
self.ConvertButton = QtGui.QPushButton(self.Form)
|
||||
self.ConvertButton.setGeometry(QtCore.QRect(160, 200, 91, 32))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
font.setPointSize(9)
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
self.ConvertButton.setFont(font)
|
||||
self.ConvertButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
icon1 = QtGui.QIcon()
|
||||
icon1.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/convert.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
self.ConvertButton.setIcon(icon1)
|
||||
self.ConvertButton.setObjectName(_fromUtf8("ConvertButton"))
|
||||
self.DirectoryButton = QtGui.QPushButton(self.Form)
|
||||
self.DirectoryButton.setGeometry(QtCore.QRect(10, 160, 141, 32))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
font.setPointSize(8)
|
||||
self.DirectoryButton.setFont(font)
|
||||
self.DirectoryButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
icon2 = QtGui.QIcon()
|
||||
icon2.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/folder_new.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
self.DirectoryButton.setIcon(icon2)
|
||||
self.DirectoryButton.setObjectName(_fromUtf8("DirectoryButton"))
|
||||
self.FileButton = QtGui.QPushButton(self.Form)
|
||||
self.FileButton.setGeometry(QtCore.QRect(260, 160, 151, 32))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
font.setPointSize(8)
|
||||
self.FileButton.setFont(font)
|
||||
self.FileButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
icon3 = QtGui.QIcon()
|
||||
icon3.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/document_new.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
self.FileButton.setIcon(icon3)
|
||||
self.FileButton.setObjectName(_fromUtf8("FileButton"))
|
||||
self.ClearButton = QtGui.QPushButton(self.Form)
|
||||
self.ClearButton.setGeometry(QtCore.QRect(160, 160, 91, 32))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
font.setPointSize(8)
|
||||
self.ClearButton.setFont(font)
|
||||
self.ClearButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
icon4 = QtGui.QIcon()
|
||||
icon4.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/clear.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
self.ClearButton.setIcon(icon4)
|
||||
self.ClearButton.setObjectName(_fromUtf8("ClearButton"))
|
||||
self.OptionsBasic = QtGui.QFrame(self.Form)
|
||||
self.OptionsBasic.setGeometry(QtCore.QRect(1, 230, 421, 41))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
font.setPointSize(9)
|
||||
self.OptionsBasic.setFont(font)
|
||||
self.OptionsBasic.setObjectName(_fromUtf8("OptionsBasic"))
|
||||
self.MangaBox = QtGui.QCheckBox(self.OptionsBasic)
|
||||
self.MangaBox.setGeometry(QtCore.QRect(9, 10, 130, 18))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.MangaBox.setFont(font)
|
||||
self.MangaBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.MangaBox.setObjectName(_fromUtf8("MangaBox"))
|
||||
self.QualityBox = QtGui.QCheckBox(self.OptionsBasic)
|
||||
self.QualityBox.setGeometry(QtCore.QRect(282, 10, 135, 18))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.QualityBox.setFont(font)
|
||||
self.QualityBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.QualityBox.setTristate(True)
|
||||
self.QualityBox.setObjectName(_fromUtf8("QualityBox"))
|
||||
self.RotateBox = QtGui.QCheckBox(self.OptionsBasic)
|
||||
self.RotateBox.setGeometry(QtCore.QRect(145, 10, 130, 18))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.RotateBox.setFont(font)
|
||||
self.RotateBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.RotateBox.setObjectName(_fromUtf8("RotateBox"))
|
||||
self.JobList = QtGui.QListWidget(self.Form)
|
||||
self.JobList.setGeometry(QtCore.QRect(10, 50, 401, 101))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
font.setPointSize(8)
|
||||
font.setItalic(False)
|
||||
self.JobList.setFont(font)
|
||||
self.JobList.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.JobList.setStyleSheet(_fromUtf8("QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}"))
|
||||
self.JobList.setProperty("showDropIndicator", False)
|
||||
self.JobList.setSelectionMode(QtGui.QAbstractItemView.NoSelection)
|
||||
self.JobList.setIconSize(QtCore.QSize(18, 18))
|
||||
self.JobList.setVerticalScrollMode(QtGui.QAbstractItemView.ScrollPerPixel)
|
||||
self.JobList.setHorizontalScrollMode(QtGui.QAbstractItemView.ScrollPerPixel)
|
||||
self.JobList.setObjectName(_fromUtf8("JobList"))
|
||||
self.BasicModeButton = QtGui.QPushButton(self.Form)
|
||||
self.BasicModeButton.setGeometry(QtCore.QRect(10, 10, 195, 32))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
font.setPointSize(9)
|
||||
self.BasicModeButton.setFont(font)
|
||||
self.BasicModeButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.BasicModeButton.setObjectName(_fromUtf8("BasicModeButton"))
|
||||
self.AdvModeButton = QtGui.QPushButton(self.Form)
|
||||
self.AdvModeButton.setGeometry(QtCore.QRect(217, 10, 195, 32))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
font.setPointSize(9)
|
||||
self.AdvModeButton.setFont(font)
|
||||
self.AdvModeButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.AdvModeButton.setObjectName(_fromUtf8("AdvModeButton"))
|
||||
self.OptionsAdvancedGamma = QtGui.QFrame(self.Form)
|
||||
self.OptionsAdvancedGamma.setEnabled(True)
|
||||
self.OptionsAdvancedGamma.setGeometry(QtCore.QRect(10, 305, 401, 41))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
font.setPointSize(9)
|
||||
self.OptionsAdvancedGamma.setFont(font)
|
||||
self.OptionsAdvancedGamma.setObjectName(_fromUtf8("OptionsAdvancedGamma"))
|
||||
self.GammaLabel = QtGui.QLabel(self.OptionsAdvancedGamma)
|
||||
self.GammaLabel.setGeometry(QtCore.QRect(15, 0, 100, 40))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.GammaLabel.setFont(font)
|
||||
self.GammaLabel.setObjectName(_fromUtf8("GammaLabel"))
|
||||
self.GammaSlider = QtGui.QSlider(self.OptionsAdvancedGamma)
|
||||
self.GammaSlider.setGeometry(QtCore.QRect(110, 10, 275, 22))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.GammaSlider.setFont(font)
|
||||
self.GammaSlider.setFocusPolicy(QtCore.Qt.ClickFocus)
|
||||
self.GammaSlider.setMaximum(500)
|
||||
self.GammaSlider.setSingleStep(5)
|
||||
self.GammaSlider.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.GammaSlider.setObjectName(_fromUtf8("GammaSlider"))
|
||||
self.ProgressBar = QtGui.QProgressBar(self.Form)
|
||||
self.ProgressBar.setGeometry(QtCore.QRect(10, 10, 401, 31))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
font.setPointSize(10)
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
self.ProgressBar.setFont(font)
|
||||
self.ProgressBar.setProperty("value", 0)
|
||||
self.ProgressBar.setAlignment(QtCore.Qt.AlignJustify|QtCore.Qt.AlignVCenter)
|
||||
self.ProgressBar.setFormat(_fromUtf8(""))
|
||||
self.ProgressBar.setObjectName(_fromUtf8("ProgressBar"))
|
||||
self.OptionsExpert = QtGui.QFrame(self.Form)
|
||||
self.OptionsExpert.setGeometry(QtCore.QRect(1, 337, 421, 41))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
font.setPointSize(9)
|
||||
self.OptionsExpert.setFont(font)
|
||||
self.OptionsExpert.setObjectName(_fromUtf8("OptionsExpert"))
|
||||
self.ColorBox = QtGui.QCheckBox(self.OptionsExpert)
|
||||
self.ColorBox.setGeometry(QtCore.QRect(9, 11, 130, 18))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.ColorBox.setFont(font)
|
||||
self.ColorBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.ColorBox.setObjectName(_fromUtf8("ColorBox"))
|
||||
self.OptionsExpertInternal = QtGui.QFrame(self.OptionsExpert)
|
||||
self.OptionsExpertInternal.setGeometry(QtCore.QRect(105, 0, 295, 40))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.OptionsExpertInternal.setFont(font)
|
||||
self.OptionsExpertInternal.setObjectName(_fromUtf8("OptionsExpertInternal"))
|
||||
self.gridLayout_2 = QtGui.QGridLayout(self.OptionsExpertInternal)
|
||||
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
|
||||
self.wLabel = QtGui.QLabel(self.OptionsExpertInternal)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.wLabel.setFont(font)
|
||||
self.wLabel.setObjectName(_fromUtf8("wLabel"))
|
||||
self.gridLayout_2.addWidget(self.wLabel, 0, 0, 1, 1)
|
||||
self.customWidth = QtGui.QLineEdit(self.OptionsExpertInternal)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.customWidth.sizePolicy().hasHeightForWidth())
|
||||
self.customWidth.setSizePolicy(sizePolicy)
|
||||
self.customWidth.setMaximumSize(QtCore.QSize(40, 16777215))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.customWidth.setFont(font)
|
||||
self.customWidth.setFocusPolicy(QtCore.Qt.ClickFocus)
|
||||
self.customWidth.setAcceptDrops(False)
|
||||
self.customWidth.setMaxLength(4)
|
||||
self.customWidth.setObjectName(_fromUtf8("customWidth"))
|
||||
self.gridLayout_2.addWidget(self.customWidth, 0, 1, 1, 1)
|
||||
self.hLabel = QtGui.QLabel(self.OptionsExpertInternal)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.hLabel.setFont(font)
|
||||
self.hLabel.setObjectName(_fromUtf8("hLabel"))
|
||||
self.gridLayout_2.addWidget(self.hLabel, 0, 2, 1, 1)
|
||||
self.customHeight = QtGui.QLineEdit(self.OptionsExpertInternal)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.customHeight.sizePolicy().hasHeightForWidth())
|
||||
self.customHeight.setSizePolicy(sizePolicy)
|
||||
self.customHeight.setMaximumSize(QtCore.QSize(40, 16777215))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.customHeight.setFont(font)
|
||||
self.customHeight.setFocusPolicy(QtCore.Qt.ClickFocus)
|
||||
self.customHeight.setAcceptDrops(False)
|
||||
self.customHeight.setMaxLength(4)
|
||||
self.customHeight.setObjectName(_fromUtf8("customHeight"))
|
||||
self.gridLayout_2.addWidget(self.customHeight, 0, 3, 1, 1)
|
||||
KCC.setCentralWidget(self.Form)
|
||||
self.statusBar = QtGui.QStatusBar(KCC)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
font.setPointSize(8)
|
||||
self.statusBar.setFont(font)
|
||||
self.statusBar.setSizeGripEnabled(False)
|
||||
self.statusBar.setObjectName(_fromUtf8("statusBar"))
|
||||
KCC.setStatusBar(self.statusBar)
|
||||
self.ActionBasic = QtGui.QAction(KCC)
|
||||
self.ActionBasic.setCheckable(True)
|
||||
self.ActionBasic.setChecked(False)
|
||||
font = QtGui.QFont()
|
||||
self.ActionBasic.setFont(font)
|
||||
self.ActionBasic.setObjectName(_fromUtf8("ActionBasic"))
|
||||
self.ActionAdvanced = QtGui.QAction(KCC)
|
||||
self.ActionAdvanced.setCheckable(True)
|
||||
self.ActionAdvanced.setObjectName(_fromUtf8("ActionAdvanced"))
|
||||
|
||||
self.retranslateUi(KCC)
|
||||
QtCore.QMetaObject.connectSlotsByName(KCC)
|
||||
KCC.setTabOrder(self.DirectoryButton, self.FileButton)
|
||||
KCC.setTabOrder(self.FileButton, self.ConvertButton)
|
||||
KCC.setTabOrder(self.ConvertButton, self.ClearButton)
|
||||
|
||||
def retranslateUi(self, KCC):
|
||||
KCC.setWindowTitle(_translate("KCC", "Kindle Comic Converter", None))
|
||||
self.ProcessingBox.setToolTip(_translate("KCC", "Disable image optimizations.", None))
|
||||
self.ProcessingBox.setText(_translate("KCC", "No optimisation", None))
|
||||
self.UpscaleBox.setToolTip(_translate("KCC", "<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))
|
||||
self.UpscaleBox.setText(_translate("KCC", "Stretch/Upscale", None))
|
||||
self.WebtoonBox.setToolTip(_translate("KCC", "<html><head/><body><p>Enable auto-splitting of webtoons like <span style=\" font-style:italic;\">Tower of God</span> or <span style=\" font-style:italic;\">Noblesse</span>.<br/>Pages with a low width, high height and vertical panel flow.</p></body></html>", None))
|
||||
self.WebtoonBox.setText(_translate("KCC", "Webtoon mode", None))
|
||||
self.NoDitheringBox.setToolTip(_translate("KCC", "<html><head/><body><p>Create PNG files instead JPEG.<br/>Quality increase is not noticeable on most of devices.<br/>Output files <span style=\" font-weight:600;\">might</span> be smaller.<br/><span style=\" font-weight:600;\">MOBI conversion will be much slower.</span></p></body></html>", None))
|
||||
self.NoDitheringBox.setText(_translate("KCC", "PNG output", None))
|
||||
self.BorderBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Autodetection<br/></span>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))
|
||||
self.BorderBox.setText(_translate("KCC", "W/B margins", None))
|
||||
self.NoRotateBox.setToolTip(_translate("KCC", "<html><head/><body><p>Disable splitting and rotation.</p></body></html>", None))
|
||||
self.NoRotateBox.setText(_translate("KCC", "No split/rotate", None))
|
||||
self.DeviceBox.setToolTip(_translate("KCC", "Target device.", None))
|
||||
self.FormatBox.setToolTip(_translate("KCC", "Output format.", None))
|
||||
self.ConvertButton.setText(_translate("KCC", "Convert", None))
|
||||
self.DirectoryButton.setText(_translate("KCC", "Add directory", None))
|
||||
self.FileButton.setText(_translate("KCC", "Add file", None))
|
||||
self.ClearButton.setText(_translate("KCC", "Clear list", None))
|
||||
self.MangaBox.setToolTip(_translate("KCC", "Enable right-to-left reading.", None))
|
||||
self.MangaBox.setText(_translate("KCC", "Manga mode", None))
|
||||
self.QualityBox.setToolTip(_translate("KCC", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
|
||||
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
|
||||
"p, li { white-space: pre-wrap; }\n"
|
||||
"</style></head><body style=\" font-family:\'Sans\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
|
||||
"<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-weight:600; text-decoration: underline;\">Unchecked - Normal quality mode<br /></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-style:italic;\">Use it when Panel View support is not needed.</span><span style=\" font-family:\'MS Shell Dlg 2\'; font-weight:600; text-decoration: underline;\"><br /></span><span style=\" font-family:\'MS Shell Dlg 2\';\">- Maximum quality when zoom is not enabled.<br />- Poor quality when zoom is enabled.<br />- Lowest file size.</span></p>\n"
|
||||
"<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-weight:600; text-decoration: underline;\">Indeterminate - High quality mode<br /></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-style:italic;\">Not zoomed image </span><span style=\" font-family:\'MS Shell Dlg 2\'; font-weight:600; font-style:italic;\">might </span><span style=\" font-family:\'MS Shell Dlg 2\'; font-style:italic;\">be a little blurry.</span><span style=\" font-family:\'MS Shell Dlg 2\'; font-weight:600; text-decoration: underline;\"><br /></span><span style=\" font-family:\'MS Shell Dlg 2\';\">- Medium/High quality when zoom is not enabled.<br />- Maximum quality when zoom is enabled.</span></p>\n"
|
||||
"<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-weight:600; text-decoration: underline;\">Checked - Ultra quality mode<br /></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-style:italic;\">Maximum possible quality.</span><span style=\" font-family:\'MS Shell Dlg 2\'; font-weight:600; text-decoration: underline;\"><br /></span><span style=\" font-family:\'MS Shell Dlg 2\';\">- Maximum quality when zoom is not enabled.<br />- Maximum quality when zoom is enabled.<br />- Very high file size.</span></p></body></html>", None))
|
||||
self.QualityBox.setText(_translate("KCC", "High/Ultra quality", None))
|
||||
self.RotateBox.setToolTip(_translate("KCC", "<html><head/><body><p>Disable page spliting.<br/>They will be rotated instead.</p></body></html>", None))
|
||||
self.RotateBox.setText(_translate("KCC", "Horizontal mode", None))
|
||||
self.BasicModeButton.setText(_translate("KCC", "Basic", None))
|
||||
self.AdvModeButton.setText(_translate("KCC", "Advanced", None))
|
||||
self.GammaLabel.setText(_translate("KCC", "Gamma: Auto", None))
|
||||
self.ColorBox.setToolTip(_translate("KCC", "Do not convert images to grayscale.", None))
|
||||
self.ColorBox.setText(_translate("KCC", "Color mode", None))
|
||||
self.wLabel.setToolTip(_translate("KCC", "Resolution of target device.", None))
|
||||
self.wLabel.setText(_translate("KCC", "Custom width: ", None))
|
||||
self.customWidth.setToolTip(_translate("KCC", "Resolution of target device.", None))
|
||||
self.customWidth.setInputMask(_translate("KCC", "0000; ", None))
|
||||
self.hLabel.setToolTip(_translate("KCC", "Resolution of target device.", None))
|
||||
self.hLabel.setText(_translate("KCC", "Custom height: ", None))
|
||||
self.customHeight.setToolTip(_translate("KCC", "Resolution of target device.", None))
|
||||
self.customHeight.setInputMask(_translate("KCC", "0000; ", None))
|
||||
self.ActionBasic.setText(_translate("KCC", "Basic", None))
|
||||
self.ActionAdvanced.setText(_translate("KCC", "Advanced", None))
|
||||
|
||||
import KCC_rc
|
||||
@@ -1,409 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'KCC-OSX.ui'
|
||||
#
|
||||
# Created: Wed Dec 04 18:28:04 2013
|
||||
# by: PyQt4 UI code generator 4.10.3
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
try:
|
||||
_fromUtf8 = QtCore.QString.fromUtf8
|
||||
except AttributeError:
|
||||
def _fromUtf8(s):
|
||||
return s
|
||||
|
||||
try:
|
||||
_encoding = QtGui.QApplication.UnicodeUTF8
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
||||
except AttributeError:
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig)
|
||||
|
||||
class Ui_KCC(object):
|
||||
def setupUi(self, KCC):
|
||||
KCC.setObjectName(_fromUtf8("KCC"))
|
||||
KCC.resize(420, 397)
|
||||
KCC.setMinimumSize(QtCore.QSize(420, 397))
|
||||
KCC.setMaximumSize(QtCore.QSize(420, 397))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(9)
|
||||
KCC.setFont(font)
|
||||
icon = QtGui.QIcon()
|
||||
icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/Icon/icons/comic2ebook.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
KCC.setWindowIcon(icon)
|
||||
KCC.setLocale(QtCore.QLocale(QtCore.QLocale.C, QtCore.QLocale.AnyCountry))
|
||||
self.Form = QtGui.QWidget(KCC)
|
||||
self.Form.setObjectName(_fromUtf8("Form"))
|
||||
self.OptionsAdvanced = QtGui.QFrame(self.Form)
|
||||
self.OptionsAdvanced.setEnabled(True)
|
||||
self.OptionsAdvanced.setGeometry(QtCore.QRect(4, 253, 421, 61))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(9)
|
||||
self.OptionsAdvanced.setFont(font)
|
||||
self.OptionsAdvanced.setObjectName(_fromUtf8("OptionsAdvanced"))
|
||||
self.gridLayout = QtGui.QGridLayout(self.OptionsAdvanced)
|
||||
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
|
||||
self.ProcessingBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
self.ProcessingBox.setFont(font)
|
||||
self.ProcessingBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.ProcessingBox.setObjectName(_fromUtf8("ProcessingBox"))
|
||||
self.gridLayout.addWidget(self.ProcessingBox, 1, 0, 1, 1)
|
||||
self.UpscaleBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
self.UpscaleBox.setFont(font)
|
||||
self.UpscaleBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.UpscaleBox.setTristate(True)
|
||||
self.UpscaleBox.setObjectName(_fromUtf8("UpscaleBox"))
|
||||
self.gridLayout.addWidget(self.UpscaleBox, 1, 1, 1, 1)
|
||||
self.WebtoonBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
self.WebtoonBox.setFont(font)
|
||||
self.WebtoonBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.WebtoonBox.setObjectName(_fromUtf8("WebtoonBox"))
|
||||
self.gridLayout.addWidget(self.WebtoonBox, 3, 1, 1, 1)
|
||||
self.NoDitheringBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
self.NoDitheringBox.setFont(font)
|
||||
self.NoDitheringBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.NoDitheringBox.setObjectName(_fromUtf8("NoDitheringBox"))
|
||||
self.gridLayout.addWidget(self.NoDitheringBox, 3, 2, 1, 1)
|
||||
self.BorderBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
self.BorderBox.setFont(font)
|
||||
self.BorderBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.BorderBox.setTristate(True)
|
||||
self.BorderBox.setObjectName(_fromUtf8("BorderBox"))
|
||||
self.gridLayout.addWidget(self.BorderBox, 3, 0, 1, 1)
|
||||
self.NoRotateBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
self.NoRotateBox.setFont(font)
|
||||
self.NoRotateBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.NoRotateBox.setObjectName(_fromUtf8("NoRotateBox"))
|
||||
self.gridLayout.addWidget(self.NoRotateBox, 1, 2, 1, 1)
|
||||
self.DeviceBox = QtGui.QComboBox(self.Form)
|
||||
self.DeviceBox.setGeometry(QtCore.QRect(8, 201, 151, 34))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(11)
|
||||
self.DeviceBox.setFont(font)
|
||||
self.DeviceBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.DeviceBox.setObjectName(_fromUtf8("DeviceBox"))
|
||||
self.FormatBox = QtGui.QComboBox(self.Form)
|
||||
self.FormatBox.setGeometry(QtCore.QRect(262, 201, 152, 34))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(11)
|
||||
self.FormatBox.setFont(font)
|
||||
self.FormatBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.FormatBox.setObjectName(_fromUtf8("FormatBox"))
|
||||
self.ConvertButton = QtGui.QPushButton(self.Form)
|
||||
self.ConvertButton.setGeometry(QtCore.QRect(160, 200, 101, 41))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(11)
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
self.ConvertButton.setFont(font)
|
||||
self.ConvertButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
icon1 = QtGui.QIcon()
|
||||
icon1.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/convert.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
self.ConvertButton.setIcon(icon1)
|
||||
self.ConvertButton.setObjectName(_fromUtf8("ConvertButton"))
|
||||
self.DirectoryButton = QtGui.QPushButton(self.Form)
|
||||
self.DirectoryButton.setGeometry(QtCore.QRect(5, 160, 156, 41))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(11)
|
||||
self.DirectoryButton.setFont(font)
|
||||
self.DirectoryButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
icon2 = QtGui.QIcon()
|
||||
icon2.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/folder_new.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
self.DirectoryButton.setIcon(icon2)
|
||||
self.DirectoryButton.setObjectName(_fromUtf8("DirectoryButton"))
|
||||
self.FileButton = QtGui.QPushButton(self.Form)
|
||||
self.FileButton.setGeometry(QtCore.QRect(260, 160, 157, 41))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(11)
|
||||
self.FileButton.setFont(font)
|
||||
self.FileButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
icon3 = QtGui.QIcon()
|
||||
icon3.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/document_new.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
self.FileButton.setIcon(icon3)
|
||||
self.FileButton.setObjectName(_fromUtf8("FileButton"))
|
||||
self.ClearButton = QtGui.QPushButton(self.Form)
|
||||
self.ClearButton.setGeometry(QtCore.QRect(160, 160, 101, 41))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(11)
|
||||
self.ClearButton.setFont(font)
|
||||
self.ClearButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
icon4 = QtGui.QIcon()
|
||||
icon4.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/clear.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
self.ClearButton.setIcon(icon4)
|
||||
self.ClearButton.setObjectName(_fromUtf8("ClearButton"))
|
||||
self.OptionsBasic = QtGui.QFrame(self.Form)
|
||||
self.OptionsBasic.setGeometry(QtCore.QRect(5, 233, 421, 41))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
self.OptionsBasic.setFont(font)
|
||||
self.OptionsBasic.setObjectName(_fromUtf8("OptionsBasic"))
|
||||
self.MangaBox = QtGui.QCheckBox(self.OptionsBasic)
|
||||
self.MangaBox.setGeometry(QtCore.QRect(9, 10, 130, 18))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
self.MangaBox.setFont(font)
|
||||
self.MangaBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.MangaBox.setObjectName(_fromUtf8("MangaBox"))
|
||||
self.QualityBox = QtGui.QCheckBox(self.OptionsBasic)
|
||||
self.QualityBox.setGeometry(QtCore.QRect(282, 10, 135, 18))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
self.QualityBox.setFont(font)
|
||||
self.QualityBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.QualityBox.setTristate(True)
|
||||
self.QualityBox.setObjectName(_fromUtf8("QualityBox"))
|
||||
self.RotateBox = QtGui.QCheckBox(self.OptionsBasic)
|
||||
self.RotateBox.setGeometry(QtCore.QRect(145, 10, 130, 18))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
self.RotateBox.setFont(font)
|
||||
self.RotateBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.RotateBox.setObjectName(_fromUtf8("RotateBox"))
|
||||
self.JobList = QtGui.QListWidget(self.Form)
|
||||
self.JobList.setGeometry(QtCore.QRect(10, 50, 401, 101))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(11)
|
||||
self.JobList.setFont(font)
|
||||
self.JobList.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.JobList.setStyleSheet(_fromUtf8("QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}"))
|
||||
self.JobList.setProperty("showDropIndicator", False)
|
||||
self.JobList.setSelectionMode(QtGui.QAbstractItemView.NoSelection)
|
||||
self.JobList.setVerticalScrollMode(QtGui.QAbstractItemView.ScrollPerPixel)
|
||||
self.JobList.setHorizontalScrollMode(QtGui.QAbstractItemView.ScrollPerPixel)
|
||||
self.JobList.setObjectName(_fromUtf8("JobList"))
|
||||
self.BasicModeButton = QtGui.QPushButton(self.Form)
|
||||
self.BasicModeButton.setGeometry(QtCore.QRect(5, 10, 210, 41))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
self.BasicModeButton.setFont(font)
|
||||
self.BasicModeButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.BasicModeButton.setObjectName(_fromUtf8("BasicModeButton"))
|
||||
self.AdvModeButton = QtGui.QPushButton(self.Form)
|
||||
self.AdvModeButton.setGeometry(QtCore.QRect(207, 10, 210, 41))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
self.AdvModeButton.setFont(font)
|
||||
self.AdvModeButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.AdvModeButton.setObjectName(_fromUtf8("AdvModeButton"))
|
||||
self.OptionsAdvancedGamma = QtGui.QFrame(self.Form)
|
||||
self.OptionsAdvancedGamma.setEnabled(True)
|
||||
self.OptionsAdvancedGamma.setGeometry(QtCore.QRect(5, 303, 401, 41))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(9)
|
||||
self.OptionsAdvancedGamma.setFont(font)
|
||||
self.OptionsAdvancedGamma.setObjectName(_fromUtf8("OptionsAdvancedGamma"))
|
||||
self.GammaLabel = QtGui.QLabel(self.OptionsAdvancedGamma)
|
||||
self.GammaLabel.setGeometry(QtCore.QRect(20, 0, 100, 40))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
self.GammaLabel.setFont(font)
|
||||
self.GammaLabel.setObjectName(_fromUtf8("GammaLabel"))
|
||||
self.GammaSlider = QtGui.QSlider(self.OptionsAdvancedGamma)
|
||||
self.GammaSlider.setGeometry(QtCore.QRect(110, 10, 290, 22))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
self.GammaSlider.setFont(font)
|
||||
self.GammaSlider.setFocusPolicy(QtCore.Qt.ClickFocus)
|
||||
self.GammaSlider.setMaximum(500)
|
||||
self.GammaSlider.setSingleStep(5)
|
||||
self.GammaSlider.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.GammaSlider.setObjectName(_fromUtf8("GammaSlider"))
|
||||
self.ProgressBar = QtGui.QProgressBar(self.Form)
|
||||
self.ProgressBar.setGeometry(QtCore.QRect(10, 10, 401, 35))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(10)
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
self.ProgressBar.setFont(font)
|
||||
self.ProgressBar.setAutoFillBackground(True)
|
||||
self.ProgressBar.setProperty("value", 0)
|
||||
self.ProgressBar.setAlignment(QtCore.Qt.AlignJustify|QtCore.Qt.AlignVCenter)
|
||||
self.ProgressBar.setFormat(_fromUtf8(""))
|
||||
self.ProgressBar.setObjectName(_fromUtf8("ProgressBar"))
|
||||
self.OptionsExpert = QtGui.QFrame(self.Form)
|
||||
self.OptionsExpert.setGeometry(QtCore.QRect(5, 335, 421, 41))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(9)
|
||||
self.OptionsExpert.setFont(font)
|
||||
self.OptionsExpert.setObjectName(_fromUtf8("OptionsExpert"))
|
||||
self.ColorBox = QtGui.QCheckBox(self.OptionsExpert)
|
||||
self.ColorBox.setGeometry(QtCore.QRect(9, 11, 130, 18))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
self.ColorBox.setFont(font)
|
||||
self.ColorBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.ColorBox.setObjectName(_fromUtf8("ColorBox"))
|
||||
self.OptionsExpertInternal = QtGui.QFrame(self.OptionsExpert)
|
||||
self.OptionsExpertInternal.setGeometry(QtCore.QRect(95, 0, 315, 40))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
self.OptionsExpertInternal.setFont(font)
|
||||
self.OptionsExpertInternal.setObjectName(_fromUtf8("OptionsExpertInternal"))
|
||||
self.gridLayout_2 = QtGui.QGridLayout(self.OptionsExpertInternal)
|
||||
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
|
||||
self.wLabel = QtGui.QLabel(self.OptionsExpertInternal)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
self.wLabel.setFont(font)
|
||||
self.wLabel.setObjectName(_fromUtf8("wLabel"))
|
||||
self.gridLayout_2.addWidget(self.wLabel, 0, 0, 1, 1)
|
||||
self.customWidth = QtGui.QLineEdit(self.OptionsExpertInternal)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.customWidth.sizePolicy().hasHeightForWidth())
|
||||
self.customWidth.setSizePolicy(sizePolicy)
|
||||
self.customWidth.setMaximumSize(QtCore.QSize(45, 16777215))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
self.customWidth.setFont(font)
|
||||
self.customWidth.setFocusPolicy(QtCore.Qt.ClickFocus)
|
||||
self.customWidth.setAcceptDrops(False)
|
||||
self.customWidth.setMaxLength(4)
|
||||
self.customWidth.setObjectName(_fromUtf8("customWidth"))
|
||||
self.gridLayout_2.addWidget(self.customWidth, 0, 1, 1, 1)
|
||||
self.hLabel = QtGui.QLabel(self.OptionsExpertInternal)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
self.hLabel.setFont(font)
|
||||
self.hLabel.setObjectName(_fromUtf8("hLabel"))
|
||||
self.gridLayout_2.addWidget(self.hLabel, 0, 2, 1, 1)
|
||||
self.customHeight = QtGui.QLineEdit(self.OptionsExpertInternal)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.customHeight.sizePolicy().hasHeightForWidth())
|
||||
self.customHeight.setSizePolicy(sizePolicy)
|
||||
self.customHeight.setMaximumSize(QtCore.QSize(45, 16777215))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
self.customHeight.setFont(font)
|
||||
self.customHeight.setFocusPolicy(QtCore.Qt.ClickFocus)
|
||||
self.customHeight.setAcceptDrops(False)
|
||||
self.customHeight.setMaxLength(4)
|
||||
self.customHeight.setObjectName(_fromUtf8("customHeight"))
|
||||
self.gridLayout_2.addWidget(self.customHeight, 0, 3, 1, 1)
|
||||
KCC.setCentralWidget(self.Form)
|
||||
self.statusBar = QtGui.QStatusBar(KCC)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Aharoni"))
|
||||
font.setPointSize(8)
|
||||
self.statusBar.setFont(font)
|
||||
self.statusBar.setSizeGripEnabled(False)
|
||||
self.statusBar.setObjectName(_fromUtf8("statusBar"))
|
||||
KCC.setStatusBar(self.statusBar)
|
||||
self.ActionBasic = QtGui.QAction(KCC)
|
||||
self.ActionBasic.setCheckable(True)
|
||||
self.ActionBasic.setChecked(False)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(9)
|
||||
self.ActionBasic.setFont(font)
|
||||
self.ActionBasic.setObjectName(_fromUtf8("ActionBasic"))
|
||||
self.ActionAdvanced = QtGui.QAction(KCC)
|
||||
self.ActionAdvanced.setCheckable(True)
|
||||
self.ActionAdvanced.setObjectName(_fromUtf8("ActionAdvanced"))
|
||||
|
||||
self.retranslateUi(KCC)
|
||||
QtCore.QMetaObject.connectSlotsByName(KCC)
|
||||
KCC.setTabOrder(self.DirectoryButton, self.FileButton)
|
||||
KCC.setTabOrder(self.FileButton, self.ConvertButton)
|
||||
KCC.setTabOrder(self.ConvertButton, self.ClearButton)
|
||||
|
||||
def retranslateUi(self, KCC):
|
||||
KCC.setWindowTitle(_translate("KCC", "Kindle Comic Converter", None))
|
||||
self.ProcessingBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Disable image optimizations.</span></p></body></html>", None))
|
||||
self.ProcessingBox.setText(_translate("KCC", "No optimisation", None))
|
||||
self.UpscaleBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt; font-weight:600; text-decoration: underline;\">Unchecked - Nothing<br/></span><span style=\" font-size:12pt;\">Images smaller than device resolution will not be resized.</span></p><p><span style=\" font-size:12pt; font-weight:600; text-decoration: underline;\">Indeterminate - Stretching<br/></span><span style=\" font-size:12pt;\">Images smaller than device resolution will be resized. Aspect ratio will be not preserved.</span></p><p><span style=\" font-size:12pt; font-weight:600; text-decoration: underline;\">Checked - Upscaling<br/></span><span style=\" font-size:12pt;\">Images smaller than device resolution will be resized. Aspect ratio will be preserved.</span></p></body></html>", None))
|
||||
self.UpscaleBox.setText(_translate("KCC", "Stretch/Upscale", None))
|
||||
self.WebtoonBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Enable auto-splitting of webtoons like </span><span style=\" font-size:12pt; font-style:italic;\">Tower of God</span><span style=\" font-size:12pt;\"> or </span><span style=\" font-size:12pt; font-style:italic;\">Noblesse</span><span style=\" font-size:12pt;\">.<br/>Pages with a low width, high height and vertical panel flow.</span></p></body></html>", None))
|
||||
self.WebtoonBox.setText(_translate("KCC", "Webtoon mode", None))
|
||||
self.NoDitheringBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Create PNG files instead JPEG.<br/>Quality increase is not noticeable on most of devices.<br/>Output files </span><span style=\" font-size:12pt; font-weight:600;\">might</span><span style=\" font-size:12pt;\"> be smaller.<br/></span><span style=\" font-size:12pt; font-weight:600;\">MOBI conversion will be much slower.</span></p></body></html>", None))
|
||||
self.NoDitheringBox.setText(_translate("KCC", "PNG output", None))
|
||||
self.BorderBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt; font-weight:600; text-decoration: underline;\">Unchecked - Autodetection<br/></span><span style=\" font-size:12pt;\">Color of margins fill will be detected automatically.</span></p><p><span style=\" font-size:12pt; font-weight:600; text-decoration: underline;\">Indeterminate - White<br/></span><span style=\" font-size:12pt;\">Margins will be filled with white color.</span></p><p><span style=\" font-size:12pt; font-weight:600; text-decoration: underline;\">Checked - Black<br/></span><span style=\" font-size:12pt;\">Margins will be filled with black color.</span></p></body></html>", None))
|
||||
self.BorderBox.setText(_translate("KCC", "W/B margins", None))
|
||||
self.NoRotateBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Disable splitting and rotation.</span></p></body></html>", None))
|
||||
self.NoRotateBox.setText(_translate("KCC", "No split/rotate", None))
|
||||
self.DeviceBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Target device.</span></p></body></html>", None))
|
||||
self.FormatBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Output format.</span></p></body></html>", None))
|
||||
self.ConvertButton.setText(_translate("KCC", "Convert", None))
|
||||
self.DirectoryButton.setText(_translate("KCC", "Add directory", None))
|
||||
self.FileButton.setText(_translate("KCC", "Add file", None))
|
||||
self.ClearButton.setText(_translate("KCC", "Clear list", None))
|
||||
self.MangaBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Enable right-to-left reading.</span></p></body></html>", None))
|
||||
self.MangaBox.setText(_translate("KCC", "Manga mode", None))
|
||||
self.QualityBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\"font-size:12pt; font-weight:600; text-decoration: underline;\">Unchecked - Normal quality mode<br/></span><span style=\"font-size:12pt; font-style:italic;\">Use it when Panel View support is not needed.</span><span style=\"font-size:12pt; font-weight:600; text-decoration: underline;\"><br/></span><span style=\"font-size:12pt;\">- Maximum quality when zoom is not enabled.<br/>- Poor quality when zoom is enabled.<br/>- Lowest file size.</span></p><p><span style=\"font-size:12pt; font-weight:600; text-decoration: underline;\">Indeterminate - High quality mode<br/></span><span style=\"font-size:12pt; font-style:italic;\">Not zoomed image </span><span style=\"font-size:12pt; font-weight:600; font-style:italic;\">might </span><span style=\"font-size:12pt; font-style:italic;\">be a little blurry.</span><span style=\"font-size:12pt; font-weight:600; text-decoration: underline;\"><br/></span><span style=\"font-size:12pt;\">- Medium/High quality when zoom is not enabled.<br/>- Maximum quality when zoom is enabled.</span></p><p><span style=\"font-size:12pt; font-weight:600; text-decoration: underline;\">Checked - Ultra quality mode<br/></span><span style=\"font-size:12pt; font-style:italic;\">Maximum possible quality.</span><span style=\"font-size:12pt; font-weight:600; text-decoration: underline;\"><br/></span><span style=\"font-size:12pt;\">- Maximum quality when zoom is not enabled.<br/>- Maximum quality when zoom is enabled.<br/>- Very high file size.</span></p></body></html>", None))
|
||||
self.QualityBox.setText(_translate("KCC", "High/Ultra quality", None))
|
||||
self.RotateBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Disable page spliting.<br/>They will be rotated instead.</span></p></body></html>", None))
|
||||
self.RotateBox.setText(_translate("KCC", "Horizontal mode", None))
|
||||
self.BasicModeButton.setText(_translate("KCC", "Basic", None))
|
||||
self.AdvModeButton.setText(_translate("KCC", "Advanced", None))
|
||||
self.GammaLabel.setText(_translate("KCC", "Gamma: Auto", None))
|
||||
self.ColorBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Do not convert images to grayscale.</span></p></body></html>", None))
|
||||
self.ColorBox.setText(_translate("KCC", "Color mode", None))
|
||||
self.wLabel.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Resolution of target device.</span></p></body></html>", None))
|
||||
self.wLabel.setText(_translate("KCC", "Custom width: ", None))
|
||||
self.customWidth.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Resolution of target device.</span></p></body></html>", None))
|
||||
self.customWidth.setInputMask(_translate("KCC", "0000; ", None))
|
||||
self.hLabel.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Resolution of target device.</span></p></body></html>", None))
|
||||
self.hLabel.setText(_translate("KCC", "Custom height: ", None))
|
||||
self.customHeight.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Resolution of target device.</span></p></body></html>", None))
|
||||
self.customHeight.setInputMask(_translate("KCC", "0000; ", None))
|
||||
self.ActionBasic.setText(_translate("KCC", "Basic", None))
|
||||
self.ActionAdvanced.setText(_translate("KCC", "Advanced", None))
|
||||
|
||||
import KCC_rc
|
||||
@@ -1,4 +0,0 @@
|
||||
__version__ = '3.6'
|
||||
__license__ = 'ISC'
|
||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
@@ -1,114 +0,0 @@
|
||||
# Copyright (c) 2012-2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||
# Copyright (c) 2013 Pawel Jastrzebski <pawelj@vulturis.eu>
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for
|
||||
# any purpose with or without fee is hereby granted, provided that the
|
||||
# above copyright notice and this permission notice appear in all
|
||||
# copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
# AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
|
||||
# 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.
|
||||
#
|
||||
__license__ = 'ISC'
|
||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import os
|
||||
import zipfile
|
||||
import rarfile
|
||||
import locale
|
||||
from sys import platform
|
||||
from subprocess import STDOUT, PIPE
|
||||
try:
|
||||
#noinspection PyUnresolvedReferences
|
||||
from psutil import Popen
|
||||
except ImportError:
|
||||
print "ERROR: Psutil is not installed!"
|
||||
if platform.startswith('linux'):
|
||||
import Tkinter
|
||||
import tkMessageBox
|
||||
importRoot = Tkinter.Tk()
|
||||
importRoot.withdraw()
|
||||
tkMessageBox.showerror("KCC - Error", "Psutil is not installed!")
|
||||
exit(1)
|
||||
from shutil import move
|
||||
|
||||
|
||||
class CBxArchive:
|
||||
def __init__(self, origFileName):
|
||||
self.origFileName = origFileName
|
||||
if zipfile.is_zipfile(origFileName):
|
||||
self.compressor = 'zip'
|
||||
elif rarfile.is_rarfile(origFileName):
|
||||
self.compressor = 'rar'
|
||||
elif origFileName.endswith('.7z') or origFileName.endswith('.cb7'):
|
||||
self.compressor = '7z'
|
||||
else:
|
||||
self.compressor = None
|
||||
|
||||
def isCbxFile(self):
|
||||
return self.compressor is not None
|
||||
|
||||
def extractCBZ(self, targetdir):
|
||||
cbzFile = zipfile.ZipFile(self.origFileName)
|
||||
filelist = []
|
||||
for f in cbzFile.namelist():
|
||||
if f.startswith('__MACOSX') or f.endswith('.DS_Store') or f.endswith('thumbs.db'):
|
||||
pass # skip MacOS special files
|
||||
elif f.endswith('/'):
|
||||
try:
|
||||
os.makedirs(os.path.join(targetdir, f))
|
||||
except StandardError:
|
||||
pass # the dir exists so we are going to extract the images only.
|
||||
else:
|
||||
filelist.append(f)
|
||||
cbzFile.extractall(targetdir, filelist)
|
||||
|
||||
def extractCBR(self, targetdir):
|
||||
cbrFile = rarfile.RarFile(self.origFileName.encode(locale.getpreferredencoding()))
|
||||
filelist = []
|
||||
for f in cbrFile.namelist():
|
||||
if f.startswith('__MACOSX') or f.endswith('.DS_Store') or f.endswith('thumbs.db'):
|
||||
pass # skip MacOS special files
|
||||
elif f.endswith('/'):
|
||||
try:
|
||||
os.makedirs(os.path.join(targetdir, f))
|
||||
except StandardError:
|
||||
pass # the dir exists so we are going to extract the images only.
|
||||
else:
|
||||
filelist.append(f.encode(locale.getpreferredencoding()))
|
||||
cbrFile.extractall(targetdir, filelist)
|
||||
|
||||
def extractCB7(self, targetdir):
|
||||
output = Popen('7za x "' + self.origFileName.encode(locale.getpreferredencoding()) +
|
||||
'" -xr!__MACOSX -xr!.DS_Store -xr!thumbs.db -o"' + targetdir + '"',
|
||||
stdout=PIPE, stderr=STDOUT, shell=True)
|
||||
extracted = False
|
||||
for line in output.stdout:
|
||||
if "Everything is Ok" in line:
|
||||
extracted = True
|
||||
if not extracted:
|
||||
raise OSError
|
||||
|
||||
def extract(self, targetdir):
|
||||
print "\n" + targetdir + "\n"
|
||||
if self.compressor == 'rar':
|
||||
self.extractCBR(targetdir)
|
||||
elif self.compressor == 'zip':
|
||||
self.extractCBZ(targetdir)
|
||||
elif self.compressor == '7z':
|
||||
self.extractCB7(targetdir)
|
||||
adir = os.listdir(targetdir)
|
||||
if 'ComicInfo.xml' in adir:
|
||||
adir.remove('ComicInfo.xml')
|
||||
if len(adir) == 1 and os.path.isdir(os.path.join(targetdir, adir[0])):
|
||||
for f in os.listdir(os.path.join(targetdir, adir[0])):
|
||||
move(os.path.join(targetdir, adir[0], f), targetdir)
|
||||
os.rmdir(os.path.join(targetdir, adir[0]))
|
||||
return targetdir
|
||||
1060
kcc/comic2ebook.py
1060
kcc/comic2ebook.py
File diff suppressed because it is too large
Load Diff
@@ -1,292 +0,0 @@
|
||||
#!/usr/bin/env python2
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2012-2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||
# Copyright (c) 2013 Pawel Jastrzebski <pawelj@vulturis.eu>
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for
|
||||
# any purpose with or without fee is hereby granted, provided that the
|
||||
# above copyright notice and this permission notice appear in all
|
||||
# copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
# AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
|
||||
# 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.
|
||||
#
|
||||
__version__ = '3.6'
|
||||
__license__ = 'ISC'
|
||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import os
|
||||
import sys
|
||||
from shutil import rmtree, copytree, move
|
||||
from optparse import OptionParser, OptionGroup
|
||||
from multiprocessing import Pool, freeze_support
|
||||
try:
|
||||
#noinspection PyUnresolvedReferences
|
||||
from PIL import Image, ImageStat
|
||||
if tuple(map(int, ('2.2.1'.split(".")))) > tuple(map(int, (Image.PILLOW_VERSION.split(".")))):
|
||||
print "ERROR: Pillow 2.2.1 or newer is required!"
|
||||
if sys.platform.startswith('linux'):
|
||||
#noinspection PyUnresolvedReferences
|
||||
import Tkinter
|
||||
#noinspection PyUnresolvedReferences
|
||||
import tkMessageBox
|
||||
importRoot = Tkinter.Tk()
|
||||
importRoot.withdraw()
|
||||
tkMessageBox.showerror("KCC - Error", "Pillow 2.2.1 or newer is required!")
|
||||
exit(1)
|
||||
except ImportError:
|
||||
print "ERROR: Pillow is not installed!"
|
||||
if sys.platform.startswith('linux'):
|
||||
#noinspection PyUnresolvedReferences
|
||||
import Tkinter
|
||||
#noinspection PyUnresolvedReferences
|
||||
import tkMessageBox
|
||||
importRoot = Tkinter.Tk()
|
||||
importRoot.withdraw()
|
||||
tkMessageBox.showerror("KCC - Error", "Pillow 2.2.1 or newer is required!")
|
||||
exit(1)
|
||||
try:
|
||||
from PyQt4 import QtCore
|
||||
except ImportError:
|
||||
QtCore = None
|
||||
|
||||
|
||||
def getImageFileName(imgfile):
|
||||
filename = os.path.splitext(imgfile)
|
||||
if filename[0].startswith('.') or\
|
||||
(filename[1].lower() != '.png' and
|
||||
filename[1].lower() != '.jpg' and
|
||||
filename[1].lower() != '.gif' and
|
||||
filename[1].lower() != '.tif' and
|
||||
filename[1].lower() != '.tiff' and
|
||||
filename[1].lower() != '.bmp' and
|
||||
filename[1].lower() != '.jpeg'):
|
||||
return None
|
||||
return filename
|
||||
|
||||
|
||||
def sanitizePanelSize(panel, opt):
|
||||
newPanels = []
|
||||
if panel[2] > 8 * opt.height:
|
||||
diff = (panel[2] / 8)
|
||||
newPanels.append([panel[0], panel[1] - diff*7, diff])
|
||||
newPanels.append([panel[1] - diff*7, panel[1] - diff*6, diff])
|
||||
newPanels.append([panel[1] - diff*6, panel[1] - diff*5, diff])
|
||||
newPanels.append([panel[1] - diff*5, panel[1] - diff*4, diff])
|
||||
newPanels.append([panel[1] - diff*4, panel[1] - diff*3, diff])
|
||||
newPanels.append([panel[1] - diff*3, panel[1] - diff*2, diff])
|
||||
newPanels.append([panel[1] - diff*2, panel[1] - diff, diff])
|
||||
newPanels.append([panel[1] - diff, panel[1], diff])
|
||||
elif panel[2] > 4 * opt.height:
|
||||
diff = (panel[2] / 4)
|
||||
newPanels.append([panel[0], panel[1] - diff*3, diff])
|
||||
newPanels.append([panel[1] - diff*3, panel[1] - diff*2, diff])
|
||||
newPanels.append([panel[1] - diff*2, panel[1] - diff, diff])
|
||||
newPanels.append([panel[1] - diff, panel[1], diff])
|
||||
elif panel[2] > 2 * opt.height:
|
||||
newPanels.append([panel[0], panel[1] - (panel[2] / 2), (panel[2] / 2)])
|
||||
newPanels.append([panel[1] - (panel[2] / 2), panel[1], (panel[2] / 2)])
|
||||
else:
|
||||
newPanels = [panel]
|
||||
return newPanels
|
||||
|
||||
|
||||
def splitImage_tick(output):
|
||||
if output:
|
||||
splitWorkerOutput.append(output)
|
||||
splitWorkerPool.terminate()
|
||||
if GUI:
|
||||
GUI.emit(QtCore.SIGNAL("progressBarTick"))
|
||||
if not GUI.conversionAlive:
|
||||
splitWorkerPool.terminate()
|
||||
|
||||
|
||||
#noinspection PyUnboundLocalVariable
|
||||
def splitImage(work):
|
||||
try:
|
||||
path = work[0]
|
||||
name = work[1]
|
||||
opt = work[2]
|
||||
# Harcoded opttions
|
||||
threshold = 1.0
|
||||
delta = 15
|
||||
print ".",
|
||||
fileExpanded = os.path.splitext(name)
|
||||
filePath = os.path.join(path, name)
|
||||
# Detect corrupted files
|
||||
try:
|
||||
Image.open(filePath)
|
||||
except IOError:
|
||||
raise RuntimeError('Cannot read image file %s' % filePath)
|
||||
try:
|
||||
image = Image.open(filePath)
|
||||
image.verify()
|
||||
except:
|
||||
raise RuntimeError('Image file %s is corrupted' % filePath)
|
||||
try:
|
||||
image = Image.open(filePath)
|
||||
image.load()
|
||||
except:
|
||||
raise RuntimeError('Image file %s is corrupted' % filePath)
|
||||
image = Image.open(filePath)
|
||||
image = image.convert('RGB')
|
||||
widthImg, heightImg = image.size
|
||||
if heightImg > opt.height:
|
||||
if opt.debug:
|
||||
from PIL import ImageDraw
|
||||
debugImage = Image.open(filePath)
|
||||
draw = ImageDraw.Draw(debugImage)
|
||||
|
||||
# Find panels
|
||||
y1 = 0
|
||||
y2 = 15
|
||||
panels = []
|
||||
while y2 < heightImg:
|
||||
while ImageStat.Stat(image.crop([0, y1, widthImg, y2])).var[0] < threshold and y2 < heightImg:
|
||||
y2 += delta
|
||||
y2 -= delta
|
||||
y1Temp = y2
|
||||
y1 = y2 + delta
|
||||
y2 = y1 + delta
|
||||
while ImageStat.Stat(image.crop([0, y1, widthImg, y2])).var[0] >= threshold and y2 < heightImg:
|
||||
y1 += delta
|
||||
y2 += delta
|
||||
if y1 + delta >= heightImg:
|
||||
y1 = heightImg - 1
|
||||
y2Temp = y1
|
||||
if opt.debug:
|
||||
draw.line([(0, y1Temp), (widthImg, y1Temp)], fill=(0, 255, 0))
|
||||
draw.line([(0, y2Temp), (widthImg, y2Temp)], fill=(255, 0, 0))
|
||||
panelHeight = y2Temp - y1Temp
|
||||
if panelHeight > delta:
|
||||
# Panels that can't be cut nicely will be forcefully splitted
|
||||
panelsCleaned = sanitizePanelSize([y1Temp, y2Temp, panelHeight], opt)
|
||||
for panel in panelsCleaned:
|
||||
panels.append(panel)
|
||||
if opt.debug:
|
||||
debugImage.save(os.path.join(path, fileExpanded[0] + '-debug.png'), 'PNG')
|
||||
|
||||
# Create virtual pages
|
||||
pages = []
|
||||
currentPage = []
|
||||
pageLeft = opt.height
|
||||
panelNumber = 0
|
||||
for panel in panels:
|
||||
if pageLeft - panel[2] > 0:
|
||||
pageLeft -= panel[2]
|
||||
currentPage.append(panelNumber)
|
||||
panelNumber += 1
|
||||
else:
|
||||
if len(currentPage) > 0:
|
||||
pages.append(currentPage)
|
||||
pageLeft = opt.height - panel[2]
|
||||
currentPage = [panelNumber]
|
||||
panelNumber += 1
|
||||
if len(currentPage) > 0:
|
||||
pages.append(currentPage)
|
||||
|
||||
# Create pages
|
||||
pageNumber = 1
|
||||
for page in pages:
|
||||
pageHeight = 0
|
||||
targetHeight = 0
|
||||
for panel in page:
|
||||
pageHeight += panels[panel][2]
|
||||
if pageHeight > delta:
|
||||
newPage = Image.new('RGB', (widthImg, pageHeight))
|
||||
for panel in page:
|
||||
panelImg = image.crop([0, panels[panel][0], widthImg, panels[panel][1]])
|
||||
newPage.paste(panelImg, (0, targetHeight))
|
||||
targetHeight += panels[panel][2]
|
||||
newPage.save(os.path.join(path, fileExpanded[0] + '-' +
|
||||
str(pageNumber) + '.png'), 'PNG')
|
||||
pageNumber += 1
|
||||
os.remove(filePath)
|
||||
except StandardError:
|
||||
return str(sys.exc_info()[1])
|
||||
|
||||
|
||||
def Copyright():
|
||||
print ('comic2panel v%(__version__)s. '
|
||||
'Written 2013 by Ciro Mattia Gonano and Pawel Jastrzebski.' % globals())
|
||||
|
||||
|
||||
def main(argv=None, qtGUI=None):
|
||||
global options, GUI, splitWorkerPool, splitWorkerOutput
|
||||
parser = OptionParser(usage="Usage: %prog [options] comic_folder", add_help_option=False)
|
||||
mainOptions = OptionGroup(parser, "MANDATORY")
|
||||
otherOptions = OptionGroup(parser, "OTHER")
|
||||
mainOptions.add_option("-y", "--height", type="int", dest="height", default=0,
|
||||
help="Height of the target device screen")
|
||||
mainOptions.add_option("-i", "--in-place", action="store_true", dest="inPlace", default=False,
|
||||
help="Overwrite source directory")
|
||||
otherOptions.add_option("-d", "--debug", action="store_true", dest="debug", default=False,
|
||||
help="Create debug file for every splitted image")
|
||||
otherOptions.add_option("-h", "--help", action="help",
|
||||
help="Show this help message and exit")
|
||||
parser.add_option_group(mainOptions)
|
||||
parser.add_option_group(otherOptions)
|
||||
options, args = parser.parse_args(argv)
|
||||
if qtGUI:
|
||||
GUI = qtGUI
|
||||
else:
|
||||
GUI = None
|
||||
if len(args) != 1:
|
||||
parser.print_help()
|
||||
return
|
||||
if options.height > 0:
|
||||
options.sourceDir = args[0]
|
||||
options.targetDir = args[0] + "-Splitted"
|
||||
print "\nSplitting images..."
|
||||
if os.path.isdir(options.sourceDir):
|
||||
rmtree(options.targetDir, True)
|
||||
copytree(options.sourceDir, options.targetDir)
|
||||
work = []
|
||||
pagenumber = 0
|
||||
splitWorkerOutput = []
|
||||
splitWorkerPool = Pool()
|
||||
for root, dirs, files in os.walk(options.targetDir, False):
|
||||
for name in files:
|
||||
if getImageFileName(name) is not None:
|
||||
pagenumber += 1
|
||||
work.append([root, name, options])
|
||||
else:
|
||||
os.remove(os.path.join(root, name))
|
||||
if GUI:
|
||||
GUI.emit(QtCore.SIGNAL("progressBarTick"), pagenumber)
|
||||
if len(work) > 0:
|
||||
for i in work:
|
||||
splitWorkerPool.apply_async(func=splitImage, args=(i, ), callback=splitImage_tick)
|
||||
splitWorkerPool.close()
|
||||
splitWorkerPool.join()
|
||||
if GUI and not GUI.conversionAlive:
|
||||
rmtree(options.targetDir, True)
|
||||
raise UserWarning("Conversion interrupted.")
|
||||
if len(splitWorkerOutput) > 0:
|
||||
rmtree(options.targetDir, True)
|
||||
raise RuntimeError("One of workers crashed. Cause: " + splitWorkerOutput[0])
|
||||
if options.inPlace:
|
||||
rmtree(options.sourceDir)
|
||||
move(options.targetDir, options.sourceDir)
|
||||
else:
|
||||
rmtree(options.targetDir, True)
|
||||
raise UserWarning("Source directory is empty.")
|
||||
else:
|
||||
raise UserWarning("Provided path is not a directory.")
|
||||
else:
|
||||
raise UserWarning("Target height is not set.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
freeze_support()
|
||||
Copyright()
|
||||
main(sys.argv[1:])
|
||||
sys.exit(0)
|
||||
536
kcc/image.py
536
kcc/image.py
@@ -1,536 +0,0 @@
|
||||
# Copyright (C) 2010 Alex Yatskov
|
||||
# Copyright (C) 2011 Stanislav (proDOOMman) Kosolapov <prodoomman@gmail.com>
|
||||
# Copyright (C) 2012-2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||
# Copyright (C) 2013 Pawel Jastrzebski <pawelj@vulturis.eu>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
__license__ = 'ISC'
|
||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import os
|
||||
from sys import platform
|
||||
try:
|
||||
# noinspection PyUnresolvedReferences
|
||||
from PIL import Image, ImageOps, ImageStat, ImageChops
|
||||
if tuple(map(int, ('2.2.1'.split(".")))) > tuple(map(int, (Image.PILLOW_VERSION.split(".")))):
|
||||
print "ERROR: Pillow 2.2.1 or newer is required!"
|
||||
if platform.startswith('linux'):
|
||||
#noinspection PyUnresolvedReferences
|
||||
import Tkinter
|
||||
#noinspection PyUnresolvedReferences
|
||||
import tkMessageBox
|
||||
importRoot = Tkinter.Tk()
|
||||
importRoot.withdraw()
|
||||
tkMessageBox.showerror("KCC - Error", "Pillow 2.2.1 or newer is required!")
|
||||
exit(1)
|
||||
except ImportError:
|
||||
print "ERROR: Pillow is not installed!"
|
||||
if platform.startswith('linux'):
|
||||
#noinspection PyUnresolvedReferences
|
||||
import Tkinter
|
||||
#noinspection PyUnresolvedReferences
|
||||
import tkMessageBox
|
||||
importRoot = Tkinter.Tk()
|
||||
importRoot.withdraw()
|
||||
tkMessageBox.showerror("KCC - Error", "Pillow 2.2.1 or newer is required!")
|
||||
exit(1)
|
||||
|
||||
|
||||
class ProfileData:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
Palette4 = [
|
||||
0x00, 0x00, 0x00,
|
||||
0x55, 0x55, 0x55,
|
||||
0xaa, 0xaa, 0xaa,
|
||||
0xff, 0xff, 0xff
|
||||
]
|
||||
|
||||
Palette15 = [
|
||||
0x00, 0x00, 0x00,
|
||||
0x11, 0x11, 0x11,
|
||||
0x22, 0x22, 0x22,
|
||||
0x33, 0x33, 0x33,
|
||||
0x44, 0x44, 0x44,
|
||||
0x55, 0x55, 0x55,
|
||||
0x66, 0x66, 0x66,
|
||||
0x77, 0x77, 0x77,
|
||||
0x88, 0x88, 0x88,
|
||||
0x99, 0x99, 0x99,
|
||||
0xaa, 0xaa, 0xaa,
|
||||
0xbb, 0xbb, 0xbb,
|
||||
0xcc, 0xcc, 0xcc,
|
||||
0xdd, 0xdd, 0xdd,
|
||||
0xff, 0xff, 0xff,
|
||||
]
|
||||
|
||||
Palette16 = [
|
||||
0x00, 0x00, 0x00,
|
||||
0x11, 0x11, 0x11,
|
||||
0x22, 0x22, 0x22,
|
||||
0x33, 0x33, 0x33,
|
||||
0x44, 0x44, 0x44,
|
||||
0x55, 0x55, 0x55,
|
||||
0x66, 0x66, 0x66,
|
||||
0x77, 0x77, 0x77,
|
||||
0x88, 0x88, 0x88,
|
||||
0x99, 0x99, 0x99,
|
||||
0xaa, 0xaa, 0xaa,
|
||||
0xbb, 0xbb, 0xbb,
|
||||
0xcc, 0xcc, 0xcc,
|
||||
0xdd, 0xdd, 0xdd,
|
||||
0xee, 0xee, 0xee,
|
||||
0xff, 0xff, 0xff,
|
||||
]
|
||||
|
||||
PalleteNull = [
|
||||
]
|
||||
|
||||
Profiles = {
|
||||
'K1': ("Kindle 1", (600, 670), Palette4, 1.8, (900, 1005)),
|
||||
'K2': ("Kindle 2", (600, 670), Palette15, 1.8, (900, 1005)),
|
||||
'K345': ("Kindle", (600, 800), Palette16, 1.8, (900, 1200)),
|
||||
'KHD': ("Kindle Paperwhite", (758, 1024), Palette16, 1.8, (1137, 1536)),
|
||||
'KDX': ("Kindle DX/DXG", (824, 1000), Palette16, 1.8, (1236, 1500)),
|
||||
'KF': ("Kindle Fire", (600, 1024), PalleteNull, 1.0, (900, 1536)),
|
||||
'KFHD': ("K. Fire HD 7\"", (800, 1280), PalleteNull, 1.0, (1200, 1920)),
|
||||
'KFHD8': ("K. Fire HD 8.9\"", (1200, 1920), PalleteNull, 1.0, (1800, 2880)),
|
||||
'KFHDX': ("K. Fire HDX 7\"", (1200, 1920), PalleteNull, 1.0, (1800, 2880)),
|
||||
'KFHDX8': ("K. Fire HDX 8.9\"", (1600, 2560), PalleteNull, 1.0, (2400, 3840)),
|
||||
'KFA': ("Kindle for Android", (0, 0), PalleteNull, 1.0, (0, 0)),
|
||||
'OTHER': ("Other", (0, 0), Palette16, 1.8, (0, 0)),
|
||||
}
|
||||
|
||||
ProfileLabels = {
|
||||
"Kindle 1": 'K1',
|
||||
"Kindle 2": 'K2',
|
||||
"Kindle": 'K345',
|
||||
"Kindle Paperwhite": 'KHD',
|
||||
"Kindle DX/DXG": 'KDX',
|
||||
"Kindle Fire": 'KF',
|
||||
"K. Fire HD 7\"": 'KFHD',
|
||||
"K. Fire HD 8.9\"": 'KFHD8',
|
||||
"K. Fire HDX 7\"": 'KFHDX',
|
||||
"K. Fire HDX 8.9\"": 'KFHDX8',
|
||||
"Kindle for Android": 'KFA',
|
||||
"Other": 'OTHER'
|
||||
}
|
||||
|
||||
ProfileLabelsGUI = [
|
||||
"Kindle Paperwhite",
|
||||
"Kindle",
|
||||
"Separator",
|
||||
"K. Fire HD 7\"",
|
||||
"K. Fire HD 8.9\"",
|
||||
"K. Fire HDX 7\"",
|
||||
"K. Fire HDX 8.9\"",
|
||||
"Separator",
|
||||
"Kindle for Android",
|
||||
"Other",
|
||||
"Separator",
|
||||
"Kindle 1",
|
||||
"Kindle 2",
|
||||
"Kindle DX/DXG",
|
||||
"Kindle Fire"
|
||||
]
|
||||
|
||||
|
||||
class ComicPage:
|
||||
def __init__(self, source, device, fill=None):
|
||||
try:
|
||||
self.profile_label, self.size, self.palette, self.gamma, self.panelviewsize = device
|
||||
except KeyError:
|
||||
raise RuntimeError('Unexpected output device %s' % device)
|
||||
# Detect corrupted files - Phase 2
|
||||
try:
|
||||
self.origFileName = source
|
||||
self.filename = os.path.basename(self.origFileName)
|
||||
self.image = Image.open(source)
|
||||
except IOError:
|
||||
raise RuntimeError('Cannot read image file %s' % source)
|
||||
# Detect corrupted files - Phase 3
|
||||
try:
|
||||
self.image = Image.open(source)
|
||||
self.image.verify()
|
||||
except:
|
||||
raise RuntimeError('Image file %s is corrupted' % source)
|
||||
# Detect corrupted files - Phase 4
|
||||
try:
|
||||
self.image = Image.open(source)
|
||||
self.image.load()
|
||||
except:
|
||||
raise RuntimeError('Image file %s is corrupted' % source)
|
||||
self.image = Image.open(source)
|
||||
self.image = self.image.convert('RGB')
|
||||
self.rotated = None
|
||||
self.border = None
|
||||
self.noHPV = None
|
||||
self.noVPV = None
|
||||
if fill:
|
||||
self.fill = fill
|
||||
else:
|
||||
self.fill = None
|
||||
|
||||
def saveToDir(self, targetdir, forcepng, color, wipe):
|
||||
try:
|
||||
suffix = ""
|
||||
if not color and not forcepng:
|
||||
self.image = self.image.convert('L')
|
||||
if self.rotated:
|
||||
suffix += "_kccrot"
|
||||
if wipe:
|
||||
os.remove(os.path.join(targetdir, self.filename))
|
||||
else:
|
||||
suffix += "_kcchq"
|
||||
if self.noHPV:
|
||||
suffix += "_kccnh"
|
||||
if self.noVPV:
|
||||
suffix += "_kccnv"
|
||||
if self.border:
|
||||
suffix += "_kccxl" + str(self.border[0]) + "_kccyu" + str(self.border[1]) + "_kccxr" +\
|
||||
str(self.border[2]) + "_kccyd" + str(self.border[3])
|
||||
if forcepng:
|
||||
self.image.save(os.path.join(targetdir, os.path.splitext(self.filename)[0] + suffix + ".png"), "PNG",
|
||||
optimize=1)
|
||||
else:
|
||||
self.image.save(os.path.join(targetdir, os.path.splitext(self.filename)[0] + suffix + ".jpg"), "JPEG",
|
||||
optimize=1)
|
||||
except IOError as e:
|
||||
raise RuntimeError('Cannot write image in directory %s: %s' % (targetdir, e))
|
||||
|
||||
def optimizeImage(self, gamma):
|
||||
if gamma < 0.1:
|
||||
gamma = self.gamma
|
||||
if self.gamma != 1.0 and self.isImageColor(self.image):
|
||||
gamma = 1.0
|
||||
if gamma == 1.0:
|
||||
self.image = ImageOps.autocontrast(self.image)
|
||||
else:
|
||||
self.image = ImageOps.autocontrast(Image.eval(self.image, lambda a: 255 * (a / 255.) ** gamma))
|
||||
|
||||
def quantizeImage(self):
|
||||
colors = len(self.palette) / 3
|
||||
if colors < 256:
|
||||
self.palette += self.palette[:3] * (256 - colors)
|
||||
palImg = Image.new('P', (1, 1))
|
||||
palImg.putpalette(self.palette)
|
||||
self.image = self.image.convert('L')
|
||||
self.image = self.image.convert('RGB')
|
||||
# Quantize is deprecated but new function call it internally anyway...
|
||||
self.image = self.image.quantize(palette=palImg)
|
||||
|
||||
def calculateBorderPercent(self, x, img, isWidth):
|
||||
if isWidth:
|
||||
return int(round(float(x)/float(img.image.size[0]), 4) * 10000 * 1.5)
|
||||
else:
|
||||
return int(round(float(x)/float(img.image.size[1]), 4) * 10000 * 1.5)
|
||||
|
||||
def calculateBorder(self, sourceImage):
|
||||
if self.fill == 'white':
|
||||
border = ImageOps.invert(sourceImage.image).getbbox()
|
||||
else:
|
||||
border = sourceImage.image.getbbox()
|
||||
if border is not None:
|
||||
self.border = [self.calculateBorderPercent(border[0], sourceImage, True),
|
||||
self.calculateBorderPercent(border[1], sourceImage, False),
|
||||
self.calculateBorderPercent((sourceImage.image.size[0] - border[2]), sourceImage, True),
|
||||
self.calculateBorderPercent((sourceImage.image.size[1] - border[3]), sourceImage, False)]
|
||||
if int((border[2] - border[0]) * 1.5) < self.size[0]:
|
||||
self.noHPV = True
|
||||
self.border[0] /= 2
|
||||
if int((border[3] - border[1]) * 1.5) < self.size[1]:
|
||||
self.noVPV = True
|
||||
self.border[1] /= 2
|
||||
else:
|
||||
self.border = [0, 0, 0, 0]
|
||||
self.noHPV = True
|
||||
self.noVPV = True
|
||||
|
||||
def resizeImage(self, upscale=False, stretch=False, bordersColor=None, qualityMode=0):
|
||||
if bordersColor:
|
||||
fill = bordersColor
|
||||
else:
|
||||
fill = self.fill
|
||||
# Set target size
|
||||
if qualityMode == 0:
|
||||
size = (self.size[0], self.size[1])
|
||||
else:
|
||||
size = (self.panelviewsize[0], self.panelviewsize[1])
|
||||
# If image is smaller than device resolution and upscale is off - Just expand it by adding margins
|
||||
if self.image.size[0] <= self.size[0] and self.image.size[1] <= self.size[1] and not upscale:
|
||||
borderw = (self.size[0] - self.image.size[0]) / 2
|
||||
borderh = (self.size[1] - self.image.size[1]) / 2
|
||||
self.image = ImageOps.expand(self.image, border=(borderw, borderh), fill=fill)
|
||||
return self.image
|
||||
# If stretching is on - Resize without other considerations
|
||||
if stretch:
|
||||
if self.image.size[0] <= size[0] and self.image.size[1] <= size[1]:
|
||||
method = Image.BICUBIC
|
||||
else:
|
||||
method = Image.ANTIALIAS
|
||||
self.image = self.image.resize(size, method)
|
||||
return self.image
|
||||
# Otherwise - Upscale/Downscale
|
||||
ratioDev = float(self.size[0]) / float(self.size[1])
|
||||
if (float(self.image.size[0]) / float(self.image.size[1])) < ratioDev:
|
||||
diff = int(self.image.size[1] * ratioDev) - self.image.size[0]
|
||||
self.image = ImageOps.expand(self.image, border=(diff / 2, 0), fill=fill)
|
||||
elif (float(self.image.size[0]) / float(self.image.size[1])) > ratioDev:
|
||||
diff = int(self.image.size[0] / ratioDev) - self.image.size[1]
|
||||
self.image = ImageOps.expand(self.image, border=(0, diff / 2), fill=fill)
|
||||
if self.image.size[0] <= size[0] and self.image.size[1] <= size[1]:
|
||||
method = Image.BICUBIC
|
||||
else:
|
||||
method = Image.ANTIALIAS
|
||||
self.image = ImageOps.fit(self.image, size, method=method, centering=(0.5, 0.5))
|
||||
return self.image
|
||||
|
||||
def splitPage(self, targetdir, righttoleft=False, rotate=False):
|
||||
width, height = self.image.size
|
||||
dstwidth, dstheight = self.size
|
||||
# Only split if origin is not oriented the same as target
|
||||
if (width > height) != (dstwidth > dstheight):
|
||||
if rotate:
|
||||
self.image = self.image.rotate(90)
|
||||
self.rotated = True
|
||||
return None
|
||||
else:
|
||||
self.rotated = False
|
||||
if width > height:
|
||||
# Source is landscape, so split by the width
|
||||
leftbox = (0, 0, width / 2, height)
|
||||
rightbox = (width / 2, 0, width, height)
|
||||
else:
|
||||
# Source is portrait and target is landscape, so split by the height
|
||||
leftbox = (0, 0, width, height / 2)
|
||||
rightbox = (0, height / 2, width, height)
|
||||
filename = os.path.splitext(self.filename)
|
||||
fileone = targetdir + '/' + filename[0] + '_kcca' + filename[1]
|
||||
filetwo = targetdir + '/' + filename[0] + '_kccb' + filename[1]
|
||||
try:
|
||||
if righttoleft:
|
||||
pageone = self.image.crop(rightbox)
|
||||
pagetwo = self.image.crop(leftbox)
|
||||
else:
|
||||
pageone = self.image.crop(leftbox)
|
||||
pagetwo = self.image.crop(rightbox)
|
||||
pageone.save(fileone)
|
||||
pagetwo.save(filetwo)
|
||||
os.remove(self.origFileName)
|
||||
except IOError as e:
|
||||
raise RuntimeError('Cannot write image in directory %s: %s' % (targetdir, e))
|
||||
return fileone, filetwo
|
||||
else:
|
||||
self.rotated = False
|
||||
return None
|
||||
|
||||
def cutPageNumber(self):
|
||||
if ImageChops.invert(self.image).getbbox() is not None:
|
||||
widthImg, heightImg = self.image.size
|
||||
delta = 2
|
||||
diff = delta
|
||||
fixedThreshold = 5
|
||||
if ImageStat.Stat(self.image).var[0] < 2 * fixedThreshold:
|
||||
return self.image
|
||||
while ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg))).var[0] < fixedThreshold\
|
||||
and diff < heightImg:
|
||||
diff += delta
|
||||
diff -= delta
|
||||
pageNumberCut1 = diff
|
||||
if diff < delta:
|
||||
diff = delta
|
||||
oldStat = ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg))).var[0]
|
||||
diff += delta
|
||||
while ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg))).var[0] - oldStat > 0\
|
||||
and diff < heightImg / 4:
|
||||
oldStat = ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg))).var[0]
|
||||
diff += delta
|
||||
diff -= delta
|
||||
pageNumberCut2 = diff
|
||||
diff += delta
|
||||
oldStat = ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg,
|
||||
heightImg - pageNumberCut2))).var[0]
|
||||
while ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg - pageNumberCut2))).var[0]\
|
||||
< fixedThreshold + oldStat and diff < heightImg / 4:
|
||||
diff += delta
|
||||
diff -= delta
|
||||
pageNumberCut3 = diff
|
||||
delta = 5
|
||||
diff = delta
|
||||
while ImageStat.Stat(self.image.crop((0, heightImg - pageNumberCut2, diff, heightImg))).var[0]\
|
||||
< fixedThreshold and diff < widthImg:
|
||||
diff += delta
|
||||
diff -= delta
|
||||
pageNumberX1 = diff
|
||||
diff = delta
|
||||
while ImageStat.Stat(self.image.crop((widthImg - diff, heightImg - pageNumberCut2,
|
||||
widthImg, heightImg))).var[0] < fixedThreshold and diff < widthImg:
|
||||
diff += delta
|
||||
diff -= delta
|
||||
pageNumberX2 = widthImg - diff
|
||||
if pageNumberCut3 - pageNumberCut1 > 2 * delta\
|
||||
and float(pageNumberX2 - pageNumberX1) / float(pageNumberCut2 - pageNumberCut1) <= 9.0\
|
||||
and ImageStat.Stat(self.image.crop((0, heightImg - pageNumberCut3, widthImg, heightImg))).var[0]\
|
||||
/ ImageStat.Stat(self.image).var[0] < 0.1\
|
||||
and pageNumberCut3 < heightImg / 4 - delta:
|
||||
diff = pageNumberCut3
|
||||
else:
|
||||
diff = pageNumberCut1
|
||||
self.image = self.image.crop((0, 0, widthImg, heightImg - diff))
|
||||
return self.image
|
||||
|
||||
def cropWhiteSpace(self, threshold):
|
||||
if ImageChops.invert(self.image).getbbox() is not None:
|
||||
widthImg, heightImg = self.image.size
|
||||
delta = 10
|
||||
diff = delta
|
||||
# top
|
||||
while ImageStat.Stat(self.image.crop((0, 0, widthImg, diff))).var[0] < threshold and diff < heightImg:
|
||||
diff += delta
|
||||
diff -= delta
|
||||
self.image = self.image.crop((0, diff, widthImg, heightImg))
|
||||
widthImg, heightImg = self.image.size
|
||||
diff = delta
|
||||
# left
|
||||
while ImageStat.Stat(self.image.crop((0, 0, diff, heightImg))).var[0] < threshold and diff < widthImg:
|
||||
diff += delta
|
||||
diff -= delta
|
||||
self.image = self.image.crop((diff, 0, widthImg, heightImg))
|
||||
widthImg, heightImg = self.image.size
|
||||
diff = delta
|
||||
# down
|
||||
while ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg))).var[0] < threshold\
|
||||
and diff < heightImg:
|
||||
diff += delta
|
||||
diff -= delta
|
||||
self.image = self.image.crop((0, 0, widthImg, heightImg - diff))
|
||||
widthImg, heightImg = self.image.size
|
||||
diff = delta
|
||||
# right
|
||||
while ImageStat.Stat(self.image.crop((widthImg - diff, 0, widthImg, heightImg))).var[0] < threshold\
|
||||
and diff < widthImg:
|
||||
diff += delta
|
||||
diff -= delta
|
||||
self.image = self.image.crop((0, 0, widthImg - diff, heightImg))
|
||||
return self.image
|
||||
|
||||
def getImageHistogram(self, image, new=True):
|
||||
histogram = image.histogram()
|
||||
RBGW = []
|
||||
pixelCount = 0
|
||||
for i in range(256):
|
||||
pixelCount += histogram[i] + histogram[256 + i] + histogram[512 + i]
|
||||
RBGW.append(histogram[i] + histogram[256 + i] + histogram[512 + i])
|
||||
white = 0
|
||||
black = 0
|
||||
for i in range(251, 256):
|
||||
white += RBGW[i]
|
||||
for i in range(5):
|
||||
black += RBGW[i]
|
||||
if new:
|
||||
if black > 0 and white == 0:
|
||||
return 1
|
||||
elif white > 0 and black == 0:
|
||||
return -1
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
if black > white and black > pixelCount*0.5:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def getImageFill(self, isWebToon):
|
||||
if isWebToon:
|
||||
fill = 0
|
||||
fill += self.getImageHistogram(self.image.crop((0, 0, self.image.size[0], 5)), False)
|
||||
fill += self.getImageHistogram(self.image.crop((0, self.image.size[1]-5, self.image.size[0],
|
||||
self.image.size[1])), False)
|
||||
if fill == 2:
|
||||
self.fill = 'black'
|
||||
elif fill == 0:
|
||||
self.fill = 'white'
|
||||
else:
|
||||
fill = 0
|
||||
fill += self.getImageHistogram(self.image.crop((0, 0, 5, 5)), False)
|
||||
fill += self.getImageHistogram(self.image.crop((self.image.size[0]-5, 0, self.image.size[0], 5)), False)
|
||||
fill += self.getImageHistogram(self.image.crop((0, self.image.size[1]-5, 5, self.image.size[1])), False)
|
||||
fill += self.getImageHistogram(self.image.crop((self.image.size[0]-5, self.image.size[1]-5,
|
||||
self.image.size[0], self.image.size[1])), False)
|
||||
if fill > 1:
|
||||
self.fill = 'black'
|
||||
else:
|
||||
self.fill = 'white'
|
||||
else:
|
||||
fill = 0
|
||||
# Search fom horizontal solid lines
|
||||
startY = 0
|
||||
stopY = 3
|
||||
searching = True
|
||||
while stopY <= self.image.size[1]:
|
||||
checkSolid = self.getImageHistogram(self.image.crop((0, startY, self.image.size[0], stopY)))
|
||||
if checkSolid:
|
||||
fill += checkSolid
|
||||
startY = stopY + 1
|
||||
stopY = startY + 3
|
||||
if stopY > self.image.size[1] and searching:
|
||||
startY = self.image.size[1] - 3
|
||||
stopY = self.image.size[1]
|
||||
searching = False
|
||||
# Search fom vertical solid lines
|
||||
startX = 0
|
||||
stopX = 3
|
||||
searching = True
|
||||
while stopX <= self.image.size[0]:
|
||||
checkSolid = self.getImageHistogram(self.image.crop((startX, 0, stopX, self.image.size[1])))
|
||||
if checkSolid:
|
||||
fill += checkSolid
|
||||
startX = stopX + 1
|
||||
stopX = startX + 3
|
||||
if stopX > self.image.size[0] and searching:
|
||||
startX = self.image.size[0] - 3
|
||||
stopX = self.image.size[0]
|
||||
searching = False
|
||||
if fill > 0:
|
||||
self.fill = 'black'
|
||||
else:
|
||||
self.fill = 'white'
|
||||
|
||||
def isImageColor(self, image):
|
||||
v = ImageStat.Stat(image).var
|
||||
isMonochromatic = reduce(lambda x, y: x and y < 0.005, v, True)
|
||||
if isMonochromatic:
|
||||
# Monochromatic
|
||||
return False
|
||||
else:
|
||||
if len(v) == 3:
|
||||
maxmin = abs(max(v) - min(v))
|
||||
if maxmin > 1000:
|
||||
# Color
|
||||
return True
|
||||
elif maxmin > 100:
|
||||
# Probably color
|
||||
return True
|
||||
else:
|
||||
# Grayscale
|
||||
return False
|
||||
elif len(v) == 1:
|
||||
# Black and white
|
||||
return False
|
||||
else:
|
||||
# Detection failed
|
||||
return False
|
||||
@@ -1,384 +0,0 @@
|
||||
# Based on initial version of KindleUnpack. Copyright (C) 2009 Charles M. Hannum <root@ihack.net>
|
||||
# Improvements Copyright (C) 2009-2012 P. Durrant, K. Hendricks, S. Siebert, fandrieu, DiapDealer, nickredding
|
||||
# Copyright (C) 2013 Pawel Jastrzebski <pawelj@vulturis.eu>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
__license__ = 'ISC'
|
||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import struct
|
||||
# from uuid import uuid4
|
||||
|
||||
# important pdb header offsets
|
||||
unique_id_seed = 68
|
||||
number_of_pdb_records = 76
|
||||
|
||||
# important palmdoc header offsets
|
||||
book_length = 4
|
||||
book_record_count = 8
|
||||
first_pdb_record = 78
|
||||
|
||||
# important rec0 offsets
|
||||
length_of_book = 4
|
||||
mobi_header_base = 16
|
||||
mobi_header_length = 20
|
||||
mobi_type = 24
|
||||
mobi_version = 36
|
||||
first_non_text = 80
|
||||
title_offset = 84
|
||||
first_image_record = 108
|
||||
first_content_index = 192
|
||||
last_content_index = 194
|
||||
kf8_last_content_index = 192 # for KF8 mobi headers
|
||||
fcis_index = 200
|
||||
flis_index = 208
|
||||
srcs_index = 224
|
||||
srcs_count = 228
|
||||
primary_index = 244
|
||||
datp_index = 256
|
||||
huffoff = 112
|
||||
hufftbloff = 120
|
||||
|
||||
|
||||
def getint(datain, ofs, sz='L'):
|
||||
i, = struct.unpack_from('>'+sz, datain, ofs)
|
||||
return i
|
||||
|
||||
|
||||
def writeint(datain, ofs, n, length='L'):
|
||||
if length == 'L':
|
||||
return datain[:ofs]+struct.pack('>L', n)+datain[ofs+4:]
|
||||
else:
|
||||
return datain[:ofs]+struct.pack('>H', n)+datain[ofs+2:]
|
||||
|
||||
|
||||
def getsecaddr(datain, secno):
|
||||
nsec = getint(datain, number_of_pdb_records, 'H')
|
||||
assert secno >= 0 & secno < nsec, 'secno %d out of range (nsec=%d)' % (secno, nsec)
|
||||
secstart = getint(datain, first_pdb_record+secno*8)
|
||||
if secno == nsec-1:
|
||||
secend = len(datain)
|
||||
else:
|
||||
secend = getint(datain, first_pdb_record+(secno+1)*8)
|
||||
return secstart, secend
|
||||
|
||||
|
||||
def readsection(datain, secno):
|
||||
secstart, secend = getsecaddr(datain, secno)
|
||||
return datain[secstart:secend]
|
||||
|
||||
|
||||
def writesection(datain, secno, secdata): # overwrite, accounting for different length
|
||||
dataout = deletesectionrange(datain, secno, secno)
|
||||
return insertsection(dataout, secno, secdata)
|
||||
|
||||
|
||||
def nullsection(datain, secno): # make it zero-length without deleting it
|
||||
datalst = []
|
||||
nsec = getint(datain, number_of_pdb_records, 'H')
|
||||
secstart, secend = getsecaddr(datain, secno)
|
||||
zerosecstart, zerosecend = getsecaddr(datain, 0)
|
||||
dif = secend-secstart
|
||||
datalst.append(datain[:first_pdb_record])
|
||||
for i in range(0, secno+1):
|
||||
ofs, flgval = struct.unpack_from('>2L', datain, first_pdb_record+i*8)
|
||||
datalst.append(struct.pack('>L', ofs) + struct.pack('>L', flgval))
|
||||
for i in range(secno+1, nsec):
|
||||
ofs, flgval = struct.unpack_from('>2L', datain, first_pdb_record+i*8)
|
||||
ofs -= dif
|
||||
datalst.append(struct.pack('>L', ofs) + struct.pack('>L', flgval))
|
||||
lpad = zerosecstart - (first_pdb_record + 8*nsec)
|
||||
if lpad > 0:
|
||||
datalst.append('\0' * lpad)
|
||||
datalst.append(datain[zerosecstart: secstart])
|
||||
datalst.append(datain[secend:])
|
||||
dataout = "".join(datalst)
|
||||
return dataout
|
||||
|
||||
|
||||
def deletesectionrange(datain, firstsec, lastsec): # delete a range of sections
|
||||
datalst = []
|
||||
firstsecstart, firstsecend = getsecaddr(datain, firstsec)
|
||||
lastsecstart, lastsecend = getsecaddr(datain, lastsec)
|
||||
zerosecstart, zerosecend = getsecaddr(datain, 0)
|
||||
dif = lastsecend - firstsecstart + 8*(lastsec-firstsec+1)
|
||||
nsec = getint(datain, number_of_pdb_records, 'H')
|
||||
datalst.append(datain[:unique_id_seed])
|
||||
datalst.append(struct.pack('>L', 2*(nsec-(lastsec-firstsec+1))+1))
|
||||
datalst.append(datain[unique_id_seed+4:number_of_pdb_records])
|
||||
datalst.append(struct.pack('>H', nsec-(lastsec-firstsec+1)))
|
||||
newstart = zerosecstart - 8*(lastsec-firstsec+1)
|
||||
for i in range(0, firstsec):
|
||||
ofs, flgval = struct.unpack_from('>2L', datain, first_pdb_record+i*8)
|
||||
ofs -= 8 * (lastsec - firstsec + 1)
|
||||
datalst.append(struct.pack('>L', ofs) + struct.pack('>L', flgval))
|
||||
for i in range(lastsec+1, nsec):
|
||||
ofs, flgval = struct.unpack_from('>2L', datain, first_pdb_record+i*8)
|
||||
ofs -= dif
|
||||
flgval = 2*(i-(lastsec-firstsec+1))
|
||||
datalst.append(struct.pack('>L', ofs) + struct.pack('>L', flgval))
|
||||
lpad = newstart - (first_pdb_record + 8*(nsec - (lastsec - firstsec + 1)))
|
||||
if lpad > 0:
|
||||
datalst.append('\0' * lpad)
|
||||
datalst.append(datain[zerosecstart:firstsecstart])
|
||||
datalst.append(datain[lastsecend:])
|
||||
dataout = "".join(datalst)
|
||||
return dataout
|
||||
|
||||
|
||||
def insertsection(datain, secno, secdata): # insert a new section
|
||||
datalst = []
|
||||
nsec = getint(datain, number_of_pdb_records, 'H')
|
||||
secstart, secend = getsecaddr(datain, secno)
|
||||
zerosecstart, zerosecend = getsecaddr(datain, 0)
|
||||
dif = len(secdata)
|
||||
datalst.append(datain[:unique_id_seed])
|
||||
datalst.append(struct.pack('>L', 2*(nsec+1)+1))
|
||||
datalst.append(datain[unique_id_seed+4:number_of_pdb_records])
|
||||
datalst.append(struct.pack('>H', nsec+1))
|
||||
newstart = zerosecstart + 8
|
||||
for i in range(0, secno):
|
||||
ofs, flgval = struct.unpack_from('>2L', datain, first_pdb_record+i*8)
|
||||
ofs += 8
|
||||
datalst.append(struct.pack('>L', ofs) + struct.pack('>L', flgval))
|
||||
datalst.append(struct.pack('>L', secstart + 8) + struct.pack('>L', (2*secno)))
|
||||
for i in range(secno, nsec):
|
||||
ofs, flgval = struct.unpack_from('>2L', datain, first_pdb_record+i*8)
|
||||
ofs = ofs + dif + 8
|
||||
flgval = 2*(i+1)
|
||||
datalst.append(struct.pack('>L', ofs) + struct.pack('>L', flgval))
|
||||
lpad = newstart - (first_pdb_record + 8*(nsec + 1))
|
||||
if lpad > 0:
|
||||
datalst.append('\0' * lpad)
|
||||
datalst.append(datain[zerosecstart:secstart])
|
||||
datalst.append(secdata)
|
||||
datalst.append(datain[secstart:])
|
||||
dataout = "".join(datalst)
|
||||
return dataout
|
||||
|
||||
|
||||
def insertsectionrange(sectionsource, firstsec, lastsec, sectiontarget, targetsec): # insert a range of sections
|
||||
dataout = sectiontarget
|
||||
for idx in range(lastsec, firstsec-1, -1):
|
||||
dataout = insertsection(dataout, targetsec, readsection(sectionsource, idx))
|
||||
return dataout
|
||||
|
||||
|
||||
def get_exth_params(rec0):
|
||||
ebase = mobi_header_base + getint(rec0, mobi_header_length)
|
||||
elen = getint(rec0, ebase+4)
|
||||
enum = getint(rec0, ebase+8)
|
||||
return ebase, elen, enum
|
||||
|
||||
|
||||
def add_exth(rec0, exth_num, exth_bytes):
|
||||
ebase, elen, enum = get_exth_params(rec0)
|
||||
newrecsize = 8+len(exth_bytes)
|
||||
newrec0 = rec0[0:ebase+4]+struct.pack('>L', elen+newrecsize)+struct.pack('>L', enum+1) +\
|
||||
struct.pack('>L', exth_num) + struct.pack('>L', newrecsize)+exth_bytes+rec0[ebase+12:]
|
||||
newrec0 = writeint(newrec0, title_offset, getint(newrec0, title_offset)+newrecsize)
|
||||
return newrec0
|
||||
|
||||
|
||||
def read_exth(rec0, exth_num):
|
||||
exth_values = []
|
||||
ebase, elen, enum = get_exth_params(rec0)
|
||||
ebase += 12
|
||||
while enum > 0:
|
||||
exth_id = getint(rec0, ebase)
|
||||
if exth_id == exth_num:
|
||||
# We might have multiple exths, so build a list.
|
||||
exth_values.append(rec0[ebase+8:ebase+getint(rec0, ebase+4)])
|
||||
enum -= 1
|
||||
ebase = ebase+getint(rec0, ebase+4)
|
||||
return exth_values
|
||||
|
||||
|
||||
def write_exth(rec0, exth_num, exth_bytes):
|
||||
ebase, elen, enum = get_exth_params(rec0)
|
||||
ebase_idx = ebase+12
|
||||
enum_idx = enum
|
||||
while enum_idx > 0:
|
||||
exth_id = getint(rec0, ebase_idx)
|
||||
if exth_id == exth_num:
|
||||
dif = len(exth_bytes)+8-getint(rec0, ebase_idx+4)
|
||||
newrec0 = rec0
|
||||
if dif != 0:
|
||||
newrec0 = writeint(newrec0, title_offset, getint(newrec0, title_offset)+dif)
|
||||
return newrec0[:ebase+4]+struct.pack('>L', elen+len(exth_bytes)+8-getint(rec0, ebase_idx+4)) +\
|
||||
struct.pack('>L', enum)+rec0[ebase+12:ebase_idx+4] +\
|
||||
struct.pack('>L', len(exth_bytes)+8)+exth_bytes +\
|
||||
rec0[ebase_idx+getint(rec0, ebase_idx+4):]
|
||||
enum_idx -= 1
|
||||
ebase_idx = ebase_idx+getint(rec0, ebase_idx+4)
|
||||
return rec0
|
||||
|
||||
|
||||
def del_exth(rec0, exth_num):
|
||||
ebase, elen, enum = get_exth_params(rec0)
|
||||
ebase_idx = ebase+12
|
||||
enum_idx = 0
|
||||
while enum_idx < enum:
|
||||
exth_id = getint(rec0, ebase_idx)
|
||||
exth_size = getint(rec0, ebase_idx+4)
|
||||
if exth_id == exth_num:
|
||||
newrec0 = rec0
|
||||
newrec0 = writeint(newrec0, title_offset, getint(newrec0, title_offset)-exth_size)
|
||||
newrec0 = newrec0[:ebase_idx]+newrec0[ebase_idx+exth_size:]
|
||||
newrec0 = newrec0[0:ebase+4]+struct.pack('>L', elen-exth_size)+struct.pack('>L', enum-1)+newrec0[ebase+12:]
|
||||
return newrec0
|
||||
enum_idx += 1
|
||||
ebase_idx = ebase_idx+exth_size
|
||||
return rec0
|
||||
|
||||
|
||||
class mobi_split:
|
||||
def __init__(self, infile, newKindle):
|
||||
try:
|
||||
datain = open(infile, 'rb').read()
|
||||
datain_rec0 = readsection(datain, 0)
|
||||
ver = getint(datain_rec0, mobi_version)
|
||||
# fake_asin = str(uuid4())
|
||||
self.combo = (ver != 8)
|
||||
if not self.combo:
|
||||
return
|
||||
exth121 = read_exth(datain_rec0, 121)
|
||||
if len(exth121) == 0:
|
||||
self.combo = False
|
||||
return
|
||||
else:
|
||||
# only pay attention to first exth121
|
||||
# (there should only be one)
|
||||
datain_kf8, = struct.unpack_from('>L', exth121[0], 0)
|
||||
if datain_kf8 == 0xffffffff:
|
||||
self.combo = False
|
||||
return
|
||||
datain_kfrec0 = readsection(datain, datain_kf8)
|
||||
firstimage = getint(datain_rec0, first_image_record)
|
||||
lastimage = getint(datain_rec0, last_content_index, 'H')
|
||||
|
||||
if not newKindle:
|
||||
# create the standalone mobi7
|
||||
num_sec = getint(datain, number_of_pdb_records, 'H')
|
||||
# remove BOUNDARY up to but not including ELF record
|
||||
self.result_file = deletesectionrange(datain, datain_kf8-1, num_sec-2)
|
||||
# check if there are SRCS records and delete them
|
||||
srcs = getint(datain_rec0, srcs_index)
|
||||
num_srcs = getint(datain_rec0, srcs_count)
|
||||
if srcs != 0xffffffff and num_srcs > 0:
|
||||
self.result_file = deletesectionrange(self.result_file, srcs, srcs+num_srcs-1)
|
||||
datain_rec0 = writeint(datain_rec0, srcs_index, 0xffffffff)
|
||||
datain_rec0 = writeint(datain_rec0, srcs_count, 0)
|
||||
# reset the EXTH 121 KF8 Boundary meta data to 0xffffffff
|
||||
datain_rec0 = write_exth(datain_rec0, 121, struct.pack('>L', 0xffffffff))
|
||||
# datain_rec0 = del_exth(datain_rec0,121)
|
||||
# datain_rec0 = del_exth(datain_rec0,534)
|
||||
# don't remove the EXTH 125 KF8 Count of Resources, seems to be present in mobi6 files as well
|
||||
# set the EXTH 129 KF8 Masthead / Cover Image string to the null string
|
||||
datain_rec0 = write_exth(datain_rec0, 129, '')
|
||||
# don't remove the EXTH 131 KF8 Unidentified Count, seems to be present in mobi6 files as well
|
||||
|
||||
# Make sure we have an ASIN & cdeType set...
|
||||
# if len(read_exth(datain_rec0, 113)) == 0:
|
||||
# datain_rec0 = add_exth(datain_rec0, 113, fake_asin)
|
||||
# if len(read_exth(datain_rec0, 504)) == 0:
|
||||
# datain_rec0 = add_exth(datain_rec0, 504, fake_asin)
|
||||
if len(read_exth(datain_rec0, 501)) == 0:
|
||||
datain_rec0 = add_exth(datain_rec0, 501, b'EBOK')
|
||||
|
||||
# need to reset flags stored in 0x80-0x83
|
||||
# old mobi with exth: 0x50, mobi7 part with exth: 0x1850, mobi8 part with exth: 0x1050
|
||||
# Bit Flags
|
||||
# 0x1000 = Bit 12 indicates if embedded fonts are used or not
|
||||
# 0x0800 = means this Header points to *shared* images/resource/fonts ??
|
||||
# 0x0080 = unknown new flag, why is this now being set by Kindlegen 2.8?
|
||||
# 0x0040 = exth exists
|
||||
# 0x0010 = Not sure but this is always set so far
|
||||
fval, = struct.unpack_from('>L', datain_rec0, 0x80)
|
||||
# need to remove flag 0x0800 for KindlePreviewer 2.8 and unset Bit 12 for embedded fonts
|
||||
fval &= 0x07FF
|
||||
datain_rec0 = datain_rec0[:0x80] + struct.pack('>L', fval) + datain_rec0[0x84:]
|
||||
self.result_file = writesection(self.result_file, 0, datain_rec0)
|
||||
if lastimage == 0xffff:
|
||||
# find the lowest of the next sections and copy up to that.
|
||||
ofs_list = [(kf8_last_content_index, 'L'), (fcis_index, 'L'), (flis_index, 'L'), (datp_index, 'L'),
|
||||
(hufftbloff, 'L')]
|
||||
for ofs, sz in ofs_list:
|
||||
n = getint(datain_kfrec0, ofs, sz)
|
||||
if 0 < n < lastimage:
|
||||
lastimage = n-1
|
||||
|
||||
# Try to null out FONT and RES, but leave the (empty) PDB record so image refs remain valid
|
||||
for i in range(firstimage, lastimage):
|
||||
imgsec = readsection(self.result_file, i)
|
||||
if imgsec[0:4] in ['RESC', 'FONT']:
|
||||
self.result_file = nullsection(self.result_file, i)
|
||||
# mobi7 finished
|
||||
else:
|
||||
# create standalone mobi8
|
||||
self.result_file = deletesectionrange(datain, 0, datain_kf8-1)
|
||||
target = getint(datain_kfrec0, first_image_record)
|
||||
self.result_file = insertsectionrange(datain, firstimage, lastimage, self.result_file, target)
|
||||
datain_kfrec0 = readsection(self.result_file, 0)
|
||||
|
||||
# Only keep the correct EXTH 116 StartOffset, KG 2.5 carries over the one from the mobi7 part,
|
||||
# which then points at garbage in the mobi8 part, and confuses FW 3.4
|
||||
kf8starts = read_exth(datain_kfrec0, 116)
|
||||
# If we have multiple StartOffset, keep only the last one
|
||||
kf8start_count = len(kf8starts)
|
||||
while kf8start_count > 1:
|
||||
kf8start_count -= 1
|
||||
datain_kfrec0 = del_exth(datain_kfrec0, 116)
|
||||
|
||||
# update the EXTH 125 KF8 Count of Images/Fonts/Resources
|
||||
datain_kfrec0 = write_exth(datain_kfrec0, 125, struct.pack('>L', lastimage-firstimage+1))
|
||||
|
||||
# Same dance for the KF8, we want an ASIN & cdeType :)
|
||||
# if len(read_exth(datain_kfrec0, 113)) == 0:
|
||||
# datain_kfrec0 = add_exth(datain_kfrec0, 113, fake_asin)
|
||||
# if len(read_exth(datain_kfrec0, 504)) == 0:
|
||||
# datain_kfrec0 = add_exth(datain_kfrec0, 504, fake_asin)
|
||||
if len(read_exth(datain_kfrec0, 501)) == 0:
|
||||
datain_kfrec0 = add_exth(datain_kfrec0, 501, b'EBOK')
|
||||
|
||||
# need to reset flags stored in 0x80-0x83
|
||||
# old mobi with exth: 0x50, mobi7 part with exth: 0x1850, mobi8 part with exth: 0x1050
|
||||
# standalone mobi8 with exth: 0x0050
|
||||
# Bit Flags
|
||||
# 0x1000 = Bit 12 indicates if embedded fonts are used or not
|
||||
# 0x0800 = means this Header points to *shared* images/resource/fonts ??
|
||||
# 0x0080 = unknown new flag, why is this now being set by Kindlegen 2.8?
|
||||
# 0x0040 = exth exists
|
||||
# 0x0010 = Not sure but this is always set so far
|
||||
fval, = struct.unpack_from('>L', datain_kfrec0, 0x80)
|
||||
fval &= 0x1FFF
|
||||
fval |= 0x0800
|
||||
datain_kfrec0 = datain_kfrec0[:0x80] + struct.pack('>L', fval) + datain_kfrec0[0x84:]
|
||||
|
||||
# properly update other index pointers that have been shifted by the insertion of images
|
||||
ofs_list = [(kf8_last_content_index, 'L'), (fcis_index, 'L'), (flis_index, 'L'), (datp_index, 'L'),
|
||||
(hufftbloff, 'L')]
|
||||
for ofs, sz in ofs_list:
|
||||
n = getint(datain_kfrec0, ofs, sz)
|
||||
if n != 0xffffffff:
|
||||
datain_kfrec0 = writeint(datain_kfrec0, ofs, n+lastimage-firstimage+1, sz)
|
||||
self.result_file = writesection(self.result_file, 0, datain_kfrec0)
|
||||
# mobi8 finished
|
||||
except Exception:
|
||||
raise
|
||||
|
||||
def getResult(self):
|
||||
return self.result_file
|
||||
1877
kcc/rarfile.py
1877
kcc/rarfile.py
File diff suppressed because it is too large
Load Diff
1146
kindlecomicconverter/KCC_gui.py
Normal file
1146
kindlecomicconverter/KCC_gui.py
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
273
kindlecomicconverter/KCC_ui.py
Normal file
273
kindlecomicconverter/KCC_ui.py
Normal file
@@ -0,0 +1,273 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'gui\KCC.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.8.1
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
class Ui_mainWindow(object):
|
||||
def setupUi(self, mainWindow):
|
||||
mainWindow.setObjectName("mainWindow")
|
||||
mainWindow.resize(450, 400)
|
||||
icon = QtGui.QIcon()
|
||||
icon.addPixmap(QtGui.QPixmap(":/Icon/icons/comic2ebook.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
mainWindow.setWindowIcon(icon)
|
||||
self.centralWidget = QtWidgets.QWidget(mainWindow)
|
||||
self.centralWidget.setObjectName("centralWidget")
|
||||
self.gridLayout = QtWidgets.QGridLayout(self.centralWidget)
|
||||
self.gridLayout.setContentsMargins(-1, -1, -1, 5)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.progressBar = QtWidgets.QProgressBar(self.centralWidget)
|
||||
self.progressBar.setMinimumSize(QtCore.QSize(0, 30))
|
||||
font = QtGui.QFont()
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
self.progressBar.setFont(font)
|
||||
self.progressBar.setVisible(False)
|
||||
self.progressBar.setAlignment(QtCore.Qt.AlignJustify|QtCore.Qt.AlignVCenter)
|
||||
self.progressBar.setObjectName("progressBar")
|
||||
self.gridLayout.addWidget(self.progressBar, 1, 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.gridLayout.addWidget(self.jobList, 2, 0, 1, 2)
|
||||
self.customWidget = QtWidgets.QWidget(self.centralWidget)
|
||||
self.customWidget.setVisible(False)
|
||||
self.customWidget.setObjectName("customWidget")
|
||||
self.gridLayout_3 = QtWidgets.QGridLayout(self.customWidget)
|
||||
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.gridLayout_3.addWidget(self.hLabel, 0, 2, 1, 1)
|
||||
self.widthBox = QtWidgets.QSpinBox(self.customWidget)
|
||||
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.gridLayout_3.addWidget(self.wLabel, 0, 0, 1, 1)
|
||||
self.heightBox = QtWidgets.QSpinBox(self.customWidget)
|
||||
self.heightBox.setMaximum(3840)
|
||||
self.heightBox.setObjectName("heightBox")
|
||||
self.gridLayout_3.addWidget(self.heightBox, 0, 3, 1, 1)
|
||||
self.gridLayout.addWidget(self.customWidget, 6, 0, 1, 2)
|
||||
self.optionWidget = QtWidgets.QWidget(self.centralWidget)
|
||||
self.optionWidget.setObjectName("optionWidget")
|
||||
self.gridLayout_2 = QtWidgets.QGridLayout(self.optionWidget)
|
||||
self.gridLayout_2.setContentsMargins(0, 0, 0, 0)
|
||||
self.gridLayout_2.setObjectName("gridLayout_2")
|
||||
self.mangaBox = QtWidgets.QCheckBox(self.optionWidget)
|
||||
self.mangaBox.setObjectName("mangaBox")
|
||||
self.gridLayout_2.addWidget(self.mangaBox, 0, 0, 1, 1)
|
||||
self.rotateBox = QtWidgets.QCheckBox(self.optionWidget)
|
||||
self.rotateBox.setTristate(True)
|
||||
self.rotateBox.setObjectName("rotateBox")
|
||||
self.gridLayout_2.addWidget(self.rotateBox, 0, 1, 1, 1)
|
||||
self.qualityBox = QtWidgets.QCheckBox(self.optionWidget)
|
||||
self.qualityBox.setTristate(True)
|
||||
self.qualityBox.setObjectName("qualityBox")
|
||||
self.gridLayout_2.addWidget(self.qualityBox, 0, 2, 1, 1)
|
||||
self.webtoonBox = QtWidgets.QCheckBox(self.optionWidget)
|
||||
self.webtoonBox.setObjectName("webtoonBox")
|
||||
self.gridLayout_2.addWidget(self.webtoonBox, 1, 0, 1, 1)
|
||||
self.upscaleBox = QtWidgets.QCheckBox(self.optionWidget)
|
||||
self.upscaleBox.setTristate(True)
|
||||
self.upscaleBox.setObjectName("upscaleBox")
|
||||
self.gridLayout_2.addWidget(self.upscaleBox, 1, 1, 1, 1)
|
||||
self.gammaBox = QtWidgets.QCheckBox(self.optionWidget)
|
||||
self.gammaBox.setObjectName("gammaBox")
|
||||
self.gridLayout_2.addWidget(self.gammaBox, 1, 2, 1, 1)
|
||||
self.borderBox = QtWidgets.QCheckBox(self.optionWidget)
|
||||
self.borderBox.setTristate(True)
|
||||
self.borderBox.setObjectName("borderBox")
|
||||
self.gridLayout_2.addWidget(self.borderBox, 2, 0, 1, 1)
|
||||
self.outputSplit = QtWidgets.QCheckBox(self.optionWidget)
|
||||
self.outputSplit.setObjectName("outputSplit")
|
||||
self.gridLayout_2.addWidget(self.outputSplit, 2, 1, 1, 1)
|
||||
self.colorBox = QtWidgets.QCheckBox(self.optionWidget)
|
||||
self.colorBox.setObjectName("colorBox")
|
||||
self.gridLayout_2.addWidget(self.colorBox, 2, 2, 1, 1)
|
||||
self.gridLayout.addWidget(self.optionWidget, 4, 0, 1, 2)
|
||||
self.gammaWidget = QtWidgets.QWidget(self.centralWidget)
|
||||
self.gammaWidget.setVisible(False)
|
||||
self.gammaWidget.setObjectName("gammaWidget")
|
||||
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.gammaWidget)
|
||||
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.horizontalLayout_2.addWidget(self.gammaLabel)
|
||||
self.gammaSlider = QtWidgets.QSlider(self.gammaWidget)
|
||||
self.gammaSlider.setMaximum(250)
|
||||
self.gammaSlider.setSingleStep(5)
|
||||
self.gammaSlider.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.gammaSlider.setObjectName("gammaSlider")
|
||||
self.horizontalLayout_2.addWidget(self.gammaSlider)
|
||||
self.gridLayout.addWidget(self.gammaWidget, 5, 0, 1, 2)
|
||||
self.toolWidget = QtWidgets.QWidget(self.centralWidget)
|
||||
self.toolWidget.setObjectName("toolWidget")
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout(self.toolWidget)
|
||||
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
self.editorButton = QtWidgets.QPushButton(self.toolWidget)
|
||||
self.editorButton.setMinimumSize(QtCore.QSize(0, 30))
|
||||
icon1 = QtGui.QIcon()
|
||||
icon1.addPixmap(QtGui.QPixmap(":/Other/icons/editor.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
self.editorButton.setIcon(icon1)
|
||||
self.editorButton.setObjectName("editorButton")
|
||||
self.horizontalLayout.addWidget(self.editorButton)
|
||||
self.wikiButton = QtWidgets.QPushButton(self.toolWidget)
|
||||
self.wikiButton.setMinimumSize(QtCore.QSize(0, 30))
|
||||
icon2 = QtGui.QIcon()
|
||||
icon2.addPixmap(QtGui.QPixmap(":/Other/icons/wiki.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
self.wikiButton.setIcon(icon2)
|
||||
self.wikiButton.setObjectName("wikiButton")
|
||||
self.horizontalLayout.addWidget(self.wikiButton)
|
||||
self.gridLayout.addWidget(self.toolWidget, 0, 0, 1, 2)
|
||||
self.buttonWidget = QtWidgets.QWidget(self.centralWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.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.setContentsMargins(0, 0, 0, 0)
|
||||
self.gridLayout_4.setObjectName("gridLayout_4")
|
||||
self.directoryButton = QtWidgets.QPushButton(self.buttonWidget)
|
||||
self.directoryButton.setMinimumSize(QtCore.QSize(0, 30))
|
||||
icon3 = QtGui.QIcon()
|
||||
icon3.addPixmap(QtGui.QPixmap(":/Other/icons/folder_new.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
self.directoryButton.setIcon(icon3)
|
||||
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))
|
||||
icon4 = QtGui.QIcon()
|
||||
icon4.addPixmap(QtGui.QPixmap(":/Other/icons/document_new.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
self.fileButton.setIcon(icon4)
|
||||
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.setSizeAdjustPolicy(QtWidgets.QComboBox.AdjustToMinimumContentsLength)
|
||||
self.deviceBox.setObjectName("deviceBox")
|
||||
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.setSizeAdjustPolicy(QtWidgets.QComboBox.AdjustToMinimumContentsLength)
|
||||
self.formatBox.setObjectName("formatBox")
|
||||
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()
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
self.convertButton.setFont(font)
|
||||
icon5 = QtGui.QIcon()
|
||||
icon5.addPixmap(QtGui.QPixmap(":/Other/icons/convert.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
self.convertButton.setIcon(icon5)
|
||||
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))
|
||||
icon6 = QtGui.QIcon()
|
||||
icon6.addPixmap(QtGui.QPixmap(":/Other/icons/clear.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
self.clearButton.setIcon(icon6)
|
||||
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)
|
||||
mainWindow.setCentralWidget(self.centralWidget)
|
||||
self.statusBar = QtWidgets.QStatusBar(mainWindow)
|
||||
self.statusBar.setSizeGripEnabled(False)
|
||||
self.statusBar.setObjectName("statusBar")
|
||||
mainWindow.setStatusBar(self.statusBar)
|
||||
|
||||
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.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)
|
||||
|
||||
def retranslateUi(self, mainWindow):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
mainWindow.setWindowTitle(_translate("mainWindow", "Kindle Comic Converter"))
|
||||
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>"))
|
||||
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.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.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.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.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.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.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.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.gammaLabel.setText(_translate("mainWindow", "Gamma: Auto"))
|
||||
self.editorButton.setText(_translate("mainWindow", "Editor"))
|
||||
self.editorButton.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Shift+Click to edit directory.</p></body></html>"))
|
||||
self.wikiButton.setText(_translate("mainWindow", "Wiki"))
|
||||
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"))
|
||||
|
||||
from . import KCC_rc
|
||||
116
kindlecomicconverter/KCC_ui_editor.py
Normal file
116
kindlecomicconverter/KCC_ui_editor.py
Normal file
@@ -0,0 +1,116 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'gui\MetaEditor.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.6
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
class Ui_editorDialog(object):
|
||||
def setupUi(self, editorDialog):
|
||||
editorDialog.setObjectName("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.setWindowIcon(icon)
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout(editorDialog)
|
||||
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.gridLayout.setContentsMargins(0, 0, 0, 0)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.label_1 = QtWidgets.QLabel(self.editorWidget)
|
||||
self.label_1.setObjectName("label_1")
|
||||
self.gridLayout.addWidget(self.label_1, 0, 0, 1, 1)
|
||||
self.seriesLine = QtWidgets.QLineEdit(self.editorWidget)
|
||||
self.seriesLine.setObjectName("seriesLine")
|
||||
self.gridLayout.addWidget(self.seriesLine, 0, 1, 1, 1)
|
||||
self.label_2 = QtWidgets.QLabel(self.editorWidget)
|
||||
self.label_2.setObjectName("label_2")
|
||||
self.gridLayout.addWidget(self.label_2, 1, 0, 1, 1)
|
||||
self.volumeLine = QtWidgets.QLineEdit(self.editorWidget)
|
||||
self.volumeLine.setObjectName("volumeLine")
|
||||
self.gridLayout.addWidget(self.volumeLine, 1, 1, 1, 1)
|
||||
self.label_3 = QtWidgets.QLabel(self.editorWidget)
|
||||
self.label_3.setObjectName("label_3")
|
||||
self.gridLayout.addWidget(self.label_3, 2, 0, 1, 1)
|
||||
self.numberLine = QtWidgets.QLineEdit(self.editorWidget)
|
||||
self.numberLine.setObjectName("numberLine")
|
||||
self.gridLayout.addWidget(self.numberLine, 2, 1, 1, 1)
|
||||
self.label_4 = QtWidgets.QLabel(self.editorWidget)
|
||||
self.label_4.setObjectName("label_4")
|
||||
self.gridLayout.addWidget(self.label_4, 3, 0, 1, 1)
|
||||
self.writerLine = QtWidgets.QLineEdit(self.editorWidget)
|
||||
self.writerLine.setObjectName("writerLine")
|
||||
self.gridLayout.addWidget(self.writerLine, 3, 1, 1, 1)
|
||||
self.label_5 = QtWidgets.QLabel(self.editorWidget)
|
||||
self.label_5.setObjectName("label_5")
|
||||
self.gridLayout.addWidget(self.label_5, 4, 0, 1, 1)
|
||||
self.pencillerLine = QtWidgets.QLineEdit(self.editorWidget)
|
||||
self.pencillerLine.setObjectName("pencillerLine")
|
||||
self.gridLayout.addWidget(self.pencillerLine, 4, 1, 1, 1)
|
||||
self.label_6 = QtWidgets.QLabel(self.editorWidget)
|
||||
self.label_6.setObjectName("label_6")
|
||||
self.gridLayout.addWidget(self.label_6, 5, 0, 1, 1)
|
||||
self.inkerLine = QtWidgets.QLineEdit(self.editorWidget)
|
||||
self.inkerLine.setObjectName("inkerLine")
|
||||
self.gridLayout.addWidget(self.inkerLine, 5, 1, 1, 1)
|
||||
self.label_7 = QtWidgets.QLabel(self.editorWidget)
|
||||
self.label_7.setObjectName("label_7")
|
||||
self.gridLayout.addWidget(self.label_7, 6, 0, 1, 1)
|
||||
self.coloristLine = QtWidgets.QLineEdit(self.editorWidget)
|
||||
self.coloristLine.setObjectName("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.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)
|
||||
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.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.setIcon(icon2)
|
||||
self.cancelButton.setObjectName("cancelButton")
|
||||
self.horizontalLayout.addWidget(self.cancelButton)
|
||||
self.verticalLayout.addWidget(self.optionWidget)
|
||||
|
||||
self.retranslateUi(editorDialog)
|
||||
QtCore.QMetaObject.connectSlotsByName(editorDialog)
|
||||
|
||||
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
|
||||
4
kindlecomicconverter/__init__.py
Normal file
4
kindlecomicconverter/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
__version__ = '5.5.0'
|
||||
__license__ = 'ISC'
|
||||
__copyright__ = '2012-2019, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
1234
kindlecomicconverter/comic2ebook.py
Executable file
1234
kindlecomicconverter/comic2ebook.py
Executable file
File diff suppressed because it is too large
Load Diff
281
kindlecomicconverter/comic2panel.py
Normal file
281
kindlecomicconverter/comic2panel.py
Normal file
@@ -0,0 +1,281 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||
# Copyright (c) 2013-2019 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for
|
||||
# any purpose with or without fee is hereby granted, provided that the
|
||||
# above copyright notice and this permission notice appear in all
|
||||
# copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
# AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
|
||||
# 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 os
|
||||
import sys
|
||||
from shutil import rmtree, copytree, move
|
||||
from optparse import OptionParser, OptionGroup
|
||||
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):
|
||||
if output:
|
||||
mergeWorkerOutput.append(output)
|
||||
mergeWorkerPool.terminate()
|
||||
if GUI:
|
||||
GUI.progressBarTick.emit('tick')
|
||||
if not GUI.conversionAlive:
|
||||
mergeWorkerPool.terminate()
|
||||
|
||||
|
||||
def mergeDirectory(work):
|
||||
try:
|
||||
directory = work[0]
|
||||
images = []
|
||||
imagesValid = []
|
||||
sizes = []
|
||||
targetHeight = 0
|
||||
for root, _, files in walkLevel(directory, 0):
|
||||
for name in files:
|
||||
if getImageFileName(name) is not None:
|
||||
i = Image.open(os.path.join(root, name))
|
||||
images.append([os.path.join(root, name), i.size[0], i.size[1]])
|
||||
sizes.append(i.size[0])
|
||||
if len(images) > 0:
|
||||
targetWidth = max(set(sizes), key=sizes.count)
|
||||
for i in images:
|
||||
if i[1] <= targetWidth:
|
||||
targetHeight += i[2]
|
||||
imagesValid.append(i[0])
|
||||
# Silently drop directories that contain too many images
|
||||
# 131072 = GIMP_MAX_IMAGE_SIZE / 4
|
||||
if targetHeight > 131072:
|
||||
return None
|
||||
result = Image.new('RGB', (targetWidth, targetHeight))
|
||||
y = 0
|
||||
for i in imagesValid:
|
||||
img = Image.open(i).convert('RGB')
|
||||
if img.size[0] < targetWidth:
|
||||
img = ImageOps.fit(img, (targetWidth, img.size[1]), method=Image.BICUBIC, centering=(0.5, 0.5))
|
||||
result.paste(img, (0, y))
|
||||
y += img.size[1]
|
||||
os.remove(i)
|
||||
savePath = os.path.split(imagesValid[0])
|
||||
result.save(os.path.join(savePath[0], os.path.splitext(savePath[1])[0] + '.png'), 'PNG')
|
||||
except Exception:
|
||||
return str(sys.exc_info()[1]), sanitizeTrace(sys.exc_info()[2])
|
||||
|
||||
|
||||
def detectSolid(img):
|
||||
return not ImageChops.invert(img).getbbox() or not img.getbbox()
|
||||
|
||||
|
||||
def splitImageTick(output):
|
||||
if output:
|
||||
splitWorkerOutput.append(output)
|
||||
splitWorkerPool.terminate()
|
||||
if GUI:
|
||||
GUI.progressBarTick.emit('tick')
|
||||
if not GUI.conversionAlive:
|
||||
splitWorkerPool.terminate()
|
||||
|
||||
|
||||
# noinspection PyUnboundLocalVariable
|
||||
def splitImage(work):
|
||||
try:
|
||||
path = work[0]
|
||||
name = work[1]
|
||||
opt = work[2]
|
||||
filePath = os.path.join(path, name)
|
||||
imgOrg = Image.open(filePath).convert('RGB')
|
||||
imgProcess = Image.open(filePath).convert('1')
|
||||
widthImg, heightImg = imgOrg.size
|
||||
if heightImg > opt.height:
|
||||
if opt.debug:
|
||||
drawImg = Image.open(filePath).convert(mode='RGBA')
|
||||
draw = ImageDraw.Draw(drawImg)
|
||||
|
||||
# Find panels
|
||||
yWork = 0
|
||||
panelDetected = False
|
||||
panels = []
|
||||
while yWork < heightImg:
|
||||
tmpImg = imgProcess.crop([0, yWork, widthImg, yWork + 4])
|
||||
solid = detectSolid(tmpImg)
|
||||
if not solid and not panelDetected:
|
||||
panelDetected = True
|
||||
panelY1 = yWork - 2
|
||||
if solid and panelDetected:
|
||||
panelDetected = False
|
||||
panelY2 = yWork + 6
|
||||
panels.append((panelY1, panelY2, panelY2 - panelY1))
|
||||
yWork += 5
|
||||
|
||||
# Split too big panels
|
||||
panelsProcessed = []
|
||||
for panel in panels:
|
||||
if panel[2] <= opt.height * 1.5:
|
||||
panelsProcessed.append(panel)
|
||||
elif panel[2] < opt.height * 2:
|
||||
diff = panel[2] - opt.height
|
||||
panelsProcessed.append((panel[0], panel[1] - diff, opt.height))
|
||||
panelsProcessed.append((panel[1] - opt.height, panel[1], opt.height))
|
||||
else:
|
||||
parts = round(panel[2] / opt.height)
|
||||
diff = panel[2] // parts
|
||||
for x in range(0, parts):
|
||||
panelsProcessed.append((panel[0] + (x * diff), panel[1] - ((parts - x - 1) * diff), diff))
|
||||
|
||||
if opt.debug:
|
||||
for panel in panelsProcessed:
|
||||
draw.rectangle([(0, panel[0]), (widthImg, panel[1])], (0, 255, 0, 128), (0, 0, 255, 255))
|
||||
debugImage = Image.alpha_composite(imgOrg.convert(mode='RGBA'), drawImg)
|
||||
debugImage.save(os.path.join(path, os.path.splitext(name)[0] + '-debug.png'), 'PNG')
|
||||
|
||||
# Create virtual pages
|
||||
pages = []
|
||||
currentPage = []
|
||||
pageLeft = opt.height
|
||||
panelNumber = 0
|
||||
for panel in panelsProcessed:
|
||||
if pageLeft - panel[2] > 0:
|
||||
pageLeft -= panel[2]
|
||||
currentPage.append(panelNumber)
|
||||
panelNumber += 1
|
||||
else:
|
||||
if len(currentPage) > 0:
|
||||
pages.append(currentPage)
|
||||
pageLeft = opt.height - panel[2]
|
||||
currentPage = [panelNumber]
|
||||
panelNumber += 1
|
||||
if len(currentPage) > 0:
|
||||
pages.append(currentPage)
|
||||
|
||||
# Create pages
|
||||
pageNumber = 1
|
||||
for page in pages:
|
||||
pageHeight = 0
|
||||
targetHeight = 0
|
||||
for panel in page:
|
||||
pageHeight += panelsProcessed[panel][2]
|
||||
if pageHeight > 15:
|
||||
newPage = Image.new('RGB', (widthImg, pageHeight))
|
||||
for panel in page:
|
||||
panelImg = imgOrg.crop([0, panelsProcessed[panel][0], widthImg, panelsProcessed[panel][1]])
|
||||
newPage.paste(panelImg, (0, targetHeight))
|
||||
targetHeight += panelsProcessed[panel][2]
|
||||
newPage.save(os.path.join(path, os.path.splitext(name)[0] + '-' + str(pageNumber) + '.png'), 'PNG')
|
||||
pageNumber += 1
|
||||
os.remove(filePath)
|
||||
except Exception:
|
||||
return str(sys.exc_info()[1]), sanitizeTrace(sys.exc_info()[2])
|
||||
|
||||
|
||||
def main(argv=None, qtgui=None):
|
||||
global options, GUI, splitWorkerPool, splitWorkerOutput, mergeWorkerPool, mergeWorkerOutput
|
||||
parser = OptionParser(usage="Usage: kcc-c2p [options] comic_folder", add_help_option=False)
|
||||
mainOptions = OptionGroup(parser, "MANDATORY")
|
||||
otherOptions = OptionGroup(parser, "OTHER")
|
||||
mainOptions.add_option("-y", "--height", type="int", dest="height", default=0,
|
||||
help="Height of the target device screen")
|
||||
mainOptions.add_option("-i", "--in-place", action="store_true", dest="inPlace", default=False,
|
||||
help="Overwrite source directory")
|
||||
mainOptions.add_option("-m", "--merge", action="store_true", dest="merge", default=False,
|
||||
help="Combine every directory into a single image before splitting")
|
||||
otherOptions.add_option("-d", "--debug", action="store_true", dest="debug", default=False,
|
||||
help="Create debug file for every split image")
|
||||
otherOptions.add_option("-h", "--help", action="help",
|
||||
help="Show this help message and exit")
|
||||
parser.add_option_group(mainOptions)
|
||||
parser.add_option_group(otherOptions)
|
||||
options, args = parser.parse_args(argv)
|
||||
if qtgui:
|
||||
GUI = qtgui
|
||||
else:
|
||||
GUI = None
|
||||
if len(args) != 1:
|
||||
parser.print_help()
|
||||
return 1
|
||||
if options.height > 0:
|
||||
options.sourceDir = args[0]
|
||||
options.targetDir = args[0] + "-Splitted"
|
||||
if os.path.isdir(options.sourceDir):
|
||||
rmtree(options.targetDir, True)
|
||||
copytree(options.sourceDir, options.targetDir)
|
||||
work = []
|
||||
pagenumber = 1
|
||||
splitWorkerOutput = []
|
||||
splitWorkerPool = Pool(maxtasksperchild=10)
|
||||
if options.merge:
|
||||
print("Merging images...")
|
||||
directoryNumer = 1
|
||||
mergeWork = []
|
||||
mergeWorkerOutput = []
|
||||
mergeWorkerPool = Pool(maxtasksperchild=10)
|
||||
mergeWork.append([options.targetDir])
|
||||
for root, dirs, files in os.walk(options.targetDir, False):
|
||||
dirs, files = walkSort(dirs, files)
|
||||
for directory in dirs:
|
||||
directoryNumer += 1
|
||||
mergeWork.append([os.path.join(root, directory)])
|
||||
if GUI:
|
||||
GUI.progressBarTick.emit('Combining images')
|
||||
GUI.progressBarTick.emit(str(directoryNumer))
|
||||
for i in mergeWork:
|
||||
mergeWorkerPool.apply_async(func=mergeDirectory, args=(i, ), callback=mergeDirectoryTick)
|
||||
mergeWorkerPool.close()
|
||||
mergeWorkerPool.join()
|
||||
if GUI and not GUI.conversionAlive:
|
||||
rmtree(options.targetDir, True)
|
||||
raise UserWarning("Conversion interrupted.")
|
||||
if len(mergeWorkerOutput) > 0:
|
||||
rmtree(options.targetDir, True)
|
||||
raise RuntimeError("One of workers crashed. Cause: " + mergeWorkerOutput[0][0],
|
||||
mergeWorkerOutput[0][1])
|
||||
print("Splitting images...")
|
||||
for root, _, files in os.walk(options.targetDir, False):
|
||||
for name in files:
|
||||
if getImageFileName(name) is not None:
|
||||
pagenumber += 1
|
||||
work.append([root, name, options])
|
||||
else:
|
||||
os.remove(os.path.join(root, name))
|
||||
if GUI:
|
||||
GUI.progressBarTick.emit('Splitting images')
|
||||
GUI.progressBarTick.emit(str(pagenumber))
|
||||
GUI.progressBarTick.emit('tick')
|
||||
if len(work) > 0:
|
||||
for i in work:
|
||||
splitWorkerPool.apply_async(func=splitImage, args=(i, ), callback=splitImageTick)
|
||||
splitWorkerPool.close()
|
||||
splitWorkerPool.join()
|
||||
if GUI and not GUI.conversionAlive:
|
||||
rmtree(options.targetDir, True)
|
||||
raise UserWarning("Conversion interrupted.")
|
||||
if len(splitWorkerOutput) > 0:
|
||||
rmtree(options.targetDir, True)
|
||||
raise RuntimeError("One of workers crashed. Cause: " + splitWorkerOutput[0][0],
|
||||
splitWorkerOutput[0][1])
|
||||
if options.inPlace:
|
||||
rmtree(options.sourceDir)
|
||||
move(options.targetDir, options.sourceDir)
|
||||
else:
|
||||
rmtree(options.targetDir, True)
|
||||
raise UserWarning("Source directory is empty.")
|
||||
else:
|
||||
raise UserWarning("Provided path is not a directory.")
|
||||
else:
|
||||
raise UserWarning("Target height is not set.")
|
||||
81
kindlecomicconverter/comicarchive.py
Normal file
81
kindlecomicconverter/comicarchive.py
Normal file
@@ -0,0 +1,81 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||
# Copyright (c) 2013-2019 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for
|
||||
# any purpose with or without fee is hereby granted, provided that the
|
||||
# above copyright notice and this permission notice appear in all
|
||||
# copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
# AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
|
||||
# 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 os
|
||||
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
|
||||
|
||||
|
||||
class ComicArchive:
|
||||
def __init__(self, filepath):
|
||||
self.filepath = filepath
|
||||
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, shell=True)
|
||||
for line in process.stdout:
|
||||
if b'Type =' in line:
|
||||
self.type = line.rstrip().decode().split(' = ')[1].upper()
|
||||
break
|
||||
process.communicate()
|
||||
if process.returncode != 0:
|
||||
raise OSError('Archive is corrupted or encrypted.')
|
||||
elif self.type not in ['7Z', 'RAR', 'RAR5', 'ZIP']:
|
||||
raise OSError('Unsupported archive format.')
|
||||
|
||||
def extract(self, targetdir):
|
||||
if not os.path.isdir(targetdir):
|
||||
raise OSError('Target directory don\'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, shell=True)
|
||||
process.communicate()
|
||||
if process.returncode != 0:
|
||||
raise OSError('Failed to extract archive.')
|
||||
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, shell=True)
|
||||
process.communicate()
|
||||
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, shell=True)
|
||||
xml = process.communicate()
|
||||
if process.returncode != 0:
|
||||
raise OSError('Failed to extract archive.')
|
||||
try:
|
||||
return parseString(xml[0])
|
||||
except ExpatError:
|
||||
return None
|
||||
186
kindlecomicconverter/dualmetafix.py
Normal file
186
kindlecomicconverter/dualmetafix.py
Normal file
@@ -0,0 +1,186 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Based on initial version of DualMetaFix. Copyright (C) 2013 Kevin Hendricks
|
||||
# Changes for KCC Copyright (C) 2014-2019 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import struct
|
||||
import mmap
|
||||
import shutil
|
||||
|
||||
|
||||
class DualMetaFixException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
# palm database offset constants
|
||||
number_of_pdb_records = 76
|
||||
first_pdb_record = 78
|
||||
|
||||
# important rec0 offsets
|
||||
mobi_header_base = 16
|
||||
mobi_header_length = 20
|
||||
mobi_version = 36
|
||||
title_offset = 84
|
||||
|
||||
|
||||
def getint(data, ofs, sz='L'):
|
||||
i, = struct.unpack_from('>' + sz, data, ofs)
|
||||
return i
|
||||
|
||||
|
||||
def writeint(data, ofs, n, slen='L'):
|
||||
if slen == 'L':
|
||||
return data[:ofs] + struct.pack('>L', n) + data[ofs + 4:]
|
||||
else:
|
||||
return data[:ofs] + struct.pack('>H', n) + data[ofs + 2:]
|
||||
|
||||
|
||||
def getsecaddr(datain, secno):
|
||||
nsec = getint(datain, number_of_pdb_records, 'H')
|
||||
if (secno < 0) | (secno >= nsec):
|
||||
emsg = 'requested section number %d out of range (nsec=%d)' % (secno, nsec)
|
||||
raise DualMetaFixException(emsg)
|
||||
secstart = getint(datain, first_pdb_record + secno * 8)
|
||||
if secno == nsec - 1:
|
||||
secend = len(datain)
|
||||
else:
|
||||
secend = getint(datain, first_pdb_record + (secno + 1) * 8)
|
||||
return secstart, secend
|
||||
|
||||
|
||||
def readsection(datain, secno):
|
||||
secstart, secend = getsecaddr(datain, secno)
|
||||
return datain[secstart:secend]
|
||||
|
||||
|
||||
# overwrite section - must be exact same length as original
|
||||
def replacesection(datain, secno, secdata):
|
||||
secstart, secend = getsecaddr(datain, secno)
|
||||
seclen = secend - secstart
|
||||
if len(secdata) != seclen:
|
||||
raise DualMetaFixException('section length change in replacesection')
|
||||
datain[secstart:secstart + seclen] = secdata
|
||||
|
||||
|
||||
def get_exth_params(rec0):
|
||||
ebase = mobi_header_base + getint(rec0, mobi_header_length)
|
||||
if rec0[ebase:ebase + 4] != b'EXTH':
|
||||
raise DualMetaFixException('EXTH tag not found where expected')
|
||||
elen = getint(rec0, ebase + 4)
|
||||
enum = getint(rec0, ebase + 8)
|
||||
rlen = len(rec0)
|
||||
return ebase, elen, enum, rlen
|
||||
|
||||
|
||||
def add_exth(rec0, exth_num, exth_bytes):
|
||||
ebase, elen, enum, rlen = get_exth_params(rec0)
|
||||
newrecsize = 8 + len(exth_bytes)
|
||||
newrec0 = rec0[0:ebase + 4] + struct.pack('>L', elen + newrecsize) + struct.pack('>L', enum + 1) + \
|
||||
struct.pack('>L', exth_num) + struct.pack('>L', newrecsize) + exth_bytes + rec0[ebase + 12:]
|
||||
newrec0 = writeint(newrec0, title_offset, getint(newrec0, title_offset) + newrecsize)
|
||||
# keep constant record length by removing newrecsize null bytes from end
|
||||
sectail = newrec0[-newrecsize:]
|
||||
if sectail != b'\0' * newrecsize:
|
||||
raise DualMetaFixException('add_exth: trimmed non-null bytes at end of section')
|
||||
newrec0 = newrec0[0:rlen]
|
||||
return newrec0
|
||||
|
||||
|
||||
def read_exth(rec0, exth_num):
|
||||
exth_values = []
|
||||
ebase, elen, enum, rlen = get_exth_params(rec0)
|
||||
ebase += 12
|
||||
while enum > 0:
|
||||
exth_id = getint(rec0, ebase)
|
||||
if exth_id == exth_num:
|
||||
# We might have multiple exths, so build a list.
|
||||
exth_values.append(rec0[ebase + 8:ebase + getint(rec0, ebase + 4)])
|
||||
enum -= 1
|
||||
ebase = ebase + getint(rec0, ebase + 4)
|
||||
return exth_values
|
||||
|
||||
|
||||
def del_exth(rec0, exth_num):
|
||||
ebase, elen, enum, rlen = get_exth_params(rec0)
|
||||
ebase_idx = ebase + 12
|
||||
enum_idx = 0
|
||||
while enum_idx < enum:
|
||||
exth_id = getint(rec0, ebase_idx)
|
||||
exth_size = getint(rec0, ebase_idx + 4)
|
||||
if exth_id == exth_num:
|
||||
newrec0 = rec0
|
||||
newrec0 = writeint(newrec0, title_offset, getint(newrec0, title_offset) - exth_size)
|
||||
newrec0 = newrec0[:ebase_idx] + newrec0[ebase_idx + exth_size:]
|
||||
newrec0 = newrec0[0:ebase + 4] + struct.pack('>L', elen - exth_size) + \
|
||||
struct.pack('>L', enum - 1) + newrec0[ebase + 12:]
|
||||
newrec0 += b'\0' * exth_size
|
||||
if rlen != len(newrec0):
|
||||
raise DualMetaFixException('del_exth: incorrect section size change')
|
||||
return newrec0
|
||||
enum_idx += 1
|
||||
ebase_idx = ebase_idx + exth_size
|
||||
return rec0
|
||||
|
||||
|
||||
class DualMobiMetaFix:
|
||||
def __init__(self, infile, outfile, asin):
|
||||
shutil.copyfile(infile, outfile)
|
||||
f = open(outfile, "r+b")
|
||||
self.datain = mmap.mmap(f.fileno(), 0)
|
||||
self.datain_rec0 = readsection(self.datain, 0)
|
||||
|
||||
# in the first mobi header
|
||||
# add 501 to "EBOK", add 113 as asin, add 504 as asin
|
||||
rec0 = self.datain_rec0
|
||||
rec0 = del_exth(rec0, 501)
|
||||
rec0 = del_exth(rec0, 113)
|
||||
rec0 = del_exth(rec0, 504)
|
||||
rec0 = add_exth(rec0, 501, b'EBOK')
|
||||
rec0 = add_exth(rec0, 113, asin)
|
||||
rec0 = add_exth(rec0, 504, asin)
|
||||
replacesection(self.datain, 0, rec0)
|
||||
|
||||
ver = getint(self.datain_rec0, mobi_version)
|
||||
self.combo = (ver != 8)
|
||||
if not self.combo:
|
||||
return
|
||||
|
||||
exth121 = read_exth(self.datain_rec0, 121)
|
||||
if len(exth121) == 0:
|
||||
self.combo = False
|
||||
return
|
||||
else:
|
||||
# only pay attention to first exth121
|
||||
# (there should only be one)
|
||||
datain_kf8, = struct.unpack_from('>L', exth121[0], 0)
|
||||
if datain_kf8 == 0xffffffff:
|
||||
self.combo = False
|
||||
return
|
||||
self.datain_kfrec0 = readsection(self.datain, datain_kf8)
|
||||
|
||||
# in the second header
|
||||
# add 501 to "EBOK", add 113 as asin, add 504 as asin
|
||||
rec0 = self.datain_kfrec0
|
||||
rec0 = del_exth(rec0, 501)
|
||||
rec0 = del_exth(rec0, 113)
|
||||
rec0 = del_exth(rec0, 504)
|
||||
rec0 = add_exth(rec0, 501, b'EBOK')
|
||||
rec0 = add_exth(rec0, 113, asin)
|
||||
rec0 = add_exth(rec0, 504, asin)
|
||||
replacesection(self.datain, datain_kf8, rec0)
|
||||
|
||||
self.datain.flush()
|
||||
self.datain.close()
|
||||
369
kindlecomicconverter/image.py
Executable file
369
kindlecomicconverter/image.py
Executable file
@@ -0,0 +1,369 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2010 Alex Yatskov
|
||||
# Copyright (C) 2011 Stanislav (proDOOMman) Kosolapov <prodoomman@gmail.com>
|
||||
# Copyright (c) 2016 Alberto Planas <aplanas@gmail.com>
|
||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||
# Copyright (c) 2013-2019 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
from PIL import Image, ImageOps, ImageStat, ImageChops, ImageFilter
|
||||
from .shared import md5Checksum
|
||||
|
||||
|
||||
class ProfileData:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
Palette4 = [
|
||||
0x00, 0x00, 0x00,
|
||||
0x55, 0x55, 0x55,
|
||||
0xaa, 0xaa, 0xaa,
|
||||
0xff, 0xff, 0xff
|
||||
]
|
||||
|
||||
Palette15 = [
|
||||
0x00, 0x00, 0x00,
|
||||
0x11, 0x11, 0x11,
|
||||
0x22, 0x22, 0x22,
|
||||
0x33, 0x33, 0x33,
|
||||
0x44, 0x44, 0x44,
|
||||
0x55, 0x55, 0x55,
|
||||
0x66, 0x66, 0x66,
|
||||
0x77, 0x77, 0x77,
|
||||
0x88, 0x88, 0x88,
|
||||
0x99, 0x99, 0x99,
|
||||
0xaa, 0xaa, 0xaa,
|
||||
0xbb, 0xbb, 0xbb,
|
||||
0xcc, 0xcc, 0xcc,
|
||||
0xdd, 0xdd, 0xdd,
|
||||
0xff, 0xff, 0xff,
|
||||
]
|
||||
|
||||
Palette16 = [
|
||||
0x00, 0x00, 0x00,
|
||||
0x11, 0x11, 0x11,
|
||||
0x22, 0x22, 0x22,
|
||||
0x33, 0x33, 0x33,
|
||||
0x44, 0x44, 0x44,
|
||||
0x55, 0x55, 0x55,
|
||||
0x66, 0x66, 0x66,
|
||||
0x77, 0x77, 0x77,
|
||||
0x88, 0x88, 0x88,
|
||||
0x99, 0x99, 0x99,
|
||||
0xaa, 0xaa, 0xaa,
|
||||
0xbb, 0xbb, 0xbb,
|
||||
0xcc, 0xcc, 0xcc,
|
||||
0xdd, 0xdd, 0xdd,
|
||||
0xee, 0xee, 0xee,
|
||||
0xff, 0xff, 0xff,
|
||||
]
|
||||
|
||||
PalleteNull = [
|
||||
]
|
||||
|
||||
Profiles = {
|
||||
'K1': ("Kindle 1", (600, 670), Palette4, 1.8),
|
||||
'K2': ("Kindle 2", (600, 670), Palette15, 1.8),
|
||||
'K34': ("Kindle Keyboard/Touch", (600, 800), Palette16, 1.8),
|
||||
'K578': ("Kindle", (600, 800), Palette16, 1.8),
|
||||
'KDX': ("Kindle DX/DXG", (824, 1000), Palette16, 1.8),
|
||||
'KPW': ("Kindle Paperwhite 1/2", (758, 1024), Palette16, 1.8),
|
||||
'KV': ("Kindle Paperwhite 3/4/Voyage/Oasis", (1072, 1448), Palette16, 1.8),
|
||||
'KO': ("Kindle Oasis 2", (1264, 1680), Palette16, 1.8),
|
||||
'KoMT': ("Kobo Mini/Touch", (600, 800), Palette16, 1.8),
|
||||
'KoG': ("Kobo Glo", (768, 1024), Palette16, 1.8),
|
||||
'KoGHD': ("Kobo Glo HD", (1072, 1448), Palette16, 1.8),
|
||||
'KoA': ("Kobo Aura", (758, 1024), Palette16, 1.8),
|
||||
'KoAHD': ("Kobo Aura HD", (1080, 1440), Palette16, 1.8),
|
||||
'KoAH2O': ("Kobo Aura H2O", (1080, 1430), Palette16, 1.8),
|
||||
'KoAO': ("Kobo Aura ONE", (1404, 1872), Palette16, 1.8),
|
||||
'KoF': ("Kobo Forma", (1440, 1920), Palette16, 1.8),
|
||||
'OTHER': ("Other", (0, 0), Palette16, 1.8),
|
||||
}
|
||||
|
||||
|
||||
class ComicPageParser:
|
||||
def __init__(self, source, options):
|
||||
Image.MAX_IMAGE_PIXELS = int(2048 * 2048 * 2048 // 4 // 3)
|
||||
self.opt = options
|
||||
self.source = source
|
||||
self.size = self.opt.profileData[1]
|
||||
self.payload = []
|
||||
self.image = Image.open(os.path.join(source[0], source[1])).convert('RGB')
|
||||
self.color = self.colorCheck()
|
||||
self.fill = self.fillCheck()
|
||||
self.splitCheck()
|
||||
|
||||
def getImageHistogram(self, image):
|
||||
histogram = image.histogram()
|
||||
if histogram[0] == 0:
|
||||
return -1
|
||||
elif histogram[255] == 0:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
|
||||
def splitCheck(self):
|
||||
width, height = self.image.size
|
||||
dstwidth, dstheight = self.size
|
||||
if (width > height) != (dstwidth > dstheight) and width <= dstheight and height <= dstwidth \
|
||||
and not self.opt.webtoon and self.opt.splitter == 1:
|
||||
self.payload.append(['R', self.source, self.image.rotate(90, Image.BICUBIC, True), self.color, self.fill])
|
||||
elif (width > height) != (dstwidth > dstheight) and not self.opt.webtoon:
|
||||
if self.opt.splitter != 1:
|
||||
if width > height:
|
||||
leftbox = (0, 0, int(width / 2), height)
|
||||
rightbox = (int(width / 2), 0, width, height)
|
||||
else:
|
||||
leftbox = (0, 0, width, int(height / 2))
|
||||
rightbox = (0, int(height / 2), width, height)
|
||||
if self.opt.righttoleft:
|
||||
pageone = self.image.crop(rightbox)
|
||||
pagetwo = self.image.crop(leftbox)
|
||||
else:
|
||||
pageone = self.image.crop(leftbox)
|
||||
pagetwo = self.image.crop(rightbox)
|
||||
self.payload.append(['S1', self.source, pageone, self.color, self.fill])
|
||||
self.payload.append(['S2', self.source, pagetwo, self.color, self.fill])
|
||||
if self.opt.splitter > 0:
|
||||
self.payload.append(['R', self.source, self.image.rotate(90, Image.BICUBIC, True),
|
||||
self.color, self.fill])
|
||||
else:
|
||||
self.payload.append(['N', self.source, self.image, self.color, self.fill])
|
||||
|
||||
def colorCheck(self):
|
||||
if self.opt.webtoon:
|
||||
return True
|
||||
else:
|
||||
img = self.image.copy()
|
||||
bands = img.getbands()
|
||||
if bands == ('R', 'G', 'B') or bands == ('R', 'G', 'B', 'A'):
|
||||
thumb = img.resize((40, 40))
|
||||
SSE, bias = 0, [0, 0, 0]
|
||||
bias = ImageStat.Stat(thumb).mean[:3]
|
||||
bias = [b - sum(bias) / 3 for b in bias]
|
||||
for pixel in thumb.getdata():
|
||||
mu = sum(pixel) / 3
|
||||
SSE += sum((pixel[i] - mu - bias[i]) * (pixel[i] - mu - bias[i]) for i in [0, 1, 2])
|
||||
MSE = float(SSE) / (40 * 40)
|
||||
if MSE > 22:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
|
||||
def fillCheck(self):
|
||||
if self.opt.bordersColor:
|
||||
return self.opt.bordersColor
|
||||
else:
|
||||
bw = self.image.convert('L').point(lambda x: 0 if x < 128 else 255, '1')
|
||||
imageBoxA = bw.getbbox()
|
||||
imageBoxB = ImageChops.invert(bw).getbbox()
|
||||
if imageBoxA is None or imageBoxB is None:
|
||||
surfaceB, surfaceW = 0, 0
|
||||
diff = 0
|
||||
else:
|
||||
surfaceB = (imageBoxA[2] - imageBoxA[0]) * (imageBoxA[3] - imageBoxA[1])
|
||||
surfaceW = (imageBoxB[2] - imageBoxB[0]) * (imageBoxB[3] - imageBoxB[1])
|
||||
diff = ((max(surfaceB, surfaceW) - min(surfaceB, surfaceW)) / min(surfaceB, surfaceW)) * 100
|
||||
if diff > 0.5:
|
||||
if surfaceW < surfaceB:
|
||||
return 'white'
|
||||
elif surfaceW > surfaceB:
|
||||
return 'black'
|
||||
else:
|
||||
fill = 0
|
||||
startY = 0
|
||||
while startY < bw.size[1]:
|
||||
if startY + 5 > bw.size[1]:
|
||||
startY = bw.size[1] - 5
|
||||
fill += self.getImageHistogram(bw.crop((0, startY, bw.size[0], startY + 5)))
|
||||
startY += 5
|
||||
startX = 0
|
||||
while startX < bw.size[0]:
|
||||
if startX + 5 > bw.size[0]:
|
||||
startX = bw.size[0] - 5
|
||||
fill += self.getImageHistogram(bw.crop((startX, 0, startX + 5, bw.size[1])))
|
||||
startX += 5
|
||||
if fill > 0:
|
||||
return 'black'
|
||||
else:
|
||||
return 'white'
|
||||
|
||||
|
||||
class ComicPage:
|
||||
def __init__(self, options, mode, path, image, color, fill):
|
||||
self.opt = options
|
||||
_, self.size, self.palette, self.gamma = self.opt.profileData
|
||||
if self.opt.hq:
|
||||
self.size = (int(self.size[0] * 1.5), int(self.size[1] * 1.5))
|
||||
self.image = image
|
||||
self.color = color
|
||||
self.fill = fill
|
||||
self.rotated = False
|
||||
self.orgPath = os.path.join(path[0], path[1])
|
||||
if 'N' in mode:
|
||||
self.targetPath = os.path.join(path[0], os.path.splitext(path[1])[0]) + '-KCC'
|
||||
elif 'R' in mode:
|
||||
self.targetPath = os.path.join(path[0], os.path.splitext(path[1])[0]) + '-KCC-A'
|
||||
self.rotated = True
|
||||
elif 'S1' in mode:
|
||||
self.targetPath = os.path.join(path[0], os.path.splitext(path[1])[0]) + '-KCC-B'
|
||||
elif 'S2' in mode:
|
||||
self.targetPath = os.path.join(path[0], os.path.splitext(path[1])[0]) + '-KCC-C'
|
||||
|
||||
def saveToDir(self):
|
||||
try:
|
||||
flags = []
|
||||
if not self.opt.forcecolor and not self.opt.forcepng:
|
||||
self.image = self.image.convert('L')
|
||||
if self.rotated:
|
||||
flags.append('Rotated')
|
||||
if self.fill != 'white':
|
||||
flags.append('BlackBackground')
|
||||
if self.opt.forcepng:
|
||||
self.targetPath += '.png'
|
||||
self.image.save(self.targetPath, 'PNG', optimize=1)
|
||||
else:
|
||||
self.targetPath += '.jpg'
|
||||
self.image.save(self.targetPath, 'JPEG', optimize=1, quality=85)
|
||||
return [md5Checksum(self.targetPath), flags, self.orgPath]
|
||||
except IOError as err:
|
||||
raise RuntimeError('Cannot save image. ' + str(err))
|
||||
|
||||
def autocontrastImage(self):
|
||||
gamma = self.opt.gamma
|
||||
if gamma < 0.1:
|
||||
gamma = self.gamma
|
||||
if self.gamma != 1.0 and self.color:
|
||||
gamma = 1.0
|
||||
if gamma == 1.0:
|
||||
self.image = ImageOps.autocontrast(self.image)
|
||||
else:
|
||||
self.image = ImageOps.autocontrast(Image.eval(self.image, lambda a: 255 * (a / 255.) ** gamma))
|
||||
|
||||
def quantizeImage(self):
|
||||
colors = len(self.palette) // 3
|
||||
if colors < 256:
|
||||
self.palette += self.palette[:3] * (256 - colors)
|
||||
palImg = Image.new('P', (1, 1))
|
||||
palImg.putpalette(self.palette)
|
||||
self.image = self.image.convert('L')
|
||||
self.image = self.image.convert('RGB')
|
||||
# Quantize is deprecated but new function call it internally anyway...
|
||||
self.image = self.image.quantize(palette=palImg)
|
||||
|
||||
def resizeImage(self):
|
||||
if self.image.size[0] <= self.size[0] and self.image.size[1] <= self.size[1]:
|
||||
method = Image.BICUBIC
|
||||
else:
|
||||
method = Image.LANCZOS
|
||||
if self.opt.stretch or (self.opt.kfx and ('-KCC-B' in self.targetPath or '-KCC-C' in self.targetPath)):
|
||||
self.image = self.image.resize(self.size, method)
|
||||
elif self.image.size[0] <= self.size[0] and self.image.size[1] <= self.size[1] and not self.opt.upscale:
|
||||
if self.opt.format == 'CBZ' or self.opt.kfx:
|
||||
borderw = int((self.size[0] - self.image.size[0]) / 2)
|
||||
borderh = int((self.size[1] - self.image.size[1]) / 2)
|
||||
self.image = ImageOps.expand(self.image, border=(borderw, borderh), fill=self.fill)
|
||||
if self.image.size[0] != self.size[0] or self.image.size[1] != self.size[1]:
|
||||
self.image = ImageOps.fit(self.image, self.size, method=Image.BICUBIC, centering=(0.5, 0.5))
|
||||
else:
|
||||
if self.opt.format == 'CBZ' or self.opt.kfx:
|
||||
ratioDev = float(self.size[0]) / float(self.size[1])
|
||||
if (float(self.image.size[0]) / float(self.image.size[1])) < ratioDev:
|
||||
diff = int(self.image.size[1] * ratioDev) - self.image.size[0]
|
||||
self.image = ImageOps.expand(self.image, border=(int(diff / 2), 0), fill=self.fill)
|
||||
elif (float(self.image.size[0]) / float(self.image.size[1])) > ratioDev:
|
||||
diff = int(self.image.size[0] / ratioDev) - self.image.size[1]
|
||||
self.image = ImageOps.expand(self.image, border=(0, int(diff / 2)), fill=self.fill)
|
||||
self.image = ImageOps.fit(self.image, self.size, method=method, centering=(0.5, 0.5))
|
||||
else:
|
||||
hpercent = self.size[1] / float(self.image.size[1])
|
||||
wsize = int((float(self.image.size[0]) * float(hpercent)))
|
||||
self.image = self.image.resize((wsize, self.size[1]), method)
|
||||
if self.image.size[0] > self.size[0] or self.image.size[1] > self.size[1]:
|
||||
self.image.thumbnail(self.size, Image.LANCZOS)
|
||||
|
||||
def getBoundingBox(self, tmptmg):
|
||||
min_margin = [int(0.005 * i + 0.5) for i in tmptmg.size]
|
||||
max_margin = [int(0.1 * i + 0.5) for i in tmptmg.size]
|
||||
bbox = tmptmg.getbbox()
|
||||
bbox = (
|
||||
max(0, min(max_margin[0], bbox[0] - min_margin[0])),
|
||||
max(0, min(max_margin[1], bbox[1] - min_margin[1])),
|
||||
min(tmptmg.size[0],
|
||||
max(tmptmg.size[0] - max_margin[0], bbox[2] + min_margin[0])),
|
||||
min(tmptmg.size[1],
|
||||
max(tmptmg.size[1] - max_margin[1], bbox[3] + min_margin[1])),
|
||||
)
|
||||
return bbox
|
||||
|
||||
def cropPageNumber(self, power):
|
||||
if self.fill != 'white':
|
||||
tmptmg = self.image.convert(mode='L')
|
||||
else:
|
||||
tmptmg = ImageOps.invert(self.image.convert(mode='L'))
|
||||
tmptmg = tmptmg.point(lambda x: x and 255)
|
||||
tmptmg = tmptmg.filter(ImageFilter.MinFilter(size=3))
|
||||
tmptmg = tmptmg.filter(ImageFilter.GaussianBlur(radius=5))
|
||||
tmptmg = tmptmg.point(lambda x: (x >= 16 * power) and x)
|
||||
self.image = self.image.crop(tmptmg.getbbox()) if tmptmg.getbbox() else self.image
|
||||
|
||||
def cropMargin(self, power):
|
||||
if self.fill != 'white':
|
||||
tmptmg = self.image.convert(mode='L')
|
||||
else:
|
||||
tmptmg = ImageOps.invert(self.image.convert(mode='L'))
|
||||
tmptmg = tmptmg.filter(ImageFilter.GaussianBlur(radius=3))
|
||||
tmptmg = tmptmg.point(lambda x: (x >= 16 * power) and x)
|
||||
self.image = self.image.crop(self.getBoundingBox(tmptmg)) if tmptmg.getbbox() else self.image
|
||||
|
||||
|
||||
class Cover:
|
||||
def __init__(self, source, target, opt, tomeid):
|
||||
self.options = opt
|
||||
self.source = source
|
||||
self.target = target
|
||||
if tomeid == 0:
|
||||
self.tomeid = 1
|
||||
else:
|
||||
self.tomeid = tomeid
|
||||
self.image = Image.open(source)
|
||||
self.process()
|
||||
|
||||
def process(self):
|
||||
self.image = self.image.convert('RGB')
|
||||
self.image = ImageOps.autocontrast(self.image)
|
||||
if not self.options.forcecolor:
|
||||
self.image = self.image.convert('L')
|
||||
self.image.thumbnail(self.options.profileData[1], Image.LANCZOS)
|
||||
self.save()
|
||||
|
||||
def save(self):
|
||||
try:
|
||||
self.image.save(self.target, "JPEG", optimize=1, quality=85)
|
||||
except IOError:
|
||||
raise RuntimeError('Failed to process downloaded cover.')
|
||||
|
||||
def saveToKindle(self, kindle, asin):
|
||||
self.image = self.image.resize((300, 470), Image.ANTIALIAS)
|
||||
try:
|
||||
self.image.save(os.path.join(kindle.path.split('documents')[0], 'system', 'thumbnails',
|
||||
'thumbnail_' + asin + '_EBOK_portrait.jpg'), 'JPEG', optimize=1, quality=85)
|
||||
except IOError:
|
||||
raise RuntimeError('Failed to upload cover.')
|
||||
44
kindlecomicconverter/kindle.py
Normal file
44
kindlecomicconverter/kindle.py
Normal file
@@ -0,0 +1,44 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2013-2019 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for
|
||||
# any purpose with or without fee is hereby granted, provided that the
|
||||
# above copyright notice and this permission notice appear in all
|
||||
# copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
# AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
|
||||
# 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 os.path
|
||||
import psutil
|
||||
|
||||
|
||||
class Kindle:
|
||||
def __init__(self):
|
||||
self.path = self.findDevice()
|
||||
if self.path:
|
||||
self.coverSupport = self.checkThumbnails()
|
||||
else:
|
||||
self.coverSupport = False
|
||||
|
||||
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]):
|
||||
if os.path.isdir(os.path.join(drive[1], 'system')) and \
|
||||
os.path.isdir(os.path.join(drive[1], 'documents')):
|
||||
return drive[1]
|
||||
return False
|
||||
|
||||
def checkThumbnails(self):
|
||||
if os.path.isdir(os.path.join(self.path, 'system', 'thumbnails')):
|
||||
return True
|
||||
return False
|
||||
120
kindlecomicconverter/metadata.py
Normal file
120
kindlecomicconverter/metadata.py
Normal file
@@ -0,0 +1,120 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2013-2019 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for
|
||||
# any purpose with or without fee is hereby granted, provided that the
|
||||
# above copyright notice and this permission notice appear in all
|
||||
# copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
# AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
|
||||
# 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 os
|
||||
from xml.dom.minidom import parse, Document
|
||||
from tempfile import mkdtemp
|
||||
from shutil import rmtree
|
||||
from . import comicarchive
|
||||
|
||||
|
||||
class MetadataParser:
|
||||
def __init__(self, source):
|
||||
self.source = source
|
||||
self.data = {'Series': '',
|
||||
'Volume': '',
|
||||
'Number': '',
|
||||
'Writers': [],
|
||||
'Pencillers': [],
|
||||
'Inkers': [],
|
||||
'Colorists': [],
|
||||
'Summary': '',
|
||||
'Bookmarks': []}
|
||||
self.rawdata = None
|
||||
self.format = None
|
||||
if self.source.endswith('.xml') and os.path.exists(self.source):
|
||||
self.rawdata = parse(self.source)
|
||||
elif not self.source.endswith('.xml'):
|
||||
try:
|
||||
cbx = comicarchive.ComicArchive(self.source)
|
||||
self.rawdata = cbx.extractMetadata()
|
||||
self.format = cbx.type
|
||||
except OSError as e:
|
||||
raise UserWarning(e.strerror)
|
||||
if self.rawdata:
|
||||
self.parseXML()
|
||||
|
||||
def parseXML(self):
|
||||
if len(self.rawdata.getElementsByTagName('Series')) != 0:
|
||||
self.data['Series'] = self.rawdata.getElementsByTagName('Series')[0].firstChild.nodeValue
|
||||
if len(self.rawdata.getElementsByTagName('Volume')) != 0:
|
||||
self.data['Volume'] = self.rawdata.getElementsByTagName('Volume')[0].firstChild.nodeValue
|
||||
if len(self.rawdata.getElementsByTagName('Number')) != 0:
|
||||
self.data['Number'] = self.rawdata.getElementsByTagName('Number')[0].firstChild.nodeValue
|
||||
if len(self.rawdata.getElementsByTagName('Summary')) != 0:
|
||||
self.data['Summary'] = self.rawdata.getElementsByTagName('Summary')[0].firstChild.nodeValue
|
||||
for field in ['Writer', 'Penciller', 'Inker', 'Colorist']:
|
||||
if len(self.rawdata.getElementsByTagName(field)) != 0:
|
||||
for person in self.rawdata.getElementsByTagName(field)[0].firstChild.nodeValue.split(', '):
|
||||
self.data[field + 's'].append(person)
|
||||
self.data[field + 's'] = list(set(self.data[field + 's']))
|
||||
self.data[field + 's'].sort()
|
||||
if len(self.rawdata.getElementsByTagName('Page')) != 0:
|
||||
for page in self.rawdata.getElementsByTagName('Page'):
|
||||
if 'Bookmark' in page.attributes and 'Image' in page.attributes:
|
||||
self.data['Bookmarks'].append((int(page.attributes['Image'].value),
|
||||
page.attributes['Bookmark'].value))
|
||||
|
||||
def saveXML(self):
|
||||
if self.rawdata:
|
||||
root = self.rawdata.getElementsByTagName('ComicInfo')[0]
|
||||
for row in (['Series', self.data['Series']], ['Volume', self.data['Volume']],
|
||||
['Number', self.data['Number']], ['Writer', ', '.join(self.data['Writers'])],
|
||||
['Penciller', ', '.join(self.data['Pencillers'])], ['Inker', ', '.join(self.data['Inkers'])],
|
||||
['Colorist', ', '.join(self.data['Colorists'])], ['Summary', self.data['Summary']]):
|
||||
if self.rawdata.getElementsByTagName(row[0]):
|
||||
node = self.rawdata.getElementsByTagName(row[0])[0]
|
||||
if row[1]:
|
||||
node.firstChild.replaceWholeText(row[1])
|
||||
else:
|
||||
root.removeChild(node)
|
||||
elif row[1]:
|
||||
main = self.rawdata.createElement(row[0])
|
||||
root.appendChild(main)
|
||||
text = self.rawdata.createTextNode(row[1])
|
||||
main.appendChild(text)
|
||||
else:
|
||||
doc = Document()
|
||||
root = doc.createElement('ComicInfo')
|
||||
root.setAttribute('xmlns:xsd', 'http://www.w3.org/2001/XMLSchema')
|
||||
root.setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance')
|
||||
doc.appendChild(root)
|
||||
for row in (['Series', self.data['Series']], ['Volume', self.data['Volume']],
|
||||
['Number', self.data['Number']], ['Writer', ', '.join(self.data['Writers'])],
|
||||
['Penciller', ', '.join(self.data['Pencillers'])], ['Inker', ', '.join(self.data['Inkers'])],
|
||||
['Colorist', ', '.join(self.data['Colorists'])], ['Summary', self.data['Summary']]):
|
||||
if row[1]:
|
||||
main = doc.createElement(row[0])
|
||||
root.appendChild(main)
|
||||
text = doc.createTextNode(row[1])
|
||||
main.appendChild(text)
|
||||
self.rawdata = doc
|
||||
if self.source.endswith('.xml'):
|
||||
with open(self.source, 'w', encoding='utf-8') as f:
|
||||
self.rawdata.writexml(f, encoding='utf-8')
|
||||
else:
|
||||
workdir = mkdtemp('', 'KCC-')
|
||||
tmpXML = os.path.join(workdir, 'ComicInfo.xml')
|
||||
with open(tmpXML, 'w', encoding='utf-8') as f:
|
||||
self.rawdata.writexml(f, encoding='utf-8')
|
||||
try:
|
||||
cbx = comicarchive.ComicArchive(self.source)
|
||||
cbx.addFile(tmpXML)
|
||||
except OSError as e:
|
||||
raise UserWarning(e.strerror)
|
||||
rmtree(workdir)
|
||||
@@ -1,5 +1,7 @@
|
||||
# Copyright (c) 2012-2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||
# Copyright (c) 2013 Pawel Jastrzebski <pawelj@vulturis.eu>
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||
# Copyright (c) 2013-2019 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||
#
|
||||
# Based upon the code snippet by Ned Batchelder
|
||||
# (http://nedbatchelder.com/blog/200712/extracting_jpgs_from_pdfs.html)
|
||||
@@ -19,56 +21,49 @@
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
|
||||
__license__ = 'ISC'
|
||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import os
|
||||
from random import choice
|
||||
from string import ascii_uppercase, digits
|
||||
|
||||
|
||||
class PdfJpgExtract:
|
||||
def __init__(self, origFileName):
|
||||
self.origFileName = origFileName
|
||||
self.filename = os.path.splitext(origFileName)
|
||||
self.path = self.filename[0] + "-KCC-TMP"
|
||||
def __init__(self, fname):
|
||||
self.fname = fname
|
||||
self.filename = os.path.splitext(fname)
|
||||
self.path = self.filename[0] + "-KCC-" + ''.join(choice(ascii_uppercase + digits) for _ in range(3))
|
||||
|
||||
def getPath(self):
|
||||
return self.path
|
||||
|
||||
def extract(self):
|
||||
pdf = file(self.origFileName, "rb").read()
|
||||
|
||||
startmark = "\xff\xd8"
|
||||
pdf = open(self.fname, "rb").read()
|
||||
startmark = b"\xff\xd8"
|
||||
startfix = 0
|
||||
endmark = "\xff\xd9"
|
||||
endmark = b"\xff\xd9"
|
||||
endfix = 2
|
||||
i = 0
|
||||
|
||||
njpg = 0
|
||||
os.makedirs(self.path)
|
||||
while True:
|
||||
istream = pdf.find("stream", i)
|
||||
istream = pdf.find(b"stream", i)
|
||||
if istream < 0:
|
||||
break
|
||||
istart = pdf.find(startmark, istream, istream + 20)
|
||||
if istart < 0:
|
||||
i = istream + 20
|
||||
continue
|
||||
iend = pdf.find("endstream", istart)
|
||||
iend = pdf.find(b"endstream", istart)
|
||||
if iend < 0:
|
||||
raise Exception("Didn't find end of stream!")
|
||||
iend = pdf.find(endmark, iend - 20)
|
||||
if iend < 0:
|
||||
raise Exception("Didn't find end of JPG!")
|
||||
|
||||
istart += startfix
|
||||
iend += endfix
|
||||
print "JPG %d from %d to %d" % (njpg, istart, iend)
|
||||
jpg = pdf[istart:iend]
|
||||
jpgfile = file(self.path + "/jpg%d.jpg" % njpg, "wb")
|
||||
jpgfile = open(self.path + "/jpg%d.jpg" % njpg, "wb")
|
||||
jpgfile.write(jpg)
|
||||
jpgfile.close()
|
||||
|
||||
njpg += 1
|
||||
i = iend
|
||||
return self.path, njpg
|
||||
133
kindlecomicconverter/shared.py
Normal file
133
kindlecomicconverter/shared.py
Normal file
@@ -0,0 +1,133 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||
# Copyright (c) 2013-2019 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for
|
||||
# any purpose with or without fee is hereby granted, provided that the
|
||||
# above copyright notice and this permission notice appear in all
|
||||
# copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
# AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
|
||||
# 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 os
|
||||
from hashlib import md5
|
||||
from html.parser import HTMLParser
|
||||
from distutils.version import StrictVersion
|
||||
from re import split
|
||||
from traceback import format_tb
|
||||
|
||||
|
||||
class HTMLStripper(HTMLParser):
|
||||
def __init__(self):
|
||||
HTMLParser.__init__(self)
|
||||
self.reset()
|
||||
self.strict = False
|
||||
self.convert_charrefs = True
|
||||
self.fed = []
|
||||
|
||||
def handle_data(self, d):
|
||||
self.fed.append(d)
|
||||
|
||||
def get_data(self):
|
||||
return ''.join(self.fed)
|
||||
|
||||
def error(self, message):
|
||||
pass
|
||||
|
||||
|
||||
def getImageFileName(imgfile):
|
||||
name, ext = os.path.splitext(imgfile)
|
||||
ext = ext.lower()
|
||||
if name.startswith('.') or ext not in ['.png', '.jpg', '.jpeg', '.gif', '.webp']:
|
||||
return None
|
||||
return [name, ext]
|
||||
|
||||
|
||||
def walkSort(dirnames, filenames):
|
||||
convert = lambda text: int(text) if text.isdigit() else text
|
||||
alphanum_key = lambda key: [convert(c) for c in split('([0-9]+)', key)]
|
||||
dirnames.sort(key=lambda name: alphanum_key(name.lower()))
|
||||
filenames.sort(key=lambda name: alphanum_key(name.lower()))
|
||||
return dirnames, filenames
|
||||
|
||||
|
||||
def walkLevel(some_dir, level=1):
|
||||
some_dir = some_dir.rstrip(os.path.sep)
|
||||
assert os.path.isdir(some_dir)
|
||||
num_sep = some_dir.count(os.path.sep)
|
||||
for root, dirs, files in os.walk(some_dir):
|
||||
dirs, files = walkSort(dirs, files)
|
||||
yield root, dirs, files
|
||||
num_sep_this = root.count(os.path.sep)
|
||||
if num_sep + level <= num_sep_this:
|
||||
del dirs[:]
|
||||
|
||||
|
||||
def md5Checksum(fpath):
|
||||
with open(fpath, 'rb') as fh:
|
||||
m = md5()
|
||||
while True:
|
||||
data = fh.read(8192)
|
||||
if not data:
|
||||
break
|
||||
m.update(data)
|
||||
return m.hexdigest()
|
||||
|
||||
|
||||
def sanitizeTrace(traceback):
|
||||
return ''.join(format_tb(traceback))\
|
||||
.replace('C:/projects/kcc/', '')\
|
||||
.replace('c:/projects/kcc/', '')\
|
||||
.replace('C:/python36-x64/', '')\
|
||||
.replace('c:/python36-x64/', '')\
|
||||
.replace('C:\\projects\\kcc\\', '')\
|
||||
.replace('c:\\projects\\kcc\\', '')\
|
||||
.replace('C:\\python36-x64\\', '')\
|
||||
.replace('c:\\python36-x64\\', '')
|
||||
|
||||
|
||||
# noinspection PyUnresolvedReferences
|
||||
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+')
|
||||
except ImportError:
|
||||
missing.append('PyQt 5.6.0+')
|
||||
try:
|
||||
import raven
|
||||
except ImportError:
|
||||
missing.append('raven 6.0.0+')
|
||||
if level > 1:
|
||||
try:
|
||||
from psutil import __version__ as psutilVersion
|
||||
if StrictVersion('5.0.0') > StrictVersion(psutilVersion):
|
||||
missing.append('psutil 5.0.0+')
|
||||
except ImportError:
|
||||
missing.append('psutil 5.0.0+')
|
||||
try:
|
||||
from slugify import __version__ as slugifyVersion
|
||||
if StrictVersion('1.2.1') > StrictVersion(slugifyVersion):
|
||||
missing.append('python-slugify 1.2.1+')
|
||||
except ImportError:
|
||||
missing.append('python-slugify 1.2.1+')
|
||||
try:
|
||||
from PIL import __version__ as pillowVersion
|
||||
if StrictVersion('5.2.0') > StrictVersion(pillowVersion):
|
||||
missing.append('Pillow 5.2.0+')
|
||||
except ImportError:
|
||||
missing.append('Pillow 5.2.0+')
|
||||
if len(missing) > 0:
|
||||
print('ERROR: ' + ', '.join(missing) + ' is not installed!')
|
||||
exit(1)
|
||||
56
kindlecomicconverter/startup.py
Normal file
56
kindlecomicconverter/startup.py
Normal file
@@ -0,0 +1,56 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||
# Copyright (c) 2013-2019 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for
|
||||
# any purpose with or without fee is hereby granted, provided that the
|
||||
# above copyright notice and this permission notice appear in all
|
||||
# copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
# AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
|
||||
# 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 os
|
||||
import sys
|
||||
from . import __version__
|
||||
from .shared import dependencyCheck
|
||||
|
||||
|
||||
def start():
|
||||
dependencyCheck(3)
|
||||
from . import KCC_gui
|
||||
os.environ['QT_AUTO_SCREEN_SCALE_FACTOR'] = "1"
|
||||
KCCAplication = KCC_gui.QApplicationMessaging(sys.argv)
|
||||
if KCCAplication.isRunning():
|
||||
for i in range(1, len(sys.argv)):
|
||||
KCCAplication.sendMessage(sys.argv[i])
|
||||
else:
|
||||
KCCAplication.sendMessage('ARISE')
|
||||
else:
|
||||
KCCWindow = KCC_gui.QMainWindowKCC()
|
||||
KCCUI = KCC_gui.KCCGUI(KCCAplication, KCCWindow)
|
||||
for i in range(1, len(sys.argv)):
|
||||
KCCUI.handleMessage(sys.argv[i])
|
||||
sys.exit(KCCAplication.exec_())
|
||||
|
||||
|
||||
def startC2E():
|
||||
dependencyCheck(2)
|
||||
from .comic2ebook import main
|
||||
print('comic2ebook v' + __version__ + ' - Written by Ciro Mattia Gonano and Pawel Jastrzebski.')
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
|
||||
|
||||
def startC2P():
|
||||
dependencyCheck(1)
|
||||
from .comic2panel import main
|
||||
print('comic2panel v' + __version__ + ' - Written by Ciro Mattia Gonano and Pawel Jastrzebski.')
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
@@ -1,91 +0,0 @@
|
||||
****** ***** ****** UnRAR - free utility for RAR archives
|
||||
** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
****** ******* ****** License for use and distribution of
|
||||
** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
** ** ** ** ** ** FREEWARE version
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
The UnRAR utility is freeware. This means:
|
||||
|
||||
1. All copyrights to RAR and the utility UnRAR are exclusively
|
||||
owned by the author - Alexander Roshal.
|
||||
|
||||
2. The UnRAR utility may be freely distributed. It is allowed
|
||||
to distribute UnRAR inside of other software packages.
|
||||
|
||||
3. THE RAR ARCHIVER AND THE UnRAR UTILITY ARE DISTRIBUTED "AS IS".
|
||||
NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED. YOU USE AT
|
||||
YOUR OWN RISK. THE AUTHOR WILL NOT BE LIABLE FOR DATA LOSS,
|
||||
DAMAGES, LOSS OF PROFITS OR ANY OTHER KIND OF LOSS WHILE USING
|
||||
OR MISUSING THIS SOFTWARE.
|
||||
|
||||
4. Neither RAR binary code, WinRAR binary code, UnRAR source or UnRAR
|
||||
binary code may be used or reverse engineered to re-create the RAR
|
||||
compression algorithm, which is proprietary, without written
|
||||
permission of the author.
|
||||
|
||||
5. If you don't agree with terms of the license you must remove
|
||||
UnRAR files from your storage devices and cease to use the
|
||||
utility.
|
||||
|
||||
Thank you for your interest in RAR and UnRAR.
|
||||
|
||||
|
||||
Alexander L. Roshal
|
||||
|
||||
7-Zip
|
||||
~~~~~
|
||||
License for use and distribution
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
7-Zip Copyright (C) 1999-2012 Igor Pavlov.
|
||||
|
||||
Licenses for files are:
|
||||
|
||||
1) 7z.dll: GNU LGPL + unRAR restriction
|
||||
2) All other files: GNU LGPL
|
||||
|
||||
The GNU LGPL + unRAR restriction means that you must follow both
|
||||
GNU LGPL rules and unRAR restriction rules.
|
||||
|
||||
|
||||
Note:
|
||||
You can use 7-Zip on any computer, including a computer in a commercial
|
||||
organization. You don't need to register or pay for 7-Zip.
|
||||
|
||||
|
||||
GNU LGPL information
|
||||
--------------------
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You can receive a copy of the GNU Lesser General Public License from
|
||||
http://www.gnu.org/
|
||||
|
||||
|
||||
unRAR restriction
|
||||
-----------------
|
||||
|
||||
The decompression engine for RAR archives was developed using source
|
||||
code of unRAR program.
|
||||
All copyrights to original unRAR code are owned by Alexander Roshal.
|
||||
|
||||
The license for original unRAR code has the following restriction:
|
||||
|
||||
The unRAR sources cannot be used to re-create the RAR compression algorithm,
|
||||
which is proprietary. Distribution of modified unRAR sources in separate form
|
||||
or as a part of other software is permitted, provided that it is clearly
|
||||
stated in the documentation and source comments that the code may
|
||||
not be used to develop a RAR (WinRAR) compatible archiver.
|
||||
|
||||
|
||||
--
|
||||
Igor Pavlov
|
||||
@@ -1,35 +0,0 @@
|
||||
--- qt-4.8.5/src/gui/kernel/qwidget_mac.mm 2013-06-07 07:16:59.000000000 +0200
|
||||
+++ qt-4.8.5-fix/src/gui/kernel/qwidget_mac.mm 2013-10-11 23:00:15.000000000 +0200
|
||||
@@ -4715,15 +4715,13 @@ void QWidgetPrivate::scroll_sys(int dx,
|
||||
}
|
||||
|
||||
// Scroll the whole widget if qscrollRect is not valid:
|
||||
- QRect validScrollRect = qscrollRect.isValid() ? qscrollRect : q->rect();
|
||||
- validScrollRect &= clipRect();
|
||||
+ QRect validScrollRect = qscrollRect.isValid() ? qscrollRect : QRect(0, 0, q->width(), q->height());
|
||||
|
||||
// If q is overlapped by other widgets, we cannot just blit pixels since
|
||||
// this will move overlapping widgets as well. In case we just update:
|
||||
const bool overlapped = isOverlapped(validScrollRect.translated(data.crect.topLeft()));
|
||||
const bool accelerateScroll = accelEnv && isOpaque && !overlapped;
|
||||
const bool isAlien = (q->internalWinId() == 0);
|
||||
- const QPoint scrollDelta(dx, dy);
|
||||
|
||||
// If qscrollRect is valid, we are _not_ supposed to scroll q's children (as documented).
|
||||
// But we do scroll children (and the whole of q) if qscrollRect is invalid. This case is
|
||||
@@ -4745,7 +4743,6 @@ void QWidgetPrivate::scroll_sys(int dx,
|
||||
}else {
|
||||
update_sys(qscrollRect);
|
||||
}
|
||||
- return;
|
||||
}
|
||||
|
||||
#ifdef QT_MAC_USE_COCOA
|
||||
@@ -4762,6 +4759,7 @@ void QWidgetPrivate::scroll_sys(int dx,
|
||||
// moved when the parent is scrolled. All directly or indirectly moved
|
||||
// children will receive a move event before the function call returns.
|
||||
QWidgetList movedChildren;
|
||||
+ const QPoint scrollDelta(dx, dy);
|
||||
if (scrollChildren) {
|
||||
QObjectList children = q->children();
|
||||
|
||||
BIN
other/osx/7z
Normal file
BIN
other/osx/7z
Normal file
Binary file not shown.
BIN
other/osx/7z.so
Normal file
BIN
other/osx/7z.so
Normal file
Binary file not shown.
68
other/osx/Info.plist
Normal file
68
other/osx/Info.plist
Normal file
@@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Kindle Comic Converter</string>
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>cbz</string>
|
||||
<string>cbr</string>
|
||||
<string>cb7</string>
|
||||
<string>zip</string>
|
||||
<string>rar</string>
|
||||
<string>7z</string>
|
||||
<string>pdf</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>comic2ebook.icns</string>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>Comics</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>MacOS/Kindle Comic Converter</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>KindleComicConverter 5.5.0, written 2012-2019 by Ciro Mattia Gonano and Pawel Jastrzebski</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>comic2ebook.icns</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.kindlecomicconverter.KindleComicConverter</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>Kindle Comic Converter</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>5.5.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>5.5.0</string>
|
||||
<key>LSEnvironment</key>
|
||||
<dict>
|
||||
<key>PATH</key>
|
||||
<string>./../Resources:/usr/local/bin:/usr/bin:/bin</string>
|
||||
</dict>
|
||||
<key>LSHasLocalizedDisplayName</key>
|
||||
<false/>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.12.0</string>
|
||||
<key>NSAppleScriptEnabled</key>
|
||||
<false/>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>ISC License (ISCL)</string>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
||||
BIN
other/osx/sentry.py.enc
Normal file
BIN
other/osx/sentry.py.enc
Normal file
Binary file not shown.
BIN
other/windows/7z.dll
Normal file
BIN
other/windows/7z.dll
Normal file
Binary file not shown.
BIN
other/windows/7z.exe
Normal file
BIN
other/windows/7z.exe
Normal file
Binary file not shown.
90
other/windows/Additional-LICENSE.txt
Normal file
90
other/windows/Additional-LICENSE.txt
Normal file
@@ -0,0 +1,90 @@
|
||||
7-Zip
|
||||
~~~~~
|
||||
License for use and distribution
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
7-Zip Copyright (C) 1999-2018 Igor Pavlov.
|
||||
|
||||
The licenses for files are:
|
||||
|
||||
1) 7z.dll:
|
||||
- The "GNU LGPL" as main license for most of the code
|
||||
- The "GNU LGPL" with "unRAR license restriction" for some code
|
||||
- The "BSD 3-clause License" for some code
|
||||
2) All other files: the "GNU LGPL".
|
||||
|
||||
Redistributions in binary form must reproduce related license information from this file.
|
||||
|
||||
Note:
|
||||
You can use 7-Zip on any computer, including a computer in a commercial
|
||||
organization. You don't need to register or pay for 7-Zip.
|
||||
|
||||
|
||||
GNU LGPL information
|
||||
--------------------
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You can receive a copy of the GNU Lesser General Public License from
|
||||
http://www.gnu.org/
|
||||
|
||||
|
||||
|
||||
|
||||
BSD 3-clause License
|
||||
--------------------
|
||||
|
||||
The "BSD 3-clause License" is used for the code in 7z.dll that implements LZFSE data decompression.
|
||||
That code was derived from the code in the "LZFSE compression library" developed by Apple Inc,
|
||||
that also uses the "BSD 3-clause License":
|
||||
|
||||
----
|
||||
Copyright (c) 2015-2016, Apple Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder(s) nor the names of any contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
----
|
||||
|
||||
|
||||
|
||||
|
||||
unRAR license restriction
|
||||
-------------------------
|
||||
|
||||
The decompression engine for RAR archives was developed using source
|
||||
code of unRAR program.
|
||||
All copyrights to original unRAR code are owned by Alexander Roshal.
|
||||
|
||||
The license for original unRAR code has the following restriction:
|
||||
|
||||
The unRAR sources cannot be used to re-create the RAR compression algorithm,
|
||||
which is proprietary. Distribution of modified unRAR sources in separate form
|
||||
or as a part of other software is permitted, provided that it is clearly
|
||||
stated in the documentation and source comments that the code may
|
||||
not be used to develop a RAR (WinRAR) compatible archiver.
|
||||
|
||||
|
||||
--
|
||||
Igor Pavlov
|
||||
@@ -3,19 +3,20 @@
|
||||
{\flomajor\f31500\fbidi \froman\fcharset238\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fdbmajor\f31501\fbidi \froman\fcharset238\fprq2{\*\panose 02020603050405020304}Times New Roman;}
|
||||
{\fhimajor\f31502\fbidi \fswiss\fcharset238\fprq2{\*\panose 020f0302020204030204}Calibri Light;}{\fbimajor\f31503\fbidi \froman\fcharset238\fprq2{\*\panose 02020603050405020304}Times New Roman;}
|
||||
{\flominor\f31504\fbidi \froman\fcharset238\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fdbminor\f31505\fbidi \froman\fcharset238\fprq2{\*\panose 02020603050405020304}Times New Roman;}
|
||||
{\fhiminor\f31506\fbidi \fswiss\fcharset238\fprq2{\*\panose 020f0502020204030204}Calibri;}{\fbiminor\f31507\fbidi \froman\fcharset238\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f41\fbidi \froman\fcharset0\fprq2 Times New Roman;}
|
||||
{\f40\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f42\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f43\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f44\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
|
||||
{\f45\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f46\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f47\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f41\fbidi \froman\fcharset0\fprq2 Times New Roman;}
|
||||
{\f40\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f42\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f43\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f44\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
|
||||
{\f45\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f46\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f47\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f411\fbidi \fswiss\fcharset0\fprq2 Calibri;}
|
||||
{\f410\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\f412\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f413\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f416\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}
|
||||
{\f417\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\flomajor\f31510\fbidi \froman\fcharset0\fprq2 Times New Roman;}{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
|
||||
{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
|
||||
{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
|
||||
{\fdbmajor\f31520\fbidi \froman\fcharset0\fprq2 Times New Roman;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}
|
||||
{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
|
||||
{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhimajor\f31530\fbidi \fswiss\fcharset0\fprq2 Calibri Light;}
|
||||
{\fhimajor\f31529\fbidi \fswiss\fcharset204\fprq2 Calibri Light Cyr;}{\fhimajor\f31531\fbidi \fswiss\fcharset161\fprq2 Calibri Light Greek;}{\fhimajor\f31532\fbidi \fswiss\fcharset162\fprq2 Calibri Light Tur;}
|
||||
{\fhiminor\f31506\fbidi \fswiss\fcharset238\fprq2{\*\panose 020f0502020204030204}Calibri;}{\fbiminor\f31507\fbidi \froman\fcharset238\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f44\fbidi \froman\fcharset0\fprq2 Times New Roman;}
|
||||
{\f43\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f45\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f46\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f47\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
|
||||
{\f48\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f49\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f50\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f44\fbidi \froman\fcharset0\fprq2 Times New Roman;}
|
||||
{\f43\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f45\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f46\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f47\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
|
||||
{\f48\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f49\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f50\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f414\fbidi \fswiss\fcharset0\fprq2 Calibri;}
|
||||
{\f413\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\f415\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f416\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f417\fbidi \fswiss\fcharset177\fprq2 Calibri (Hebrew);}
|
||||
{\f418\fbidi \fswiss\fcharset178\fprq2 Calibri (Arabic);}{\f419\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f420\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\flomajor\f31510\fbidi \froman\fcharset0\fprq2 Times New Roman;}
|
||||
{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
|
||||
{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
|
||||
{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31520\fbidi \froman\fcharset0\fprq2 Times New Roman;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
|
||||
{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
|
||||
{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
|
||||
{\fhimajor\f31530\fbidi \fswiss\fcharset0\fprq2 Calibri Light;}{\fhimajor\f31529\fbidi \fswiss\fcharset204\fprq2 Calibri Light Cyr;}{\fhimajor\f31531\fbidi \fswiss\fcharset161\fprq2 Calibri Light Greek;}
|
||||
{\fhimajor\f31532\fbidi \fswiss\fcharset162\fprq2 Calibri Light Tur;}{\fhimajor\f31533\fbidi \fswiss\fcharset177\fprq2 Calibri Light (Hebrew);}{\fhimajor\f31534\fbidi \fswiss\fcharset178\fprq2 Calibri Light (Arabic);}
|
||||
{\fhimajor\f31535\fbidi \fswiss\fcharset186\fprq2 Calibri Light Baltic;}{\fhimajor\f31536\fbidi \fswiss\fcharset163\fprq2 Calibri Light (Vietnamese);}{\fbimajor\f31540\fbidi \froman\fcharset0\fprq2 Times New Roman;}
|
||||
{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
|
||||
{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
|
||||
@@ -26,20 +27,21 @@
|
||||
{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
|
||||
{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31570\fbidi \fswiss\fcharset0\fprq2 Calibri;}
|
||||
{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}
|
||||
{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31580\fbidi \froman\fcharset0\fprq2 Times New Roman;}
|
||||
{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
|
||||
{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
|
||||
{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;
|
||||
\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;
|
||||
\chyperlink\ctint255\cshade255\red5\green99\blue193;\cfollowedhyperlink\ctint255\cshade255\red149\green79\blue114;}{\*\defchp \f31506\fs22\lang1045\langfe1033\langfenp1033 }{\*\defpap \ql \li0\ri0\sa160\sl259\slmult1
|
||||
\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0
|
||||
\f31506\fs22\lang1045\langfe1033\cgrid\langnp1045\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\*
|
||||
{\fhiminor\f31573\fbidi \fswiss\fcharset177\fprq2 Calibri (Hebrew);}{\fhiminor\f31574\fbidi \fswiss\fcharset178\fprq2 Calibri (Arabic);}{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}
|
||||
{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31580\fbidi \froman\fcharset0\fprq2 Times New Roman;}{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
|
||||
{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
|
||||
{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}
|
||||
{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;
|
||||
\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;\chyperlink\ctint255\cshade255\red5\green99\blue193;\cfollowedhyperlink\ctint255\cshade255\red149\green79\blue114;}{\*\defchp
|
||||
\f31506\fs22\lang1045\langfe1033\langfenp1033 }{\*\defpap \ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\sa160\sl259\slmult1
|
||||
\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \f31506\fs22\lang1045\langfe1033\cgrid\langnp1045\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive
|
||||
\ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\*
|
||||
\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa160\sl259\slmult1
|
||||
\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31506\afs22\alang1025 \ltrch\fcs0 \f31506\fs22\lang1045\langfe1033\cgrid\langnp1045\langfenp1033 \snext11 \ssemihidden \sunhideused Normal Table;}{\*\cs15 \additive
|
||||
\rtlch\fcs1 \af0 \ltrch\fcs0 \ul\cf17 \sbasedon10 \sunhideused \styrsid3562894 Hyperlink;}{\*\cs16 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \ul\cf18 \sbasedon10 \ssemihidden \sunhideused \styrsid7678248 FollowedHyperlink;}}{\*\rsidtbl \rsid1081196
|
||||
\rsid3146412\rsid3562894\rsid5731975\rsid7678248\rsid9265883\rsid11107340\rsid12600926\rsid13187577}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info
|
||||
{\author Pawe\'b3 Jastrz\'eabski}{\operator Pawe\'b3 Jastrz\'eabski}{\creatim\yr2013\mo10\dy29\hr15\min17}{\revtim\yr2013\mo10\dy29\hr15\min28}{\version8}{\edmins8}{\nofpages1}{\nofwords33}{\nofchars200}{\nofcharsws232}{\vern57435}}{\*\xmlnstbl {\xmlns1 h
|
||||
ttp://schemas.microsoft.com/office/word/2003/wordml}}\paperw11906\paperh16838\margl1417\margr1417\margt1417\margb1417\gutter0\ltrsect
|
||||
\rsid3146412\rsid3562894\rsid5731975\rsid7678248\rsid9265883\rsid11107340\rsid11629590\rsid12600926\rsid13187577}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info
|
||||
{\author Pawe\'b3 Jastrz\'eabski}{\operator Pawe\'b3 Jastrz\'eabski}{\creatim\yr2013\mo10\dy29\hr15\min17}{\revtim\yr2017\mo8\dy20\hr17\min40}{\version9}{\edmins8}{\nofpages1}{\nofwords33}{\nofchars201}{\nofcharsws233}{\vern39}}{\*\xmlnstbl {\xmlns1 http:
|
||||
//schemas.microsoft.com/office/word/2003/wordml}}\paperw11906\paperh16838\margl1417\margr1417\margt1417\margb1417\gutter0\ltrsect
|
||||
\deftab708\widowctrl\ftnbj\aenddoc\hyphhotz425\trackmoves0\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0
|
||||
\showxmlerrors1\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin1417\dgvorigin1417\dghshow1\dgvshow1
|
||||
\jexpand\viewkind1\viewscale100\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel\wrppunct
|
||||
@@ -52,12 +54,13 @@ ttp://schemas.microsoft.com/office/word/2003/wordml}}\paperw11906\paperh16838\ma
|
||||
\b\fs52\cf6\lang2057\langfe1033\langnp2057\insrsid13187577\charrsid3562894
|
||||
\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \fs28\lang2057\langfe1033\langnp2057\insrsid1081196 Creation of}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \fs28\lang2057\langfe1033\langnp2057\insrsid3562894\charrsid12600926 }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0
|
||||
\b\fs28\lang2057\langfe1033\langnp2057\insrsid3562894\charrsid12600926 MOBI}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \fs28\lang2057\langfe1033\langnp2057\insrsid3562894\charrsid12600926 files }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0
|
||||
\fs28\lang2057\langfe1033\langnp2057\insrsid5731975\charrsid12600926 require additional software.}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \fs28\lang2057\langfe1033\langnp2057\insrsid3562894\charrsid12600926
|
||||
\fs28\lang2057\langfe1033\langnp2057\insrsid5731975\charrsid12600926 require}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \fs28\lang2057\langfe1033\langnp2057\insrsid11629590 s}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0
|
||||
\fs28\lang2057\langfe1033\langnp2057\insrsid5731975\charrsid12600926 additional software.}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \fs28\lang2057\langfe1033\langnp2057\insrsid3562894\charrsid12600926
|
||||
\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \b\fs28\lang2057\langfe1033\langnp2057\insrsid3562894\charrsid12600926 Please download: }{\field\flddirty{\*\fldinst {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0
|
||||
\b\fs28\lang2057\langfe1033\langnp2057\insrsid3562894\charrsid12600926 HYPERLINK "http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1000765211" }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \b\fs28\lang2057\langfe1033\langnp2057\insrsid3562894\charrsid12600926
|
||||
{\*\datafield
|
||||
00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b9600000068007400740070003a002f002f007700770077002e0061006d0061007a006f006e002e0063006f006d002f00670070002f0066006500610074007500720065002e00680074006d006c003f00690065003d00
|
||||
5500540046003800260064006f006300490064003d0031003000300030003700360035003200310031000000795881f43b1d7f48af2c825dc485276300000000a5ab000000}}}{\fldrslt {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0
|
||||
5500540046003800260064006f006300490064003d0031003000300030003700360035003200310031000000795881f43b1d7f48af2c825dc485276300000000a5ab00000000}}}{\fldrslt {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0
|
||||
\cs15\b\fs28\ul\cf17\lang2057\langfe1033\langnp2057\insrsid3562894\charrsid12600926 KindleGen}}}\sectd \ltrsect\linex0\headery708\footery708\colsx708\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0
|
||||
\b\fs28\lang2057\langfe1033\langnp2057\insrsid3562894\charrsid12600926
|
||||
\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \fs28\lang2057\langfe1033\langnp2057\insrsid3562894\charrsid12600926 And place }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \i\fs28\lang2057\langfe1033\langnp2057\insrsid5731975\charrsid12600926 kindlegen.exe}{\rtlch\fcs1
|
||||
@@ -119,7 +122,7 @@ d40384e4350d363f2451eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719a
|
||||
617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169
|
||||
6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363
|
||||
656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e}
|
||||
{\*\latentstyles\lsdstimax371\lsdlockeddef0\lsdsemihiddendef0\lsdunhideuseddef0\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1;
|
||||
{\*\latentstyles\lsdstimax375\lsdlockeddef0\lsdsemihiddendef0\lsdunhideuseddef0\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 1;
|
||||
@@ -196,7 +199,8 @@ d40384e4350d363f2451eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719a
|
||||
\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 List Table 2 Accent 5;\lsdpriority48 \lsdlocked0 List Table 3 Accent 5;
|
||||
\lsdpriority49 \lsdlocked0 List Table 4 Accent 5;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 5;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 5;
|
||||
\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 List Table 2 Accent 6;\lsdpriority48 \lsdlocked0 List Table 3 Accent 6;\lsdpriority49 \lsdlocked0 List Table 4 Accent 6;
|
||||
\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 6;}}{\*\datastore 010500000200000018000000
|
||||
\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Mention;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Smart Hyperlink;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Hashtag;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Unresolved Mention;}}{\*\datastore 010500000200000018000000
|
||||
4d73786d6c322e534158584d4c5265616465722e362e30000000000000000000000e0000
|
||||
d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff0900060000000000000000000000010000000100000000000000001000000200000001000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
@@ -206,24 +210,24 @@ fffffffffffffffffdffffff04000000feffffff05000000fefffffffeffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffff010000000c6ad98892f1d411a65f0040963251e50000000000000000000000006069
|
||||
e214b3d4ce010300000080020000000000004d0073006f004400610074006100530074006f0072006500000000000000000000000000000000000000000000000000000000000000000000000000000000001a000101ffffffffffffffff0200000000000000000000000000000000000000000000006069e214b3d4ce01
|
||||
6069e214b3d4ce010000000000000000000000003500d900ca00dd00ce004400cc00c8005a0045004700c400cd0057004900c500d400c900cb00ce00570051003d003d000000000000000000000000000000000032000101ffffffffffffffff0300000000000000000000000000000000000000000000006069e214b3d4
|
||||
ce016069e214b3d4ce010000000000000000000000004900740065006d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000201ffffffff04000000ffffffff000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000fc00000000000000010000000200000003000000feffffff0500000006000000070000000800000009000000feffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffff010000000c6ad98892f1d411a65f0040963251e5000000000000000000000000b00f
|
||||
9da8ca19d30103000000c0020000000000004d0073006f004400610074006100530074006f0072006500000000000000000000000000000000000000000000000000000000000000000000000000000000001a000101ffffffffffffffff020000000000000000000000000000000000000000000000b00f9da8ca19d301
|
||||
b00f9da8ca19d301000000000000000000000000ca0041004300c300d300d300c70058004d00d4003000c9004d00c200590043003100320055004a00300051003d003d000000000000000000000000000000000032000101ffffffffffffffff030000000000000000000000000000000000000000000000b00f9da8ca19
|
||||
d301b00f9da8ca19d3010000000000000000000000004900740065006d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000201ffffffff04000000ffffffff000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000320100000000000001000000020000000300000004000000feffffff060000000700000008000000090000000a000000feffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3c623a536f75726365732053656c65637465645374796c653d225c415041536978746845646974696f6e4f66666963654f6e6c696e652e78736c22205374796c654e616d653d22415041222056657273696f6e3d22362220786d6c6e733a
|
||||
623d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f6f6666696365446f63756d656e742f323030362f6269626c696f6772617068792220786d6c6e733d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f6f6666696365446f63756d656e74
|
||||
2f323030362f6269626c696f677261706879223e3c2f623a536f75726365733e000000003c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d226e6f223f3e0d0a3c64733a6461746173746f72654974656d2064733a6974656d49443d227b42384244
|
||||
394137462d323833422d343136342d413442352d3632323544323941454535397d2220786d6c6e733a64733d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f6f6666696365446f63756d656e742f323030362f637573746f6d586d6c223e3c64733a736368656d61526566733e3c
|
||||
64733a736368656d615265662064733a7572693d22687474703a2f2f736368656d61732e6f70656e500072006f007000650072007400690065007300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000200ffffffffffffffffffffffff000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000400000055010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d226e6f223f3e3c623a536f75726365732053656c65637465645374796c653d225c41504153697874684564697469
|
||||
6f6e4f66666963654f6e6c696e652e78736c22205374796c654e616d653d22415041222056657273696f6e3d22362220786d6c6e733a623d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f6f6666696365446f63756d656e742f323030362f6269626c696f677261706879222078
|
||||
6d6c6e733d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f6f6666696365446f63756d656e742f323030362f6269626c696f677261706879223e3c2f623a536f75726365733e00000000000000000000000000003c3f786d6c2076657273696f6e3d22312e302220656e636f6469
|
||||
6e673d225554462d3822207374616e64616c6f6e653d226e6f223f3e0d0a3c64733a6461746173746f72654974656d2064733a6974656d49443d227b43464133303041382d443733392d343633332d413933322d3236303236444335303936397d2220786d6c6e733a64733d22687474703a2f2f736368656d61732e6f70
|
||||
656e786d6c666f726d6174732e6f72672f6f6666696365446f63756d656e742f323030362f637573500072006f007000650072007400690065007300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000200ffffffffffffffffffffffff000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000500000055010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000
|
||||
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff
|
||||
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000786d6c666f726d6174732e6f72672f6f6666696365446f63756d656e742f323030362f6269626c696f677261706879222f3e3c2f64733a736368656d61526566733e3c2f64733a6461746173746f
|
||||
72654974656d3e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000746f6d586d6c223e3c64733a736368656d61526566733e3c64733a736368656d615265662064733a7572693d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f7267
|
||||
2f6f6666696365446f63756d656e742f323030362f6269626c696f677261706879222f3e3c2f64733a736368656d61526566733e3c2f64733a6461746173746f72654974656d3e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000105000000000000}}
|
||||
3
other/windows/sentry.py.enc
Normal file
3
other/windows/sentry.py.enc
Normal file
@@ -0,0 +1,3 @@
|
||||
éd¼7¶ÍÑ<>ßñ|l“z6¯n¸I_œ—Åž:£ê-ˆ!ën‚BCDÇ}fðzIe|¦ÜÖà\9KW°f½H[íY¶LYô7^Ï@mª*<2A>YmÎ_z`3©WSD{Ö"áˆa@>®;}\¥—,D›š˜Ý·Ý!yX<79>±è–<C3A8>¯~ÿ~Y_æxdÕï BøŠT
|
||||
B”𢯣
|
||||
uô|91u~¿Pa¸¸LDÜjh
|
||||
5
requirements.txt
Normal file
5
requirements.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
PyQt5>=5.6.0
|
||||
Pillow>=5.2.0
|
||||
psutil>=5.0.0
|
||||
python-slugify>=1.2.1,<3.0.0
|
||||
raven>=6.0.0
|
||||
161
setup.py
Normal file → Executable file
161
setup.py
Normal file → Executable file
@@ -1,95 +1,86 @@
|
||||
#!/usr/bin/env python2
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
cx_Freeze build script for KCC.
|
||||
pip/pyinstaller build script for KCC.
|
||||
|
||||
Usage (Mac OS X):
|
||||
python setup.py py2app
|
||||
Install as Python package:
|
||||
python3 setup.py install
|
||||
|
||||
Usage (Windows):
|
||||
python setup.py build
|
||||
Create EXE/APP:
|
||||
python3 setup.py build_binary
|
||||
"""
|
||||
from sys import platform
|
||||
|
||||
NAME = "KindleComicConverter"
|
||||
VERSION = "3.6"
|
||||
MAIN = "kcc.py"
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import setuptools
|
||||
import distutils.cmd
|
||||
from kindlecomicconverter import __version__
|
||||
|
||||
if platform == "darwin":
|
||||
from setuptools import setup
|
||||
extra_options = dict(
|
||||
setup_requires=['py2app'],
|
||||
app=[MAIN],
|
||||
options=dict(
|
||||
py2app=dict(
|
||||
argv_emulation=True,
|
||||
iconfile='icons/comic2ebook.icns',
|
||||
includes=['PIL', 'sip', 'PyQt4', 'PyQt4.QtCore', 'PyQt4.QtGui', 'PyQt4.QtNetwork'],
|
||||
qt_plugins=[],
|
||||
excludes=['PyQt4.QtDeclarative', 'PyQt4.QtDesigner', 'PyQt4.QtHelp', 'PyQt4.QtMultimedia',
|
||||
'PyQt4.QtOpenGL', 'PyQt4.QtScript', 'PyQt4.QtScriptTools', 'PyQt4.QtSql', 'PyQt4.QtSvg',
|
||||
'PyQt4.QtXmlPatterns', 'PyQt4.QtXml', 'PyQt4.QtWebKit', 'PyQt4.QtTest', 'Tkinter'],
|
||||
resources=['LICENSE.txt', 'other/Additional-LICENSE.txt', 'other/unrar', 'other/7za'],
|
||||
plist=dict(
|
||||
CFBundleName=NAME,
|
||||
CFBundleShortVersionString=VERSION,
|
||||
CFBundleGetInfoString=NAME + " " + VERSION +
|
||||
", written 2012-2013 by Ciro Mattia Gonano and Pawel Jastrzebski",
|
||||
CFBundleExecutable=NAME,
|
||||
CFBundleIdentifier='com.github.ciromattia.kcc',
|
||||
CFBundleSignature='dplt',
|
||||
CFBundleDocumentTypes=[
|
||||
dict(
|
||||
CFBundleTypeExtensions=['cbz', 'cbr', 'cb7', 'zip', 'rar', '7z', 'pdf'],
|
||||
CFBundleTypeIconFile='comic2ebook.icns',
|
||||
CFBundleTypeRole='Viewer',
|
||||
)
|
||||
],
|
||||
LSMinimumSystemVersion='10.6.0',
|
||||
LSEnvironment=dict(
|
||||
PATH='/usr/local/bin:/usr/bin:/bin'
|
||||
),
|
||||
NSHumanReadableCopyright='ISC License (ISCL)'
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
elif platform == "win32":
|
||||
from cx_Freeze import setup, Executable
|
||||
base = "Win32GUI"
|
||||
extra_options = dict(
|
||||
options={"build_exe": {"include_files": ['LICENSE.txt',
|
||||
['other/UnRAR.exe', 'UnRAR.exe'],
|
||||
['other/7za.exe', '7za.exe'],
|
||||
['other/Additional-LICENSE.txt', 'Additional-LICENSE.txt']
|
||||
], "compressed": True,
|
||||
"excludes": ['Tkinter']}},
|
||||
executables=[Executable(MAIN,
|
||||
base=base,
|
||||
targetName="KCC.exe",
|
||||
icon="icons/comic2ebook.ico",
|
||||
copyDependentFiles=True,
|
||||
appendScriptToExe=True,
|
||||
appendScriptToLibrary=False,
|
||||
compress=True)])
|
||||
else:
|
||||
print 'Please use setup.sh to build Linux package.'
|
||||
exit()
|
||||
NAME = 'KindleComicConverter'
|
||||
MAIN = 'kcc.py'
|
||||
VERSION = __version__
|
||||
|
||||
#noinspection PyUnboundLocalVariable
|
||||
setup(
|
||||
|
||||
class BuildBinaryCommand(distutils.cmd.Command):
|
||||
description = 'build binary release'
|
||||
user_options = []
|
||||
|
||||
def initialize_options(self):
|
||||
pass
|
||||
|
||||
def finalize_options(self):
|
||||
pass
|
||||
|
||||
# noinspection PyShadowingNames
|
||||
def run(self):
|
||||
VERSION = __version__
|
||||
if sys.platform == 'darwin':
|
||||
os.system('pyinstaller -y -F -i icons/comic2ebook.icns -n "Kindle Comic Converter" -w -s kcc.py')
|
||||
shutil.copy('other/osx/7z', 'dist/Kindle Comic Converter.app/Contents/Resources')
|
||||
shutil.copy('other/osx/7z.so', 'dist/Kindle Comic Converter.app/Contents/Resources')
|
||||
shutil.copy('other/osx/Info.plist', 'dist/Kindle Comic Converter.app/Contents')
|
||||
shutil.copy('LICENSE.txt', 'dist/Kindle Comic Converter.app/Contents/Resources')
|
||||
shutil.copy('other/windows/Additional-LICENSE.txt', 'dist/Kindle Comic Converter.app/Contents/Resources')
|
||||
os.chmod('dist/Kindle Comic Converter.app/Contents/Resources/7z', 0o777)
|
||||
os.system('appdmg kcc.json dist/KindleComicConverter_osx_' + VERSION + '.dmg')
|
||||
exit(0)
|
||||
elif sys.platform == 'win32':
|
||||
os.system('pyinstaller -y -F -i icons\\comic2ebook.ico -n KCC -w --noupx kcc.py')
|
||||
exit(0)
|
||||
else:
|
||||
exit(0)
|
||||
|
||||
|
||||
setuptools.setup(
|
||||
cmdclass={
|
||||
'build_binary': BuildBinaryCommand,
|
||||
},
|
||||
name=NAME,
|
||||
version=VERSION,
|
||||
author="Ciro Mattia Gonano, Pawel Jastrzebski",
|
||||
author_email="ciromattia@gmail.com, pawelj@vulturis.eu",
|
||||
description="A tool to convert comics (CBR/CBZ/PDFs/image folders) to MOBI.",
|
||||
license="ISC License (ISCL)",
|
||||
keywords="kindle comic mobipocket mobi cbz cbr manga",
|
||||
url="http://github.com/ciromattia/kcc",
|
||||
packages=['kcc'], requires=['Pillow'],
|
||||
**extra_options
|
||||
author='Ciro Mattia Gonano, Pawel Jastrzebski',
|
||||
author_email='ciromattia@gmail.com, pawelj@iosphe.re',
|
||||
description='Comic and Manga converter for e-book readers.',
|
||||
license='ISC License (ISCL)',
|
||||
keywords=['kindle', 'kobo', 'comic', 'manga', 'mobi', 'epub', 'cbz'],
|
||||
url='http://github.com/ciromattia/kcc',
|
||||
entry_points={
|
||||
'console_scripts': [
|
||||
'kcc-c2e = kindlecomicconverter.startup:startC2E',
|
||||
'kcc-c2p = kindlecomicconverter.startup:startC2P',
|
||||
],
|
||||
'gui_scripts': [
|
||||
'kcc = kindlecomicconverter.startup:start',
|
||||
],
|
||||
},
|
||||
packages=['kindlecomicconverter'],
|
||||
install_requires=[
|
||||
'PyQt5>=5.6.0',
|
||||
'Pillow>=5.2.0',
|
||||
'psutil>=5.0.0',
|
||||
'python-slugify>=1.2.1',
|
||||
'raven>=6.0.0',
|
||||
],
|
||||
classifiers=[],
|
||||
zip_safe=False,
|
||||
)
|
||||
|
||||
if platform == "darwin":
|
||||
from os import chmod
|
||||
chmod('dist/' + NAME + '.app/Contents/Resources/unrar', 0777)
|
||||
chmod('dist/' + NAME + '.app/Contents/Resources/7za', 0777)
|
||||
12
setup.sh
12
setup.sh
@@ -1,12 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Linux Python package build script
|
||||
|
||||
VERSION="3.6"
|
||||
|
||||
cp kcc.py __main__.py
|
||||
zip kcc.zip __main__.py kcc/*.py
|
||||
echo "#!/usr/bin/env python2" > kcc-bin
|
||||
cat kcc.zip >> kcc-bin
|
||||
chmod +x kcc-bin
|
||||
tar --xform s:^.*/:: --xform s/kcc-bin/kcc/ --xform s/comic2ebook/kcc/ -czf KindleComicConverter_linux_$VERSION.tar.gz kcc-bin LICENSE.txt icons/comic2ebook.png
|
||||
rm __main__.py kcc.zip kcc-bin
|
||||
Reference in New Issue
Block a user