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

Compare commits

...

414 Commits
3.0 ... 4.5.1

Author SHA1 Message Date
Paweł Jastrzębski
8d82f58f09 Merge pull request #137 from ciromattia/dev
4.5.1
2015-05-09 09:29:42 +02:00
Paweł Jastrzębski
36985f5169 Detect broken Pillow (close #135) 2015-05-07 22:37:48 +02:00
Paweł Jastrzębski
9d190c1585 Updated README + version bump 2015-05-07 18:06:16 +02:00
Paweł Jastrzębski
3834850317 Tweaked metadata editor 2015-05-07 17:49:03 +02:00
Paweł Jastrzębski
84fc23b979 Fixed CBR parsing anomalies (close #133) 2015-04-27 18:50:14 +02:00
Paweł Jastrzębski
77748afdbd Fixed supid typo 2015-04-26 18:47:40 +02:00
Paweł Jastrzębski
431e2ffaf2 Binary blob cleanup 2015-04-26 15:59:43 +02:00
Paweł Jastrzębski
16df4cd083 Added Kobo Glow HD profile 2015-04-22 20:38:17 +02:00
Paweł Jastrzębski
1aa34347c1 Added page-progression-direction tag to EPUB spine 2015-03-17 11:02:28 +01:00
Paweł Jastrzębski
561af90b06 Updated README and Setup 2015-03-09 20:08:48 +01:00
Paweł Jastrzębski
00d239e1d8 Merge pull request #131 from ciromattia/dev
4.5
2015-03-08 18:08:15 +01:00
Paweł Jastrzębski
26bd2d3ed0 Version bump 2015-03-08 18:07:47 +01:00
Paweł Jastrzębski
e7aa49b70c Fixed bookmark drift caused by image splits 2015-03-08 18:06:27 +01:00
Paweł Jastrzębski
da41edc2f1 GUI tweak 2015-02-26 18:27:10 +01:00
fsteffek
ecbf60fb28 Add ComicInfo bookmarks -> EPUB chapter support
Bookmarks from ComicRack's ComicInfo.xml are now converted to EPUB
chapters. `Bookmark` is an attribute to the `Page` element in
ComicInfo.xml.

 * Works with flat directory structure (no sub-folders support)
2015-02-21 18:40:59 +01:00
Paweł Jastrzębski
57b571b6c2 Fixed CLI version 2015-02-21 18:30:54 +01:00
Paweł Jastrzębski
44bdc0245b Fool proofing file sorting 2015-02-21 18:25:55 +01:00
fsteffek
1ec07fe4ec Fix random order of chapter list (close #129)
Directories and files returned by walk() are not always sorted.
Currently we sort the filelist after creating the it. When walk()-ing
topdown (we do) the directory list can be modified in-place. By sorting
the directories and files before creating the filelist, we guarantee
a sorted chapter list.
2015-02-21 17:59:46 +01:00
Paweł Jastrzębski
5f8f7e0919 Merge pull request #128 from fsteffek/dev
Fixed first file detection
2015-02-20 10:01:34 +01:00
fsteffek
f404b9090d Set first image in folder as cover
The walk() function does not necessarily return filenames in
alphabetical order. This leads to a random cover image.

Sorting filenames before setting the cover images fixes this issue.
2015-02-19 22:33:25 +01:00
Paweł Jastrzębski
68521f7c63 Updated installer 2015-02-17 18:08:23 +01:00
Paweł Jastrzębski
f5dd813c4c General refactoring and tweaks 2015-02-14 09:47:14 +01:00
Paweł Jastrzębski
7924c492b3 Updated OSX and Linux GUI 2015-02-08 12:52:42 +01:00
Paweł Jastrzębski
2fc21c33e2 Added metadata editor 2015-02-08 11:53:55 +01:00
Paweł Jastrzębski
cb76504acb Updated installer 2015-02-01 08:57:24 +01:00
Paweł Jastrzębski
db6b0eddfe Completely replaced Virtual Panel View with Panel View 2015-01-31 11:10:01 +01:00
Paweł Jastrzębski
7d529a2acc Added Metadata editor class 2015-01-24 18:36:15 +01:00
Paweł Jastrzębski
ad3ff35aaa Yet another workaround for file lock problems (#125) 2015-01-24 10:07:27 +01:00
Paweł Jastrzębski
c62eeeb712 Re-enabled MCD support 2015-01-21 19:15:38 +01:00
Paweł Jastrzębski
5a36a13105 Replaced os.walk 2015-01-21 18:19:54 +01:00
Paweł Jastrzębski
12684d6562 Code cleanup 2015-01-20 21:45:22 +01:00
Paweł Jastrzębski
c5f68ae12a Merge pull request #124 from ciromattia/dev
4.4.1
2015-01-11 16:20:43 +01:00
Paweł Jastrzębski
7bd9c766cc Version bump 2015-01-11 16:20:01 +01:00
Paweł Jastrzębski
c6b1417d9c Added one Windows DLL 2015-01-11 16:17:04 +01:00
Paweł Jastrzębski
98bf28a713 Fixed OSX GUI anomalies 2015-01-10 11:09:28 +01:00
Paweł Jastrzębski
f2d6d5b458 Fixed upgrade freeze (close #123) 2015-01-05 10:47:21 +01:00
Paweł Jastrzębski
5de492ffb6 Overhauled dependency check 2015-01-05 08:43:15 +01:00
Paweł Jastrzębski
5c2c6ed825 Tweaked OSX hack 2015-01-04 18:59:12 +01:00
Paweł Jastrzębski
c2730ab01c Merge pull request #122 from ciromattia/dev
4.4
2015-01-04 14:57:09 +01:00
Paweł Jastrzębski
bfba66d47d Improved KindleGen detection 2015-01-04 14:53:14 +01:00
Paweł Jastrzębski
b5bc2f8e00 Updated README + version bump 2015-01-04 10:49:59 +01:00
Paweł Jastrzębski
917eaef548 GUI tweaks 2015-01-04 10:27:13 +01:00
Paweł Jastrzębski
3187ebb054 Generic processing improvements 2015-01-04 09:13:20 +01:00
Paweł Jastrzębski
b9276e9ede WebToon processing improvements 2015-01-04 09:11:46 +01:00
Paweł Jastrzębski
147d815057 Code cleanup 2015-01-04 09:09:33 +01:00
Paweł Jastrzębski
180123fee2 Improved 7zip detection 2015-01-03 09:17:00 +01:00
Paweł Jastrzębski
2768e622f2 PyQT 5.4 workarounds 2015-01-02 11:51:14 +01:00
Paweł Jastrzębski
b629b45d46 Pillow update 2015-01-02 09:55:34 +01:00
Paweł Jastrzębski
f66c83425c PyQT 5.4 update 2015-01-01 15:24:59 +01:00
Paweł Jastrzębski
68b4b7114d Added RAR5 support 2014-12-30 11:07:11 +01:00
Paweł Jastrzębski
36f8c82eaf Fixed OSX race condition 2014-12-30 11:00:21 +01:00
Paweł Jastrzębski
bd665c3261 Merge pull request #119 from ciromattia/4.x
4.3.1
2014-11-24 20:13:17 +01:00
Paweł Jastrzębski
94586fa590 Version bump 2014-11-24 19:07:50 +01:00
Paweł Jastrzębski
89806dfcfc Disabled MCD integration 2014-11-24 18:56:24 +01:00
Paweł Jastrzębski
c9eb73ab90 OS X: Miscellaneous fixes (close #115) 2014-11-24 18:47:53 +01:00
Paweł Jastrzębski
2edcc0369a Updated UnRAR 2014-11-22 15:22:31 +01:00
Paweł Jastrzębski
bc0a52b848 PEP 8 2014-11-21 22:46:43 +01:00
Paweł Jastrzębski
5ae72bf06d Fixed Kindle Voyage profile 2014-11-21 22:41:51 +01:00
Paweł Jastrzębski
24c32643c1 Tweaked glob support 2014-11-10 19:33:03 +01:00
Paweł Jastrzębski
40b988f964 Merge branch 'multifile' of git://github.com/theaquamarine/kcc into 4.x 2014-10-29 07:14:39 +01:00
blue
ac794eff85 Use glob to resolve file globs
For systems where the shell doesn't do glob expansion, eg Windows.
2014-10-28 18:34:14 +00:00
blue
eaa387a9d6 Add basic support for converting more >1 file 2014-10-28 16:51:31 +00:00
Paweł Jastrzębski
d0f5d6dac4 Tweaked title sorting 2014-10-17 14:15:35 +02:00
Paweł Jastrzębski
b174534c1c Merge pull request #113 from ciromattia/4.x
4.3
2014-09-29 18:05:32 +02:00
Paweł Jastrzębski
19d486a4ee Updated README 2014-09-28 22:01:22 +02:00
Paweł Jastrzębski
652762b709 Updated README + version bump 2014-09-28 13:23:40 +02:00
Paweł Jastrzębski
e6df87f8fd CLI: Added tool detection 2014-09-28 13:16:13 +02:00
Paweł Jastrzębski
1a9cd0beb5 Moved MOBI creation to main code (close #111) 2014-09-28 13:01:42 +02:00
Paweł Jastrzębski
108e351126 Refactored locking mechanism (close #112) 2014-09-27 11:44:42 +02:00
Paweł Jastrzębski
dfe3e10470 Updated setup 2014-09-22 18:35:53 +02:00
Paweł Jastrzębski
787ad9fa66 Updated multiple device profiles 2014-09-18 19:05:24 +02:00
Paweł Jastrzębski
f10e8869a9 Added Kobo Aura H2O profile 2014-09-03 07:16:26 +02:00
Paweł Jastrzębski
715ada328f Tweaked error reporting (close #109) 2014-08-24 09:56:59 +02:00
Paweł Jastrzębski
56f23ab488 Merge pull request #108 from ciromattia/4.x
4.2.1
2014-08-03 11:22:28 +02:00
Paweł Jastrzębski
996af59e00 Updated README + version bump 2014-08-03 11:21:43 +02:00
Paweł Jastrzębski
37aa84c4aa Fixed MOBI processing anomalies 2014-08-02 07:54:15 +02:00
Paweł Jastrzębski
50574632e6 Replaced margin color detection algorithm 2014-08-01 07:23:55 +02:00
Paweł Jastrzębski
0afb9e8c0b Kindle: Fixed high quality mode (close #106) 2014-07-31 21:49:03 +02:00
Paweł Jastrzębski
7511c7eed6 Kindle DX: Changed default output format to CBZ 2014-07-29 19:59:21 +02:00
Paweł Jastrzębski
836a4146f9 MCD: Fixed small bug 2014-07-23 20:55:31 +02:00
Paweł Jastrzębski
15a240ccea Merge pull request #103 from ciromattia/4.x
Version 4.2
2014-07-18 10:29:14 +02:00
Paweł Jastrzębski
0722ddf8b0 Updated README + version bump 2014-07-18 08:45:57 +02:00
Paweł Jastrzębski
b3159b94e7 Prevented hypothetical problems with batch processing 2014-07-18 08:24:12 +02:00
Paweł Jastrzębski
ef5207c990 Dropped Windows XP support 2014-07-10 19:11:04 +02:00
Paweł Jastrzębski
db77d89817 Fixed Other profile 2014-07-05 09:38:10 +02:00
Paweł Jastrzębski
4571fadadb Resolved problems with page order on Kobo 2014-07-04 09:59:21 +02:00
Paweł Jastrzębski
94f56238ae Corruption detection now also delete non-image files (close #99) 2014-07-03 18:16:57 +02:00
Paweł Jastrzębski
5efb5d6dbb Updated Pillow (close #95) 2014-07-03 18:16:57 +02:00
Paweł Jastrzębski
623f615dd9 Added Manga Cover Database support 2014-07-03 18:16:56 +02:00
Paweł Jastrzębski
39fbbc42b3 Made KindleGen detection more foolproof 2014-07-03 18:16:56 +02:00
Paweł Jastrzębski
99405ab8a6 Disabled ultra quality mode for CBZ format 2014-07-03 18:16:55 +02:00
Paweł Jastrzębski
aadfca8306 Code cleanup 2014-07-03 18:16:54 +02:00
Paweł Jastrzębski
5450502c2a Updated README 2014-06-08 07:52:19 +02:00
Paweł Jastrzębski
c976b06413 Make sure that KindleGen have execute permissions 2014-06-05 07:37:32 +02:00
Paweł Jastrzębski
b6facda95b Updated OS X libraries 2014-06-04 10:00:45 +02:00
Paweł Jastrzębski
3f608eb602 Version bump 2014-06-03 19:26:24 +02:00
Paweł Jastrzębski
104cd04994 Fixed title parsing 2014-06-02 20:31:48 +02:00
Paweł Jastrzębski
b323204628 Added additional cover processing 2014-06-02 19:55:20 +02:00
Paweł Jastrzębski
56195d301d Tweaked merge 2014-05-29 22:01:21 +02:00
Paweł Jastrzębski
287723ca6f Updated UnRAR 2014-05-29 21:56:14 +02:00
Paweł Jastrzębski
90490149c7 Merge branch 'theaquamarine-kindlegen' 2014-05-29 18:54:38 +02:00
blue
2210f484df Use makeBook to create book from GUI
Call comic2ebook.makeBook() rather than comic2ebook.main()
2014-05-29 18:28:38 +02:00
blue
d5502e85b0 Use makeParser() for options in KCC_gui
KCC_gui now uses comic2ebook.makeParser() and setting global variable
in comic2ebook to handle options for ebook creation.
2014-05-29 18:28:33 +02:00
blue
59b26cfc8b Split comic2ebook.py main in two again
Now has main() which initialises the program and makeParser() which
sets up the option parser.
2014-05-29 18:28:27 +02:00
blue
a722e5fa49 Split comic2ebook.py main in two
Now has main() which initialises program and makeBook which does the
actual work.
2014-05-29 18:28:14 +02:00
Paweł Jastrzębski
fce3072dca Updated to Python 3.4 and PyQt 5.3 (close #94) 2014-05-29 18:23:28 +02:00
Paweł Jastrzębski
f53cdf9cd7 Implemented new DualMetaFix version 2014-05-28 06:57:37 +02:00
Paweł Jastrzębski
de74318c69 Replaced cx_Freeze with py2exe 2014-05-25 11:08:28 +02:00
Paweł Jastrzębski
b137e69510 Dependency tweak 2014-05-25 07:29:03 +02:00
Paweł Jastrzębski
888663fa4c Miscellaneous processing tweaks 2014-05-18 09:09:38 +02:00
Paweł Jastrzębski
8a2ba96ac5 Tiny tweaks for Linux 2014-05-17 19:12:54 +02:00
Paweł Jastrzębski
cb6b0e0a7b Updated tooltips 2014-05-15 19:38:34 +02:00
Paweł Jastrzębski
49d2a7fbab Changed domain 2014-05-14 20:23:12 +02:00
Paweł Jastrzębski
3d84b27d58 Fixed tiny bugs 2014-05-05 18:32:46 +02:00
Paweł Jastrzębski
e98a23d0c0 Updated README 2014-05-05 12:08:15 +02:00
Paweł Jastrzębski
7f80dacea8 Finished implementation of DualMetaFix 2014-05-05 10:42:16 +02:00
Paweł Jastrzębski
6efb3dcef3 Preliminary implementation of DualMetaFix 2014-05-04 21:45:03 +02:00
Paweł Jastrzębski
942a828b7e Revert "Changed output extension to AZW3"
This reverts commit 64b199ef74.
2014-05-04 21:37:26 +02:00
Paweł Jastrzębski
df5ee1badf Overhauled dependency check 2014-04-30 20:38:23 +02:00
Paweł Jastrzębski
e3ab28642d Re-enabled tray icon on Linux 2014-04-30 20:11:25 +02:00
Ciro Mattia Gonano
a1831c45d5 Revert to ISC License 2014-04-30 03:00:03 +02:00
Paweł Jastrzębski
52bea9957a Updated README 2014-04-29 13:12:27 +02:00
Paweł Jastrzębski
a71339ec34 Changed license to GNU General Public License v3 (GPL-3) 2014-04-29 13:00:32 +02:00
Paweł Jastrzębski
c5f09c44b8 Bumped a little MOBI file size limit 2014-04-24 22:11:37 +02:00
Paweł Jastrzębski
64b199ef74 Changed output extension to AZW3
This is cosmetic change. All profiles for new Kindle models already created KF8/AZW3 files but used generic extension.
2014-04-21 08:39:16 +02:00
Paweł Jastrzębski
8dd0b0e694 Tweaked whitespace cropping + other small tweaks 2014-04-18 11:47:51 +02:00
Paweł Jastrzębski
181a2e8ab4 GUI tweak: Fixed rounding 2014-04-17 18:46:25 +02:00
Paweł Jastrzębski
3fdff845b7 Tiny code cleanup 2014-04-10 13:42:29 +02:00
Paweł Jastrzębski
2ee5dc310b Fixed No optimization mode (close #88) 2014-04-08 13:10:34 +02:00
Paweł Jastrzębski
f32e9560b5 Fixed Linux/OSX crash 2014-03-26 10:23:20 +01:00
Paweł Jastrzębski
621827c1c2 Performance tweaks for Windows 2014-03-22 11:16:25 +01:00
Paweł Jastrzębski
dc312f36c2 Updated OSX libs 2014-03-19 10:14:56 +01:00
Paweł Jastrzębski
4573ff6ec2 README update 2014-03-19 09:25:45 +01:00
Paweł Jastrzębski
d77498405b Updated to psutil 2.0 2014-03-13 21:58:15 +01:00
Paweł Jastrzębski
e491fca445 Version bump + README update 2014-03-13 21:26:26 +01:00
Paweł Jastrzębski
d22ee1a488 Tweaked HQ mode 2014-02-18 12:56:27 +01:00
Paweł Jastrzębski
7ebcccd8a2 Replaced os.rename with atomic os.replace
This should eliminate last problems with file locks on Windows
2014-02-13 18:35:17 +01:00
Paweł Jastrzębski
9a691c3c63 Windows: Fixed sys.stdout and sys.stderr 2014-02-06 11:45:37 +01:00
Paweł Jastrzębski
2b04a0298e Windows: Fixed abnormalities with version check
CX_Freeze working very, very strange with Python 3.3.3
2014-02-02 08:56:50 +01:00
Paweł Jastrzębski
9867f63d00 Version bump + README update 2014-02-01 19:13:03 +01:00
Paweł Jastrzębski
866f8898be Windows: Hopefully fixed all problems with file locks 2014-02-01 18:11:16 +01:00
Paweł Jastrzębski
9f2ac7a176 Windows: Truncated tracebacks 2014-02-01 16:14:23 +01:00
Paweł Jastrzębski
634213f380 WebToons: Improved performance of directory merger 2014-02-01 14:09:25 +01:00
Paweł Jastrzębski
ce82b5ec66 Tweaked margin color detection 2014-01-31 11:15:03 +01:00
Moshev
062b239f2f Fixed errors in image.py introduced from the different handling of division between python 2 and 3 2014-01-29 08:14:00 +01:00
Paweł Jastrzębski
f5f5c05f1e Merge pull request #82 from ciromattia/python3
Python3 + Qt5
2014-01-28 03:11:33 -08:00
Paweł Jastrzębski
a229ba44bf README update 2014-01-28 12:10:33 +01:00
Paweł Jastrzębski
27e5cc3b00 Removed redundant output 2014-01-27 20:51:13 +01:00
Paweł Jastrzębski
63d752280a Margin color detection tweaks 2014-01-26 10:25:26 +01:00
Paweł Jastrzębski
60b7a90589 Improved Panel View logic 2014-01-25 17:46:10 +01:00
Paweł Jastrzębski
63413fa4ba GUI: Link to important tips appear now 5 times 2014-01-25 10:57:18 +01:00
Paweł Jastrzębski
3a536df626 Code cleanup 2014-01-25 10:42:38 +01:00
Paweł Jastrzębski
35bc4a2987 Added MD5 check to update mechanism 2014-01-24 22:54:16 +01:00
Paweł Jastrzębski
3bb8cc7778 Great Index: Using MD5 checksums instead file paths.
Performance impact is negligible, it simplify the code and is much more error resistant.
2014-01-24 22:43:24 +01:00
Paweł Jastrzębski
bd53c6108d Great Index: Slugification fix 2014-01-24 09:08:39 +01:00
Paweł Jastrzębski
3d8bcb4020 Image flags are not part of filename anymore 2014-01-23 18:06:14 +01:00
Paweł Jastrzębski
162c146bed Windows: Fixed possible problems with file locks
OSX: Tweaked last fix
2014-01-23 11:23:58 +01:00
Paweł Jastrzębski
e4750fc965 OSX: Fixed 7zip parsing 2014-01-22 21:02:06 +01:00
Paweł Jastrzębski
ebe7d910de Reverting setup changes 2014-01-22 17:43:19 +01:00
Paweł Jastrzębski
aa96381eb5 Added experimental Linux setup 2014-01-22 16:47:55 +01:00
Paweł Jastrzębski
a2b9b5aa8b Linux/OSX: Drag&Drop fix 2014-01-21 22:02:15 +01:00
Paweł Jastrzębski
1e5bfc9f66 OSX: Fixed file association (close #65) 2014-01-21 18:09:22 +01:00
Paweł Jastrzębski
25a68ebdea Reformated tooltips 2014-01-21 10:57:54 +01:00
Paweł Jastrzębski
786d2a9e1f Added option to select output directory 2014-01-20 22:26:50 +01:00
Paweł Jastrzębski
4133cd21ba Linux: Completly disabled QSystemTrayIcon
Not showing tray was not enought. Even creating object cause instability.
2014-01-20 21:26:18 +01:00
Paweł Jastrzębski
237ef728e1 Hotfixed cx_freeze packing 2014-01-20 12:07:26 +01:00
Paweł Jastrzębski
991bf5d4a9 Miscellaneous tweaks 2014-01-20 11:58:15 +01:00
Paweł Jastrzębski
aa8b78b4e4 Autoupdater for Windows (#68) 2014-01-20 11:16:25 +01:00
Paweł Jastrzębski
c2e6a0b791 README update 2014-01-19 10:53:00 +01:00
Paweł Jastrzębski
42cf9e099f Updated Linux installer 2014-01-18 12:24:16 +01:00
Paweł Jastrzębski
d99064596a Detect Python 2 + README update 2014-01-18 12:15:45 +01:00
Paweł Jastrzębski
b1e7a88353 Removing QFileDialog hack
Now when KCC support drag&drop we can return to native dialog.
2014-01-18 11:14:14 +01:00
Paweł Jastrzębski
f8610e1cd7 Linux: Disabling systray icon 2014-01-18 10:20:43 +01:00
Paweł Jastrzębski
562dad02fa Miscellaneous GUI tweaks 2014-01-18 09:51:17 +01:00
Paweł Jastrzębski
66b867c1ca Various multi-os tweaks 2014-01-17 19:37:35 +01:00
Paweł Jastrzębski
b46ada9596 Drag & drop for OSX and Linux 2014-01-17 16:19:54 +01:00
Paweł Jastrzębski
aaa2de81fc Updated Inno Setup 2014-01-17 14:37:58 +01:00
Paweł Jastrzębski
b0c6315fee Updated Windows setup + OSX fix 2014-01-17 12:34:05 +01:00
Paweł Jastrzębski
509d78c0a6 Updated OSX setup 2014-01-17 12:25:20 +01:00
Paweł Jastrzębski
65ef77bace Improved NCX creation (close #79) 2014-01-17 09:31:51 +01:00
Paweł Jastrzębski
170064853c Added drag & drop support 2014-01-16 22:11:06 +01:00
Paweł Jastrzębski
c7e9d883fa Manga mode is now always available (close #78) 2014-01-16 19:17:49 +01:00
Paweł Jastrzębski
a8521dbc9a Fixed multi-instance lock 2014-01-16 18:49:51 +01:00
Paweł Jastrzębski
0f44629273 Dropping unnecessary debug 2014-01-16 13:56:37 +01:00
Paweł Jastrzębski
f12361e7cf kindlesplit: Python3 update 2014-01-16 13:37:36 +01:00
Paweł Jastrzębski
450076e6e8 pdfjpgextract: Python3 update 2014-01-16 12:48:04 +01:00
Paweł Jastrzębski
6d445ae151 Fully implemented new slugify library 2014-01-16 12:34:36 +01:00
Paweł Jastrzębski
921511dcf2 Full UTF-8 awareness (close #74)
Tested only on Windows. But he had the biggest problems with it.
2014-01-16 11:40:49 +01:00
Paweł Jastrzębski
d76a624a82 Bucket #3 2014-01-16 08:48:29 +01:00
Paweł Jastrzębski
cf3df581e1 Moved dependiences check out of module 2014-01-15 14:58:45 +01:00
Paweł Jastrzębski
87009f27a6 Preliminary QT5 update 2014-01-15 14:09:40 +01:00
Paweł Jastrzębski
cccbd36463 And one more bucket... 2014-01-15 11:32:29 +01:00
Paweł Jastrzębski
19b438844d Bucket of various tweaks 2014-01-15 10:24:31 +01:00
Paweł Jastrzębski
878e92b527 Added proper startup scripts
Hacks that allow standalone startup of script inside module are messy.
2014-01-15 10:23:44 +01:00
Paweł Jastrzębski
116dce09fd Updated rarfile 2014-01-15 10:00:05 +01:00
Paweł Jastrzębski
3af30faee9 Merge branch 'master' into python3 2014-01-15 09:33:35 +01:00
Paweł Jastrzębski
cf0b6b3484 README update + Version bump 2014-01-14 15:57:52 +01:00
Paweł Jastrzębski
96a8c1d354 Fixed problems with HQ mode (close #77) 2014-01-14 15:54:08 +01:00
Paweł Jastrzębski
20712b6c42 README update + Version bump 2014-01-13 23:20:55 +01:00
Paweł Jastrzębski
84d836bf0e Temporary disabling HQ output for Kobo 2014-01-13 23:18:18 +01:00
Paweł Jastrzębski
d944d6385e Updated VCRedist packages 2014-01-13 14:28:37 +01:00
Paweł Jastrzębski
a38013eabc README update + Version bump 2014-01-13 14:03:43 +01:00
Paweł Jastrzębski
def9e42a61 Yet another Last™ update of margin color detection algorithm 2014-01-11 16:31:49 +01:00
Paweł Jastrzębski
34aaeab8b1 Fixed GUI bug 2014-01-07 17:52:51 +01:00
Paweł Jastrzębski
eaff6cc633 Replaced shutil.make_archive 2014-01-07 17:33:47 +01:00
Paweł Jastrzębski
54f48d2156 Fixed stretching images smaller than device screen 2014-01-07 13:27:36 +01:00
Paweł Jastrzębski
42d845cf07 Image resize fix 2014-01-05 17:09:32 +01:00
Paweł Jastrzębski
e5e53d3aa7 Fixed GUI logic 2014-01-05 13:55:42 +01:00
Paweł Jastrzębski
f952634971 Refactored detection of corrupted files 2014-01-05 13:46:08 +01:00
Paweł Jastrzębski
19ff6a51cc WebToon splitter improvements 2014-01-05 13:41:53 +01:00
Paweł Jastrzębski
8fbe558f65 Updated to Pillow 2.3.0 2014-01-05 12:13:38 +01:00
Paweł Jastrzębski
6bdb0ab942 Panel View improvements 2013-12-30 18:39:53 +01:00
Paweł Jastrzębski
7656a85708 Tweaked KindleGen warning 2013-12-29 17:13:17 +01:00
Paweł Jastrzębski
d016bade8e Bundling VCRedist with Windows installer 2013-12-29 10:01:17 +01:00
Paweł Jastrzębski
3cc99c6221 Margin autodetection improvements 2013-12-28 12:08:33 +01:00
Paweł Jastrzębski
93f5d105cf Updated README 2013-12-28 11:04:01 +01:00
Paweł Jastrzębski
c1c44bdf88 Reverting output extension changes 2013-12-28 10:19:43 +01:00
Paweł Jastrzębski
72132ea908 GUI: Tweaked profile logic 2013-12-28 09:06:10 +01:00
Paweł Jastrzębski
29f901f92a Fixed PDF queue (close #73) 2013-12-28 08:30:37 +01:00
Paweł Jastrzębski
22b7258aa3 GUI: Refactored profile logic 2013-12-27 14:42:22 +01:00
Paweł Jastrzębski
c0f788bd67 Added preliminary support for Kobo devices 2013-12-27 09:51:15 +01:00
Paweł Jastrzębski
8f10e93c08 Fixed KindleGen error handling 2013-12-24 13:47:06 +01:00
Paweł Jastrzębski
4a473e3716 Changed output extension 2013-12-20 09:22:15 +01:00
Ciro Mattia Gonano
89d31cb8e5 Merge master into python3 2013-12-16 22:37:37 +01:00
Paweł Jastrzębski
80b65b12b7 Updated tooltips 2013-12-13 19:22:52 +01:00
Paweł Jastrzębski
e835502837 Version Bump 2013-12-07 20:08:20 +01:00
Paweł Jastrzębski
5bcdc78725 Fixed Panel View bugs 2013-12-07 14:50:37 +01:00
Paweł Jastrzębski
acb4dfad8f Fixex PNG hotfix 2013-12-07 09:52:20 +01:00
Paweł Jastrzębski
7f5de29174 Version Bump 2013-12-06 23:33:04 +01:00
Paweł Jastrzębski
11007402cd Fixed PNG output (sigh!) 2013-12-06 23:27:58 +01:00
Paweł Jastrzębski
0cf92fc48f Fixed psutil detection 2013-12-06 17:58:39 +01:00
Paweł Jastrzębski
953942ca00 Fixed tray icon owner 2013-12-06 17:42:11 +01:00
Paweł Jastrzębski
c46ca8b507 Updated README + Minor tweaks 2013-12-06 17:18:20 +01:00
Paweł Jastrzębski
48d3bee225 Upscaling is now default on Kindle Fire HD/HDX models 2013-12-05 19:49:29 +01:00
Paweł Jastrzębski
3b0e5cc309 Panel View support overhaul - Round 2 2013-12-05 15:41:47 +01:00
Paweł Jastrzębski
e5be31f9d5 TrayIcon: Clicking it now properly unminimize window 2013-12-04 19:04:54 +01:00
Paweł Jastrzębski
17ea85c31f Overhauled Panel View support 2013-12-04 18:32:32 +01:00
Paweł Jastrzębski
572e1422bf Gamma auto mode is now even more automatic 2013-12-04 18:30:19 +01:00
Ciro Mattia Gonano
af263073b5 Update README.md 2013-12-04 11:42:45 +01:00
Ciro Mattia Gonano
7facf2d620 Re-add text link for bitcoin 2013-12-04 11:42:26 +01:00
Ciro Mattia Gonano
eef3ff434b Added BountySource link and reformatted Donations section 2013-12-04 11:08:04 +01:00
Ciro Mattia Gonano
fa94e18a6a Merge branch 'master' into python3 2013-12-04 10:15:25 +01:00
Ciro Mattia Gonano
c680cfd5c5 Update README.md 2013-11-27 12:40:01 +01:00
Paweł Jastrzębski
3e8469611d Updated README 2013-11-25 10:41:30 +01:00
Paweł Jastrzębski
39ab475156 Updated README 2013-11-25 10:38:20 +01:00
Ciro Mattia Gonano
636de67a17 Update README.md 2013-11-25 10:14:56 +01:00
Ciro Mattia Gonano
d80c18f652 Add OS X 10.7 build download link 2013-11-25 10:14:23 +01:00
Ciro Mattia Gonano
9f68e009f1 Merge branch 'master' into python3 2013-11-19 12:49:58 +01:00
Paweł Jastrzębski
557bd2bbbf Added separate resolution for Kindle DX/DXG CBZ output (close #71) 2013-11-19 08:46:13 +01:00
Ciro Mattia Gonano
d33c53b691 Version 4.0 - first draft for Python3 conversion 2013-11-14 15:49:46 +01:00
Paweł Jastrzębski
ddd223c2ec Code cleanup 2013-11-13 11:27:26 +01:00
Paweł Jastrzębski
50f5b600b1 OS specific tweaks to status bar style 2013-11-12 14:46:32 +01:00
Paweł Jastrzębski
d94df8390a Added status bar with links 2013-11-12 14:32:38 +01:00
Paweł Jastrzębski
8b33331929 Disabled systray icon on OSX (close #70) 2013-11-12 13:18:27 +01:00
Paweł Jastrzębski
86a9dde1eb Added simple tray icon (close #69) 2013-11-12 12:13:57 +01:00
Ciro Mattia Gonano
33dec77063 Merge remote-tracking branch 'origin/master' 2013-11-11 11:52:04 +01:00
Ciro Mattia Gonano
fe06e2fa19 Version bump 2013-11-11 11:51:46 +01:00
Paweł Jastrzębski
7b5e3eaafd Updated README 2013-11-11 11:30:00 +01:00
Paweł Jastrzębski
0a30f1ffb9 Implemented OSX PATH change to Windows code too + minor tweaks 2013-11-09 20:09:34 +01:00
Paweł Jastrzębski
8687604d26 Tweak for Windows development environment 2013-11-08 18:19:58 +01:00
Ciro Mattia Gonano
0a9fd6c439 Merge branch 'master' of github.com:ciromattia/kcc 2013-11-08 17:21:42 +01:00
Paweł Jastrzębski
c95a9395de Optimization of ProgressThread 2013-11-08 17:13:41 +01:00
Paweł Jastrzębski
77066d7a9f Optimization of ProgressThread 2013-11-08 17:06:06 +01:00
Paweł Jastrzębski
c8e5b7de9a Implemented new method to detect border color in non-webtoon comics 2013-11-08 16:55:43 +01:00
Ciro Mattia Gonano
3e11a88a7c Bundle 7za and unrar for OSX too. 2013-11-08 15:32:22 +01:00
Paweł Jastrzębski
a7e4968836 GUI tweaks 2013-11-08 15:11:33 +01:00
Paweł Jastrzębski
6d9e2d3c03 Added Linux build script 2013-11-07 22:53:28 +01:00
Paweł Jastrzębski
0789e7a353 Updated README 2013-11-07 13:53:37 +01:00
Ciro Mattia Gonano
ff97a85552 KCC available from 10.6+ 2013-11-07 12:57:39 +01:00
Ciro Mattia Gonano
33cfd92cef Remove 10.8 limit 2013-11-07 12:14:03 +01:00
Paweł Jastrzębski
58513ef59f Updated Inno Setup script 2013-11-07 07:58:03 +01:00
Paweł Jastrzębski
6056e3e767 Updated OSX setup 2013-11-06 18:44:14 +01:00
Paweł Jastrzębski
1b1ed7c4ab Improved error messages about missing dependencies 2013-11-06 13:49:12 +01:00
Paweł Jastrzębski
5b44e4bddd Moved to psutil Popen 2013-11-06 11:41:19 +01:00
Paweł Jastrzębski
54592969a4 Optimized imports 2013-11-06 11:14:01 +01:00
Paweł Jastrzębski
38007ab3d5 Number of KindleGen threads is now dynamic 2013-11-06 11:08:14 +01:00
Paweł Jastrzębski
bdd10c7617 Tweaked KindleGen/KindleUnpack multiprocessing 2013-11-05 16:11:14 +01:00
Paweł Jastrzębski
c0f4bc021a Tweaked ComicRack metadata parser 2013-11-04 20:08:54 +01:00
Paweł Jastrzębski
34d6af93a6 Refactored KindleGen/KindleUnpack handling 2013-11-04 17:07:10 +01:00
Paweł Jastrzębski
0df481dabb Added ComicRack metadata parser 2013-11-03 09:29:13 +01:00
Paweł Jastrzębski
55c5b91411 README update 2013-10-31 14:04:06 +01:00
Paweł Jastrzębski
be745f4602 README update 2013-10-31 13:50:40 +01:00
Paweł Jastrzębski
8bf5ad0f12 Fixed headers 2013-10-30 11:50:32 +01:00
Paweł Jastrzębski
1b723b2fee README update and version bump 2013-10-29 16:45:39 +01:00
Paweł Jastrzębski
6095eb98c4 Added Inno Setup script to create hybrid 32/64bit Windows installer 2013-10-29 15:36:17 +01:00
Paweł Jastrzębski
95bb070a6b Added content server multithreading 2013-10-29 11:00:48 +01:00
Paweł Jastrzębski
75a338304a Code cleanup 2013-10-27 11:33:29 +01:00
Paweł Jastrzębski
1c28305b83 Content server tweaks 2013-10-23 09:19:33 +02:00
Paweł Jastrzębski
1f1abb80be Added simple content server 2013-10-21 15:45:00 +02:00
Paweł Jastrzębski
3addc4563a Added progressbar support in few places 2013-10-20 11:02:53 +02:00
Paweł Jastrzębski
e37e7566e2 Small tweaks 2013-10-18 10:37:51 +02:00
Paweł Jastrzębski
eedf537902 Comic2Panel: Refactored multiprocessing support 2013-10-18 10:37:35 +02:00
Paweł Jastrzębski
5e8bd52433 Refactored multiprocessing support 2013-10-17 22:35:26 +02:00
Paweł Jastrzębski
910e8a6cf9 Added some safeguards against path length limit 2013-10-17 09:25:56 +02:00
Paweł Jastrzębski
edfc2467a3 Title: Don't strip part after dot if source is directory 2013-10-17 08:59:01 +02:00
Paweł Jastrzębski
205170efe4 README update and version bump 2013-10-13 18:38:20 +02:00
Paweł Jastrzębski
fceac407ee Updated OSX setup 2013-10-12 17:54:21 +02:00
Paweł Jastrzębski
4c5ebe5949 GUI update 2013-10-12 11:29:31 +02:00
Paweł Jastrzębski
d12ad26e79 OSX: Fix status window scrolling 2013-10-11 19:31:10 +02:00
Paweł Jastrzębski
bd57665b55 Fixed status window scrolling 2013-10-11 13:18:08 +02:00
Paweł Jastrzębski
c3b8d48813 Changed upscale algorithm to bicubic + little code cleanup 2013-10-11 11:15:21 +02:00
Paweł Jastrzębski
c8933e7326 GUI: Made scrollbars smaller 2013-10-11 10:37:55 +02:00
Paweł Jastrzębski
c95c64ccff CBR/CB7: Unicode fix 2013-10-10 19:52:49 +02:00
Paweł Jastrzębski
c5bcd4c2e4 UNRAR: Suppress rename warnings 2013-10-10 18:53:30 +02:00
Paweł Jastrzębski
9e402897c5 OSX: Say NO for dots 2013-10-10 17:17:32 +02:00
Paweł Jastrzębski
cbf87df551 OSX: File association 2013-10-10 17:07:44 +02:00
Paweł Jastrzębski
ea01492e1f Slugify: Unicode fix 2013-10-10 13:17:03 +02:00
Paweł Jastrzębski
82445d5d3a File association: Socket encoding fix 2013-10-09 13:53:03 +02:00
Paweł Jastrzębski
839bc4cc9e Added support for file association 2013-10-09 11:20:18 +02:00
Paweł Jastrzębski
98c6a569bf This failure can't be ignored 2013-10-09 11:19:17 +02:00
Paweł Jastrzębski
85ad95c0d0 Setup update 2013-10-09 11:17:57 +02:00
Paweł Jastrzębski
1d0498fdce Fix for fix for access denied errors 2013-10-08 17:30:47 +02:00
Ciro Mattia Gonano
ee390c34e9 Merge remote-tracking branch 'origin/master' 2013-10-08 13:01:25 +02:00
Ciro Mattia Gonano
b853615f7d Ensure that filename is always unique, even if KCC-generated ones already exists. 2013-10-08 13:01:15 +02:00
Paweł Jastrzębski
5b2bb30902 Force usage of new Pillow 2013-10-08 12:47:34 +02:00
Paweł Jastrzębski
da4788a6c6 Paths should support UTF-8 now 2013-10-08 12:14:27 +02:00
Paweł Jastrzębski
3022635a71 Allow only one instance + messaging 2013-10-08 11:19:24 +02:00
Paweł Jastrzębski
38d3ae6a6a Attempt to fix access denied errors 2013-10-07 22:30:07 +02:00
Paweł Jastrzębski
3f0eea44f4 Attempt to fix access denied errors 2013-10-07 22:25:01 +02:00
Paweł Jastrzębski
5077f60881 Merged DX/DXG profiles. Fixed PNG quantification. 2013-10-07 12:44:14 +02:00
Paweł Jastrzębski
279f70a6bd Improved PNG output - Final thoughts 2013-10-07 09:20:57 +02:00
Paweł Jastrzębski
01f3596fde GUI improvements 2013-10-06 18:31:48 +02:00
Paweł Jastrzębski
23d3577a06 Improved PNG output 2013-10-06 13:53:17 +02:00
Paweł Jastrzębski
22c75951e0 Fixed logo padding 2013-10-06 13:27:09 +02:00
Paweł Jastrzębski
3d3fb5dc61 GUI: Font size fix 2013-10-04 16:05:29 +02:00
Paweł Jastrzębski
e4a8213a2c Some love for our awesome icon by Nikolay Verin 2013-10-04 15:44:38 +02:00
Paweł Jastrzębski
b2f71ae163 GUI: Quality option should be disabled for CBZ format 2013-10-04 12:27:38 +02:00
Paweł Jastrzębski
53256b0e34 Improved GUI 2013-10-04 11:34:53 +02:00
Paweł Jastrzębski
4ebd3e046d Fixed Panel View generator bug (close #64) 2013-10-03 19:20:59 +02:00
Paweł Jastrzębski
d07d49d2e7 Fixed slugify 2013-09-30 18:32:43 +02:00
Paweł Jastrzębski
111bfb9302 OSX: After packaging PATH is still broken 2013-09-29 11:05:02 +02:00
Paweł Jastrzębski
143b2a7ff5 Merge branch 'v3.3' 2013-09-29 10:35:20 +02:00
Paweł Jastrzębski
e7b47d28d9 Progress bar don't hide on older Kindle 2013-09-28 23:21:09 +02:00
Paweł Jastrzębski
97b44a89d4 Code cleanup 2013-09-28 19:57:49 +02:00
Paweł Jastrzębski
27e01657b1 Added support for Kindle Fire HDX 2013-09-25 12:33:47 +02:00
Paweł Jastrzębski
43638813d7 Fill detection final, final, final improvements 2013-09-25 11:47:40 +02:00
Paweł Jastrzębski
f781b6785c Fill detection final, final improvements 2013-09-23 18:35:30 +02:00
Paweł Jastrzębski
9168cd4109 Tag goodies made with KCC properly :-) 2013-09-23 17:17:46 +02:00
Paweł Jastrzębski
4c49c6ffc9 False ASIN is breaking thumbnail 2013-09-23 11:31:44 +02:00
Paweł Jastrzębski
4890727692 Replaced KindleStrip with KindleUnpack (close #6) 2013-09-23 10:21:45 +02:00
Paweł Jastrzębski
7907a45ca2 Updated OSX GUI 2013-09-20 11:13:41 +02:00
Paweł Jastrzębski
727bbba815 Linux GUI 2013-09-20 10:39:38 +02:00
Paweł Jastrzębski
877da36e5a Fixed stupid typos 2013-09-19 17:46:08 +02:00
Paweł Jastrzębski
ab8effbc32 Added 7z/CB7 support 2013-09-19 11:01:15 +02:00
Paweł Jastrzębski
a58d98f0dc Updated README and version bump 2013-09-18 12:47:33 +02:00
Paweł Jastrzębski
431cb73e61 GUI tweaks 2013-09-18 12:21:05 +02:00
Paweł Jastrzębski
0ee02f2efd Fill detection final improvements 2013-09-18 10:35:07 +02:00
Paweł Jastrzębski
8d5b2a9e88 General improvements 2013-09-16 17:17:13 +02:00
Paweł Jastrzębski
1085673010 Fill detection improvements 2013-09-16 11:20:42 +02:00
Ciro Mattia Gonano
d327a72749 Switching to PyQt correctly evaluates PATH in OS X.
Fixes #7
2013-09-16 11:12:29 +02:00
Paweł Jastrzębski
74add23c14 Panel View - Proper detection of blank pages 2013-09-16 10:18:26 +02:00
Paweł Jastrzębski
9b400573c8 Automatic matching of Panel View layout 2013-09-15 21:05:53 +02:00
Paweł Jastrzębski
a8c3ef7d00 Margins color detection now handles every file 2013-09-15 16:24:14 +02:00
Paweł Jastrzębski
a484582b70 Merged Kindle 3, 4 and 5 profiles 2013-09-15 15:42:23 +02:00
Paweł Jastrzębski
69b956904c Removed support of Virtual Panel View 2013-09-15 15:02:31 +02:00
Paweł Jastrzębski
6e3888f295 Real Panel View - Ignore margins (close #60) 2013-09-15 13:03:30 +02:00
Paweł Jastrzębski
1bfa0eb9c7 Bundled UnRAR with Windows binary 2013-09-14 17:57:11 +02:00
Paweł Jastrzębski
08a342c909 Webtoon mode tweaks 2013-09-14 17:48:53 +02:00
Paweł Jastrzębski
a28ad2b0c7 Little code cleanup 2013-09-11 15:22:18 +02:00
Paweł Jastrzębski
4c96de9cdf Updated README and version bump 2013-09-06 10:00:08 +02:00
Paweł Jastrzębski
3a645abe6f Hotfix for Russian OS 2013-09-06 09:46:22 +02:00
Paweł Jastrzębski
27bd6f96e7 Webtoon mode improvements 2013-08-19 16:46:27 +02:00
Paweł Jastrzębski
a98fac2e95 Webtoon mode improvements 2013-08-17 16:03:36 +02:00
Paweł Jastrzębski
f645b65a9e Added volume auto-split 2013-08-17 12:01:19 +02:00
Paweł Jastrzębski
6eaf8cc374 comic2panel: Detection of corrupted files 2013-08-16 19:25:26 +02:00
Paweł Jastrzębski
61c0b691ab Webtoon mode improvements 2013-08-16 17:10:18 +02:00
Paweł Jastrzębski
394cefb2de Sanitize job input 2013-08-16 17:09:49 +02:00
Paweł Jastrzębski
30d6a55e3c Webtoon mode improvements 2013-08-16 13:28:27 +02:00
Paweł Jastrzębski
e32018e8f6 Improved cleanup (close #58) 2013-08-15 10:05:03 +02:00
Paweł Jastrzębski
6b002a8475 Webtoon mode improvements 2013-08-15 09:48:50 +02:00
Paweł Jastrzębski
97e23c8f50 Web...toon mode improvements 2013-08-14 09:30:31 +02:00
Paweł Jastrzębski
e558ffd807 Temporary disabling new location of tmp files 2013-08-13 13:33:16 +02:00
Paweł Jastrzębski
71d158ca45 Fixed tmp directories - Need more coffee. 2013-08-13 10:56:49 +02:00
Paweł Jastrzębski
5f8e5e0be9 Fixed tmp directories 2013-08-13 10:48:42 +02:00
Paweł Jastrzębski
ff91eb1407 Webstrip mode improvements 2013-08-13 10:30:53 +02:00
Paweł Jastrzębski
877a859ef4 Fixed abort bug 2013-08-13 09:33:46 +02:00
Paweł Jastrzębski
f8b29cd967 Webstrip mode improvements 2013-08-13 09:25:53 +02:00
Paweł Jastrzębski
3d2554c557 Fixed tmp directories 2013-08-12 16:32:40 +02:00
Paweł Jastrzębski
b7d7204d40 Updated README and version bump 2013-08-12 15:59:32 +02:00
Paweł Jastrzębski
876d26d174 GUI: Added webstrip support 2013-08-12 14:01:57 +02:00
Paweł Jastrzębski
3ccb1a63aa Moved location of temp files 2013-08-12 13:03:03 +02:00
Paweł Jastrzębski
c8bb9b4f5f comic2panel: GUI support and itegration with comic2ebook 2013-08-12 12:59:58 +02:00
Paweł Jastrzębski
723be29118 Updated README 2013-08-11 14:56:26 +02:00
Paweł Jastrzębski
2865915cdf comic2panel: Autodetect border color 2013-08-11 14:47:06 +02:00
Paweł Jastrzębski
d3e0c2bb6e Improved detection of corrupted files 2013-08-11 12:58:34 +02:00
Paweł Jastrzębski
5e7ae73861 Updated README 2013-08-09 15:55:39 +02:00
Paweł Jastrzębski
61206b2169 Help cleanup 2013-08-09 15:25:00 +02:00
Paweł Jastrzębski
92e2a8913b No size limit anymore. KCC now split EPUB files before handling them to KindleGen. 2013-08-08 20:21:05 +02:00
Paweł Jastrzębski
ad827828d7 comic2panel: Fixed processing of last panel 2013-08-05 15:47:56 +02:00
Paweł Jastrzębski
faf16084a3 comic2panel: Multiprocessing support 2013-08-05 15:40:28 +02:00
Paweł Jastrzębski
38d2b55456 Added higly experimental parser of webstrips 2013-08-03 16:17:26 +02:00
Paweł Jastrzębski
abcebc54e8 Updated README 2013-08-03 10:23:45 +02:00
Paweł Jastrzębski
40cb963c99 Improved handling of slugification conflicts 2013-08-02 10:52:51 +02:00
Paweł Jastrzębski
9d267a6cc4 Updated README and version bump 2013-07-22 08:43:35 +02:00
Paweł Jastrzębski
462f24149b Implemented Devernay idea 2013-07-22 08:32:59 +02:00
Paweł Jastrzębski
4744b62f91 Interruption fix 2013-07-21 20:25:14 +02:00
Paweł Jastrzębski
08244e7fdc Conversion can be now interrupted 2013-07-21 20:18:04 +02:00
Paweł Jastrzębski
f64fb1bee1 Multiselect - OSX fix 2013-07-21 19:13:39 +02:00
Paweł Jastrzębski
743c3b2466 Added multiselect to add file/directory dialogs 2013-07-21 18:24:24 +02:00
Paweł Jastrzębski
aefa36fef8 Refactored KindleGen error handling 2013-07-11 13:25:32 +02:00
Paweł Jastrzębski
d7f6503196 Added profile: Kindle for Android 2013-07-11 11:47:18 +02:00
Paweł Jastrzębski
3375b8c898 Don't stop conversion if KindleGen return only warnings 2013-07-11 11:01:35 +02:00
Paweł Jastrzębski
52e5919ccd Bucket of dirty hax to improve readability on Linux/OSX 2013-07-10 09:05:44 +02:00
Paweł Jastrzębski
1c2e57adb6 Updated status messages 2013-07-10 08:50:52 +02:00
Paweł Jastrzębski
2e99d6ee0a Updated status messages 2013-07-10 08:29:14 +02:00
Paweł Jastrzębski
6744815f77 Fixed JobList scroll bars 2013-07-10 08:24:13 +02:00
Paweł Jastrzębski
0ba44ab2d3 HTML tag support for addMessage() 2013-07-10 07:51:19 +02:00
Paweł Jastrzębski
a6006450de Improved upscale/stretch options handling 2013-07-08 11:07:37 +02:00
Paweł Jastrzębski
c20e2ba451 Fixed row alignment (#55) 2013-07-04 15:32:15 +02:00
Paweł Jastrzębski
7a0b387c1c Small tweak of NoSplit option 2013-07-04 15:05:16 +02:00
Ciro Mattia Gonano
fdfe5fbe39 Disable horizontal mode check when "no split/rotate" is checked. 2013-07-04 11:50:20 +02:00
Paweł Jastrzębski
35751efad5 Little tweaks 2013-06-28 00:08:36 +02:00
Mateusz
7005c9e40a Fix misleading message when processing empty directories 2013-06-27 23:40:30 +02:00
Paweł Jastrzębski
118cf25ff7 Older UnRAR exit code is 7 when it is called without parameters 2013-06-27 18:13:39 +02:00
49 changed files with 11141 additions and 3487 deletions

9
.gitignore vendored
View File

@@ -2,8 +2,11 @@
*.cbz *.cbz
*.cbr *.cbr
.idea .idea
build
dist
kindlegen*
.DS_Store .DS_Store
Thumbs.db Thumbs.db
build
dist
Output
test
solaio
kindlegen*

25
KCC.qrc
View File

@@ -1,25 +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/clear.png</file>
<file>icons/convert.png</file>
<file>icons/document_new.png</file>
<file>icons/folder_new.png</file>
</qresource>
</RCC>

View File

@@ -1,7 +1,7 @@
ISC LICENSE ISC LICENSE
Copyright (c) 2013 Ciro Mattia Gonano <ciromattia@gmail.com> Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
Copyright (c) 2013 Paweł Jastrzębski <pawelj@vulturis.eu> Copyright (c) 2013-2015 Paweł Jastrzębski <pawelj@iosphe.re>
Permission to use, copy, modify, and/or distribute this software for Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the any purpose with or without fee is hereby granted, provided that the

504
README.md
View File

@@ -1,186 +1,338 @@
# KCC # KCC
**KindleComicConverter** is a Python app to convert comic files or folders to ePub or Panel View MOBI. **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 initally developed for Kindle but since v2.2 it outputs valid ePub 2.0 so _**despite its name, KCC is It was initially developed for Kindle but since version 4.0 it outputs valid EPUB 3.0 so _**despite its name, KCC is
actually a comic to EPUB converter that every e-reader owner can happily use**_. 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. It can also optionally optimize images by applying a number of transformations.
### A word of warning ### 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. **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. Amazon's tool is for comic publishers and involves a lot of manual effort, while **KCC** is for comic/manga readers.
If you want to read some comments over *Amazon's KC2* you can take a look at [this](http://www.mobileread.com/forums/showthread.php?t=207461&page=7#96) and [that](http://www.mobileread.com/forums/showthread.php?t=211047) threads on Mobileread. _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 ;-)
_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 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.
### Donations
If you find **KCC** valuable you can consider donating to the authors: If you find **KCC** valuable you can consider donating to the authors:
- Ciro Mattia Gonano:
* Ciro Mattia Gonano [![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=D8WNYNPBGDAS2) - [![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=D8WNYNPBGDAS2)
* Paweł Jastrzębski [![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YTTJ4LK2JDHPS) - [![Flattr this](http://api.flattr.com/button/flattr-badge-large.png)](http://flattr.com/thing/2260449/ciromattiakcc-on-GitHub)
- Paweł Jastrzębski:
- [![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YTTJ4LK2JDHPS)
- Bitcoin: 1W15wwqsfd7wbaZ6wvSJf1LW1bz6q5L8b
## BINARY RELEASES ## BINARY RELEASES
You can find the latest released binary at the following links: You can find the latest released binary at the following links:
- **Win64:** [http://kcc.vulturis.eu/Win64/](http://kcc.vulturis.eu/Win64/) - **Windows (Vista or newer):** [http://kcc.iosphe.re/Windows/](http://kcc.iosphe.re/Windows/)
- **Win32:** [http://kcc.vulturis.eu/Win32/](http://kcc.vulturis.eu/Win32/) - **Linux:** [http://kcc.iosphe.re/Linux/](http://kcc.iosphe.re/Linux/)
- **OS X:** [http://kcc.vulturis.eu/OSX/](http://kcc.vulturis.eu/OSX/) - **OS X (10.8+):** [http://kcc.iosphe.re/OSX/](http://kcc.iosphe.re/OSX/)
- **Linux:** Just download sourcecode and launch: `python kcc.py`
_It has been reported by a couple of users that version 2.10 crashing on OSX at start. We don't know if that issue still exist in version 3.0. ## DEPENDENCIES
If it happens to you please append your message to [Issue #52](https://github.com/ciromattia/kcc/issues/52)._ Following software is required to run Linux version of **KCC** and/or bare sources:
- Python 3.3+
- [PyQt](http://www.riverbankcomputing.co.uk/software/pyqt/download5) 5.2.0+
- [Pillow](http://pypi.python.org/pypi/Pillow/) 2.7.0+
- [psutil](https://pypi.python.org/pypi/psutil) 2.0+
- [python-slugify](http://pypi.python.org/pypi/python-slugify) 0.1.0+
- [scandir](https://pypi.python.org/pypi/scandir) 0.9+
On Debian based distributions these two commands should install all needed dependencies:
```
sudo apt-get install python3 python3-dev python3-pip python3-pyqt5 libpng-dev libjpeg-dev p7zip-full unrar
sudo pip3 install pillow python-slugify psutil scandir
```
### 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)*
- [UnRAR](http://www.rarlab.com/download.htm) *(For CBR/RAR support)*
- [7za](http://www.7-zip.org/download.html) *(For 7z/CB7 support)*
## INPUT FORMATS ## INPUT FORMATS
**KCC** can understand and convert, at the moment, the following file types: **KCC** can understand and convert, at the moment, the following input types:
- PNG, JPG, GIF, TIFF, BMP - Folders containing: PNG, JPG or GIF files
- Folders
- CBZ, ZIP - CBZ, ZIP
- CBR, RAR *(With `unrar` executable)* - CBR, RAR *(With `unrar` executable)*
- PDF *(Extracting only contained JPG images)* - CB7, 7Z *(With `7za` executable)*
- PDF *(Only extracting 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)*
### 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 - Please refer to official documentation for installing into your system.
- [Pillow](http://pypi.python.org/pypi/Pillow/) - For comic optimizations. Please refer to official documentation for installing into your system.
## USAGE ## USAGE
### Important tips: Should be pretty self-explanatory. All options have detailed informations in tooltips.
* 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.
* 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.
* Output MOBI file should be uploaded via USB. Other methods (e.g. via Calibre) might corrupt it.
* If you're converting color images and the end result is not satisfactory, experiment with gamma correction option (check 1.0 setting first).
### GUI
Should be pretty self-explanatory.
After completed conversion you should find ready file alongside the original input file (same directory). After completed conversion you should find ready file alongside the original input file (same directory).
### Standalone `comic2ebook.py` usage: Please check [our wiki](https://github.com/ciromattia/kcc/wiki/) for more details.
CLI version of **KCC** is intended for power users. It is not idiot-proof like GUI :-)
### Standalone `kcc-c2e.py` usage:
``` ```
Usage: comic2ebook.py [options] comic_file|comic_folder Usage: kcc-c2e [options] comic_file|comic_folder
Options: Options:
--version show program's version number and exit MAIN:
-h, --help show this help message and exit -p PROFILE, --profile=PROFILE
-p PROFILE, --profile=PROFILE Device profile (Available options: K1, K2, K345, KDX,
Device profile (Choose one among K1, K2, K3, K4NT, K4T, KDX, KDXG, KHD, KF, KFHD, KFHD8) [Default=KHD] KPW, KV, KFHD, KFHDX, KFHDX8, KFA, KoMT, KoG, KoGHD, KoA,
-t TITLE, --title=TITLE KoAHD, KoAH2O) [Default=KV]
Comic title [Default=filename] -q QUALITY, --quality=QUALITY
-m, --manga-style Manga style (Right-to-left reading and splitting) [Default=False] Quality of Panel View. 0 - Normal 1 - High 2 - Ultra [Default=0]
--quality=QUALITY Output quality. 0 - Normal 1 - High 2 - Ultra [Default=0] -m, --manga-style Manga style (Right-to-left reading and splitting)
-c, --cbz-output Outputs a CBZ archive and does not generate EPUB -w, --webtoon Webtoon processing mode
--noprocessing Do not apply image preprocessing (Page splitting and optimizations) [Default=True]
--forcepng Create PNG files instead JPEG (For non-Kindle devices) [Default=False] OUTPUT SETTINGS:
--gamma=GAMMA Apply gamma correction to linearize the image [Default=Auto] -o OUTPUT, --output=OUTPUT
--upscale Resize images smaller than device's resolution [Default=False] Output generated file to specified directory or file
--stretch Stretch images to device's resolution [Default=False] -t TITLE, --title=TITLE
--blackborders Use black borders instead of white ones when not stretching and ratio is not like the device's one [Default=False] Comic title [Default=filename or directory name]
--rotate Rotate landscape pages instead of splitting them [Default=False] -f FORMAT, --format=FORMAT
--nosplitrotate Disable splitting and rotation [Default=False] Output format (Available options: Auto, MOBI,
--nocutpagenumbers Do not try to cut page numbering on images [Default=True] EPUB, CBZ) [Default=Auto]
-o OUTPUT, --output=OUTPUT --batchsplit Split output into multiple files
Output generated file (EPUB or CBZ) to specified directory or file
--forcecolor Do not convert images to grayscale [Default=False] PROCESSING:
--customwidth=WIDTH Replace screen width provided by device profile [Default=0] --blackborders Disable autodetection and force black borders
--customheight=HEIGHT Replace screen height provided by device profile [Default=0] --whiteborders Disable autodetection and force white borders
-v, --verbose Verbose output [Default=False] --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
Replace screen width provided by device profile
--customheight=CUSTOMHEIGHT
Replace screen height provided by device profile
OTHER:
-h, --help Show this help message and exit
```
### Standalone `kcc-c2p.py` usage:
```
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
-h, --help Show this help message and exit
``` ```
## CREDITS ## 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:
- `KindleStrip` script &copy; 2010-2012 by **Paul Durrant** and released in public domain - `DualMetaFix` script by **K. Hendricks**. Released with GPL-3 License.
([forum thread](http://www.mobileread.com/forums/showthread.php?t=96903)) - `rarfile.py` script &copy; 2005-2014 **Marko Kreen** <markokr@gmail.com>. Released with ISC License.
- `rarfile.py` script &copy; 2005-2011 **Marko Kreen** <markokr@gmail.com>, released with ISC 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.
- `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 - 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.
- 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 ## SAMPLE FILES CREATED BY KCC
* [Kindle Keyboard](http://kcc.vulturis.eu/Samples/Ubunchu!-K3.mobi) * [Kindle Voyage](http://kcc.iosphe.re/Samples/Ubunchu!-KV.mobi)
* [Kindle DX](http://kcc.vulturis.eu/Samples/Ubunchu!-KDX.mobi) * [Kindle Paperwhite](http://kcc.iosphe.re/Samples/Ubunchu!-KPW.mobi)
* [Kindle DXG](http://kcc.vulturis.eu/Samples/Ubunchu!-KDXG.mobi) * [Kindle](http://kcc.iosphe.re/Samples/Ubunchu!-K345.mobi)
* [Kindle Non-Touch](http://kcc.vulturis.eu/Samples/Ubunchu!-K4NT.mobi) * [Kindle DX/DXG](http://kcc.iosphe.re/Samples/Ubunchu!-KDX.cbz)
* [Kindle Touch](http://kcc.vulturis.eu/Samples/Ubunchu!-K4T.mobi) * [Kobo Mini/Touch](http://kcc.iosphe.re/Samples/Ubunchu!-KoMT.cbz)
* [Kindle Paperwhite](http://kcc.vulturis.eu/Samples/Ubunchu!-KPW.mobi) * [Kobo Glo](http://kcc.iosphe.re/Samples/Ubunchu!-KoG.cbz)
* [Kindle Fire](http://kcc.vulturis.eu/Samples/Ubunchu!-KF.mobi) * [Kobo Glo HD](http://kcc.iosphe.re/Samples/Ubunchu!-KoGHD.cbz)
* [Kindle Fire HD](http://kcc.vulturis.eu/Samples/Ubunchu!-KFHD.mobi) * [Kobo Aura](http://kcc.iosphe.re/Samples/Ubunchu!-KoA.cbz)
* [Kindle Fire HD 8.9"](http://kcc.vulturis.eu/Samples/Ubunchu!-KFHD8.mobi) * [Kobo Aura HD](http://kcc.iosphe.re/Samples/Ubunchu!-KoAHD.cbz)
* [Kobo Aura H2O](http://kcc.iosphe.re/Samples/Ubunchu!-KoAH2O.cbz)
## CHANGELOG ## CHANGELOG
####1.00 ####4.5.1:
* Initial version * Added Kobo Glo HD profile
* Fixed RAR/CBR parsing anomalies
* Minor bug fixes and tweaks
####1.10 ####4.5:
* Added support for CBZ/CBR files in comic2ebook.py * 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
####1.11 ####4.4.1:
* Added support for CBZ/CBR files in KindleComicConverter * Fixed problems with OSX GUI
* Added one missing DLL to Windows installer
####1.20 ####4.4:
* 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! * Improved speed and quality of conversion
* Added RAR5 support
* Dropped BMP and TIFF support
* Fixed some WebToon mode bugs
* Fixed CBR parsing on OSX
####1.30 ####4.3.1:
* Fixed an issue in OPF generation for device resolution * Fixed Kindle Voyage profile
* Reworked options system (call with -h option to get the inline help) * Fixed some bugs in OS X release
* CLI version now support multiple input files at once
* Disabled MCB support
* Other minor tweaks
####1.40 ####4.3:
* Added some options for controlling image optimization * Added profiles for Kindle Voyage and Kobo Aura H2O
* Further optimization (ImageOps, page numbering cut, autocontrast) * Added missing features to CLI version
* Other minor bug fixes
####1.41 ####4.2.1:
* Fixed a serious bug on resizing when img ratio was bigger than device one * 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
####1.50 ####4.2:
* Added subfolder support for multiple chapters. * 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
####2.0 ####4.1:
* GUI! AppleScript is gone and Tk is used to provide cross-platform GUI support. * 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
####2.1 ####4.0.2:
* Added basic error reporting * Fixed some Windows and OSX specific bugs
* Fixed problem with marigns when using HQ mode
#### 2.2: ####4.0.1:
* Added (valid!) ePub 2.0 output * Fixed file lock problems that plagued some Windows users
* Rename .zip files to .cbz to avoid overwriting * Fixed content server failing to start on Windows
* Improved performance of WebToon splitter
* Tweaked margin color detection
####2.3 ####4.0:
* Fixed win32 ePub generation, folder handling, filenames with spaces and subfolders * 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
####2.4 ####3.7.2:
* Use temporary directory as workdir (fixes converting from external volumes and zipfiles renaming) * Fixed problems with HQ mode
* Fixed "add folders" from GUI.
####2.5 ####3.7.1:
* Added --black-borders option to set added borders black when page's ratio is not the device's one (#11). * Hotfixed Kobo profiles
* Fixes epub containing zipped itself (#10)
####2.6 ####3.7:
* Added --rotate option to rotate landscape images instead of splitting them (#16, #24) * Added profiles for KOBO devices
* Added --output option to customize ePub output dir/file (#22) * Improved Panel View support
* Add rendition:layout and rendition:orientation ePub meta tags (supported by new kindlegen 2.8) * Improved WebToon splitter
* Fixed natural sorting for files (#18) * Improved margin color autodetection
* Tweaked EPUB output
* Fixed stretching option
* GUI tweaks and minor bugfixes
####2.7 ####3.6.2:
* Lots of GUI improvements (#27, #13) * Fixed previous PNG output fix
* Added gamma support within --gamma option (defaults to profile-specified gamma) (#26, #27) * Fixed Panel View anomalies
* Added --nodithering option to prevent dithering optimizations (#27)
* Epub margins support (#30) ####3.6.1:
* Fixed no file added if file has no spaces on Windows (#25) * Fixed PNG output
* Gracefully exit if unrar missing (#15)
* Do not call kindlegen if source epub is bigger than 320MB (#17) ####3.6:
* Get filetype from magic number (#14) * Increased quality of Panel View zoom
* PDF conversion works again * 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 ####2.8
* Updated rarfile library * Updated rarfile library
@@ -191,33 +343,73 @@ The app relies and includes the following scripts/binaries:
* Added generic CSS file * Added generic CSS file
* Optimized archive extraction for zip/rar files (#40) * Optimized archive extraction for zip/rar files (#40)
####2.9 ####2.7
* Added support for generating a plain CBZ (skipping all the EPUB/Mobi generation) (#45) * Lots of GUI improvements (#27, #13)
* Prevent output file overwriting the source one: if a duplicate name is detected, append _kcc to the name * Added gamma support within --gamma option (defaults to profile-specified gamma) (#26, #27)
* Rarfile library updated to 2.6 * Added --nodithering option to prevent dithering optimizations (#27)
* Added GIF, TIFF and BMP to supported formats (#42) * EPUB margins support (#30)
* Filenames slugifications (#28, #31, #9, #8) * 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.10: ####2.6
* Multiprocessing support * Added --rotate option to rotate landscape images instead of splitting them (#16, #24)
* Kindle Fire support (color ePub/Mobi) * Added --output option to customize EPUB output dir/file (#22)
* Panel View support for horizontal content * Add rendition:layout and rendition:orientation EPUB meta tags (supported by new kindlegen 2.8)
* Fixed panel order for horizontal pages when --rotate is enabled * Fixed natural sorting for files (#18)
* Disabled cropping and page number cutting for blank pages
* Fixed some slugify issues with specific file naming conventions (#50, #51)
####3.0: ####2.5
* New QT GUI * Added --black-borders option to set added borders black when page's ratio is not the device's one (#11).
* Merge with AWKCC * Fixes EPUB containing zipped itself (#10)
* Added ultra quality mode
* Added support for custom width/height ####2.4
* Added option to disable color conversion * 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
## KNOWN ISSUES ## KNOWN ISSUES
* _Add directory_ dialog allow to select multiple directories but they are not added to job list. [QT bug.](https://bugreports.qt-project.org/browse/QTBUG-21372) Please check [wiki page](https://github.com/ciromattia/kcc/wiki/Known-issues).
* Removing SRCS headers sometimes fail in 32bit enviroments. Due to memory limitations.
## COPYRIGHT ## COPYRIGHT
Copyright (c) 2012-2015 Ciro Mattia Gonano and Paweł Jastrzębski.
Copyright (c) 2012-2013 Ciro Mattia Gonano and Paweł Jastrzębski.
**KCC** is released under ISC LICENSE; see LICENSE.txt for further details. **KCC** is released under ISC LICENSE; see LICENSE.txt for further details.

847
gui/KCC-Linux.ui Normal file
View File

@@ -0,0 +1,847 @@
<?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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Disable image optimizations.&lt;br/&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Input images must be already resized.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - Nothing&lt;br/&gt;&lt;/span&gt;Images smaller than device resolution will not be resized.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - Stretching&lt;br/&gt;&lt;/span&gt;Images smaller than device resolution will be resized. Aspect ratio will be not preserved.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - Upscaling&lt;br/&gt;&lt;/span&gt;Images smaller than device resolution will be resized. Aspect ratio will be preserved.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Stretch/Upscale</string>
</property>
<property name="tristate">
<bool>true</bool>
</property>
</widget>
</item>
<item row="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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Enable special parsing mode for WebToons.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Create PNG files instead JPEG.&lt;br/&gt;Quality increase is not noticeable on most of devices.&lt;br/&gt;Output files &lt;span style=&quot; font-weight:600;&quot;&gt;might&lt;/span&gt; be smaller.&lt;br/&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;MOBI conversion will be much slower.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - Autodetection&lt;br/&gt;&lt;/span&gt;Color of margins fill will be detected automatically.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - White&lt;br/&gt;&lt;/span&gt;Margins will be filled with white color.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - Black&lt;br/&gt;&lt;/span&gt;Margins will be filled with black color.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Disable page splitting and rotation.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Target device.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Output format.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Shift+Click to select the output directory.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>
<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="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Add directory containing JPG, PNG or GIF files to queue.&lt;br/&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;CBR, CBZ and CB7 files inside will not be processed!&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>
<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="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Add CBR, CBZ, CB7 or PDF file to queue.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>
<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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Enable right-to-left reading.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Quality of Panel View/zoom. Highly impact size of output file.&lt;br/&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;This option control only quality of magnification!&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Disable splitting of two-page spreads.&lt;br/&gt;They will be rotated instead.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>
</widget>
<widget class="QPushButton" name="BasicModeButton">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>141</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>260</x>
<y>10</y>
<width>151</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Don't convert images to grayscale.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Resolution of target device.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Resolution of target device.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Resolution of target device.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Resolution of target device.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="inputMask">
<string>0000</string>
</property>
<property name="maxLength">
<number>4</number>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QPushButton" name="EditorButton">
<property name="geometry">
<rect>
<x>160</x>
<y>10</y>
<width>91</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>Editor</string>
</property>
<property name="icon">
<iconset resource="KCC.qrc">
<normaloff>:/Other/icons/editor.png</normaloff>:/Other/icons/editor.png</iconset>
</property>
</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>EditorButton</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>

View File

@@ -7,19 +7,19 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>420</width> <width>420</width>
<height>380</height> <height>397</height>
</rect> </rect>
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>420</width> <width>420</width>
<height>380</height> <height>397</height>
</size> </size>
</property> </property>
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>420</width> <width>420</width>
<height>380</height> <height>397</height>
</size> </size>
</property> </property>
<property name="font"> <property name="font">
@@ -27,9 +27,6 @@
<pointsize>9</pointsize> <pointsize>9</pointsize>
</font> </font>
</property> </property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="windowTitle"> <property name="windowTitle">
<string>Kindle Comic Converter</string> <string>Kindle Comic Converter</string>
</property> </property>
@@ -47,7 +44,7 @@
</property> </property>
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>9</x> <x>4</x>
<y>253</y> <y>253</y>
<width>421</width> <width>421</width>
<height>61</height> <height>61</height>
@@ -55,6 +52,7 @@
</property> </property>
<property name="font"> <property name="font">
<font> <font>
<family>Lucida Grande</family>
<pointsize>9</pointsize> <pointsize>9</pointsize>
</font> </font>
</property> </property>
@@ -63,14 +61,15 @@
<widget class="QCheckBox" name="ProcessingBox"> <widget class="QCheckBox" name="ProcessingBox">
<property name="font"> <property name="font">
<font> <font>
<pointsize>11</pointsize> <family>Lucida Grande</family>
<pointsize>12</pointsize>
</font> </font>
</property> </property>
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Disable image optimizations.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Disable image optimizations.&lt;br/&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Input images must be already resized.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>No optimisation</string> <string>No optimisation</string>
@@ -81,35 +80,40 @@
<widget class="QCheckBox" name="UpscaleBox"> <widget class="QCheckBox" name="UpscaleBox">
<property name="font"> <property name="font">
<font> <font>
<pointsize>11</pointsize> <family>Lucida Grande</family>
<pointsize>12</pointsize>
</font> </font>
</property> </property>
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Enable image upscaling.&lt;br/&gt;Aspect ratio will be preserved.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - Nothing&lt;br/&gt;&lt;/span&gt;Images smaller than device resolution will not be resized.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - Stretching&lt;br/&gt;&lt;/span&gt;Images smaller than device resolution will be resized. Aspect ratio will be not preserved.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - Upscaling&lt;br/&gt;&lt;/span&gt;Images smaller than device resolution will be resized. Aspect ratio will be preserved.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>Upscale images</string> <string>Stretch/Upscale</string>
</property>
<property name="tristate">
<bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1"> <item row="3" column="1">
<widget class="QCheckBox" name="StretchBox"> <widget class="QCheckBox" name="WebtoonBox">
<property name="font"> <property name="font">
<font> <font>
<pointsize>11</pointsize> <family>Lucida Grande</family>
<pointsize>12</pointsize>
</font> </font>
</property> </property>
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Enable image stretching.&lt;br/&gt;Aspect ratio will be not preserved.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Enable special parsing mode for WebToons.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>Stretch images</string> <string>Webtoon mode</string>
</property> </property>
</widget> </widget>
</item> </item>
@@ -117,14 +121,15 @@
<widget class="QCheckBox" name="NoDitheringBox"> <widget class="QCheckBox" name="NoDitheringBox">
<property name="font"> <property name="font">
<font> <font>
<pointsize>11</pointsize> <family>Lucida Grande</family>
<pointsize>12</pointsize>
</font> </font>
</property> </property>
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Create PNG files instead JPEG.&lt;br/&gt;&lt;/span&gt;&lt;span style=&quot; font-size:12pt; font-weight:600;&quot;&gt;Only for non-Kindle devices!&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Create PNG files instead JPEG.&lt;br/&gt;Quality increase is not noticeable on most of devices.&lt;br/&gt;Output files &lt;span style=&quot; font-weight:600;&quot;&gt;might&lt;/span&gt; be smaller.&lt;br/&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;MOBI conversion will be much slower.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>PNG output</string> <string>PNG output</string>
@@ -135,17 +140,21 @@
<widget class="QCheckBox" name="BorderBox"> <widget class="QCheckBox" name="BorderBox">
<property name="font"> <property name="font">
<font> <font>
<pointsize>11</pointsize> <family>Lucida Grande</family>
<pointsize>12</pointsize>
</font> </font>
</property> </property>
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Fill space around images with black color.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - Autodetection&lt;br/&gt;&lt;/span&gt;Color of margins fill will be detected automatically.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - White&lt;br/&gt;&lt;/span&gt;Margins will be filled with white color.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - Black&lt;br/&gt;&lt;/span&gt;Margins will be filled with black color.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>Black borders</string> <string>W/B margins</string>
</property>
<property name="tristate">
<bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
@@ -153,14 +162,15 @@
<widget class="QCheckBox" name="NoRotateBox"> <widget class="QCheckBox" name="NoRotateBox">
<property name="font"> <property name="font">
<font> <font>
<pointsize>11</pointsize> <family>Lucida Grande</family>
<pointsize>12</pointsize>
</font> </font>
</property> </property>
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Disable splitting and rotation.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Disable page splitting and rotation.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>No split/rotate</string> <string>No split/rotate</string>
@@ -173,13 +183,14 @@
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>8</x> <x>8</x>
<y>200</y> <y>201</y>
<width>151</width> <width>151</width>
<height>34</height> <height>34</height>
</rect> </rect>
</property> </property>
<property name="font"> <property name="font">
<font> <font>
<family>Lucida Grande</family>
<pointsize>11</pointsize> <pointsize>11</pointsize>
</font> </font>
</property> </property>
@@ -187,20 +198,21 @@
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>Target device.</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Target device.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
</widget> </widget>
<widget class="QComboBox" name="FormatBox"> <widget class="QComboBox" name="FormatBox">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>262</x> <x>262</x>
<y>200</y> <y>201</y>
<width>152</width> <width>152</width>
<height>34</height> <height>34</height>
</rect> </rect>
</property> </property>
<property name="font"> <property name="font">
<font> <font>
<family>Lucida Grande</family>
<pointsize>11</pointsize> <pointsize>11</pointsize>
</font> </font>
</property> </property>
@@ -208,7 +220,7 @@
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>Output format.</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Output format.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
</widget> </widget>
<widget class="QPushButton" name="ConvertButton"> <widget class="QPushButton" name="ConvertButton">
@@ -222,6 +234,7 @@
</property> </property>
<property name="font"> <property name="font">
<font> <font>
<family>Lucida Grande</family>
<pointsize>11</pointsize> <pointsize>11</pointsize>
<weight>75</weight> <weight>75</weight>
<bold>true</bold> <bold>true</bold>
@@ -230,6 +243,9 @@
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Shift+Click to select the output directory.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text"> <property name="text">
<string>Convert</string> <string>Convert</string>
</property> </property>
@@ -249,12 +265,16 @@
</property> </property>
<property name="font"> <property name="font">
<font> <font>
<family>Lucida Grande</family>
<pointsize>11</pointsize> <pointsize>11</pointsize>
</font> </font>
</property> </property>
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Add directory containing JPG, PNG or GIF files to queue.&lt;br/&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;CBR, CBZ and CB7 files inside will not be processed!&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text"> <property name="text">
<string>Add directory</string> <string>Add directory</string>
</property> </property>
@@ -274,12 +294,16 @@
</property> </property>
<property name="font"> <property name="font">
<font> <font>
<family>Lucida Grande</family>
<pointsize>11</pointsize> <pointsize>11</pointsize>
</font> </font>
</property> </property>
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Add CBR, CBZ, CB7 or PDF file to queue.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text"> <property name="text">
<string>Add file</string> <string>Add file</string>
</property> </property>
@@ -299,6 +323,7 @@
</property> </property>
<property name="font"> <property name="font">
<font> <font>
<family>Lucida Grande</family>
<pointsize>11</pointsize> <pointsize>11</pointsize>
</font> </font>
</property> </property>
@@ -316,7 +341,7 @@
<widget class="QFrame" name="OptionsBasic"> <widget class="QFrame" name="OptionsBasic">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>10</x> <x>5</x>
<y>233</y> <y>233</y>
<width>421</width> <width>421</width>
<height>41</height> <height>41</height>
@@ -324,7 +349,8 @@
</property> </property>
<property name="font"> <property name="font">
<font> <font>
<pointsize>9</pointsize> <family>Lucida Grande</family>
<pointsize>12</pointsize>
</font> </font>
</property> </property>
<widget class="QCheckBox" name="MangaBox"> <widget class="QCheckBox" name="MangaBox">
@@ -338,14 +364,15 @@
</property> </property>
<property name="font"> <property name="font">
<font> <font>
<pointsize>11</pointsize> <family>Lucida Grande</family>
<pointsize>12</pointsize>
</font> </font>
</property> </property>
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Enable right-to-left reading.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Enable right-to-left reading.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>Manga mode</string> <string>Manga mode</string>
@@ -356,20 +383,21 @@
<rect> <rect>
<x>282</x> <x>282</x>
<y>10</y> <y>10</y>
<width>130</width> <width>135</width>
<height>18</height> <height>18</height>
</rect> </rect>
</property> </property>
<property name="font"> <property name="font">
<font> <font>
<pointsize>11</pointsize> <family>Lucida Grande</family>
<pointsize>12</pointsize>
</font> </font>
</property> </property>
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - Normal quality mode&lt;br/&gt;&lt;/span&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:14pt; font-style:italic;&quot;&gt;Use it when Panel View support is not needed.&lt;/span&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600; text-decoration: underline;&quot;&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:14pt;&quot;&gt;- Maximum quality when zoom is not enabled.&lt;br/&gt;- Poor quality when zoom is enabled.&lt;br/&gt;- Lowest file size.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - High quality mode&lt;br/&gt;&lt;/span&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:14pt; font-style:italic;&quot;&gt;Not zoomed image &lt;/span&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600; font-style:italic;&quot;&gt;might &lt;/span&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:14pt; font-style:italic;&quot;&gt;be a little blurry.&lt;/span&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600; text-decoration: underline;&quot;&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:14pt;&quot;&gt;- Medium/High quality when zoom is not enabled.&lt;br/&gt;- Maximum quality when zoom is enabled.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600; text-decoration: underline;&quot;&gt;Checked - Ultra quality mode&lt;br/&gt;&lt;/span&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:14pt; font-style:italic;&quot;&gt;Maximum possible quality.&lt;/span&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600; text-decoration: underline;&quot;&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:14pt;&quot;&gt;- Maximum quality when zoom is not enabled.&lt;br/&gt;- Maximum quality when zoom is enabled.&lt;br/&gt;- Very high file size.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Quality of Panel View/zoom. Highly impact size of output file.&lt;br/&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;This option control only quality of magnification!&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>High/Ultra quality</string> <string>High/Ultra quality</string>
@@ -389,14 +417,15 @@
</property> </property>
<property name="font"> <property name="font">
<font> <font>
<pointsize>11</pointsize> <family>Lucida Grande</family>
<pointsize>12</pointsize>
</font> </font>
</property> </property>
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Disable page spliting.&lt;br/&gt;They will be rotated instead.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Disable splitting of two-page spreads.&lt;br/&gt;They will be rotated instead.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>Horizontal mode</string> <string>Horizontal mode</string>
@@ -417,12 +446,16 @@
</property> </property>
<property name="font"> <property name="font">
<font> <font>
<family>Lucida Grande</family>
<pointsize>11</pointsize> <pointsize>11</pointsize>
</font> </font>
</property> </property>
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </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"> <property name="showDropIndicator" stdset="0">
<bool>false</bool> <bool>false</bool>
</property> </property>
@@ -435,12 +468,13 @@
<rect> <rect>
<x>5</x> <x>5</x>
<y>10</y> <y>10</y>
<width>210</width> <width>156</width>
<height>41</height> <height>41</height>
</rect> </rect>
</property> </property>
<property name="font"> <property name="font">
<font> <font>
<family>Lucida Grande</family>
<pointsize>12</pointsize> <pointsize>12</pointsize>
<weight>50</weight> <weight>50</weight>
<bold>false</bold> <bold>false</bold>
@@ -456,14 +490,15 @@
<widget class="QPushButton" name="AdvModeButton"> <widget class="QPushButton" name="AdvModeButton">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>207</x> <x>260</x>
<y>10</y> <y>10</y>
<width>210</width> <width>156</width>
<height>41</height> <height>41</height>
</rect> </rect>
</property> </property>
<property name="font"> <property name="font">
<font> <font>
<family>Lucida Grande</family>
<pointsize>12</pointsize> <pointsize>12</pointsize>
<weight>50</weight> <weight>50</weight>
<bold>false</bold> <bold>false</bold>
@@ -482,7 +517,7 @@
</property> </property>
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>10</x> <x>5</x>
<y>303</y> <y>303</y>
<width>401</width> <width>401</width>
<height>41</height> <height>41</height>
@@ -490,6 +525,7 @@
</property> </property>
<property name="font"> <property name="font">
<font> <font>
<family>Lucida Grande</family>
<pointsize>9</pointsize> <pointsize>9</pointsize>
</font> </font>
</property> </property>
@@ -504,14 +540,12 @@
</property> </property>
<property name="font"> <property name="font">
<font> <font>
<family>Lucida Grande</family>
<pointsize>12</pointsize> <pointsize>12</pointsize>
<weight>50</weight> <weight>50</weight>
<bold>false</bold> <bold>false</bold>
</font> </font>
</property> </property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;When converting color images setting this option to 1.0 MIGHT improve readability.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text"> <property name="text">
<string>Gamma: Auto</string> <string>Gamma: Auto</string>
</property> </property>
@@ -521,16 +555,18 @@
<rect> <rect>
<x>110</x> <x>110</x>
<y>10</y> <y>10</y>
<width>280</width> <width>290</width>
<height>22</height> <height>22</height>
</rect> </rect>
</property> </property>
<property name="font">
<font>
<family>Lucida Grande</family>
</font>
</property>
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::ClickFocus</enum> <enum>Qt::ClickFocus</enum>
</property> </property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;When converting color images setting this option to 1.0 &lt;/span&gt;&lt;span style=&quot; font-size:12pt; font-weight:600;&quot;&gt;might&lt;/span&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt; improve readability.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="maximum"> <property name="maximum">
<number>500</number> <number>500</number>
</property> </property>
@@ -548,19 +584,17 @@
<x>10</x> <x>10</x>
<y>10</y> <y>10</y>
<width>401</width> <width>401</width>
<height>35</height> <height>29</height>
</rect> </rect>
</property> </property>
<property name="font"> <property name="font">
<font> <font>
<family>Lucida Grande</family>
<pointsize>10</pointsize> <pointsize>10</pointsize>
<weight>75</weight> <weight>75</weight>
<bold>true</bold> <bold>true</bold>
</font> </font>
</property> </property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="value"> <property name="value">
<number>0</number> <number>0</number>
</property> </property>
@@ -574,7 +608,7 @@
<widget class="QFrame" name="OptionsExpert"> <widget class="QFrame" name="OptionsExpert">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>10</x> <x>5</x>
<y>335</y> <y>335</y>
<width>421</width> <width>421</width>
<height>41</height> <height>41</height>
@@ -582,6 +616,7 @@
</property> </property>
<property name="font"> <property name="font">
<font> <font>
<family>Lucida Grande</family>
<pointsize>9</pointsize> <pointsize>9</pointsize>
</font> </font>
</property> </property>
@@ -596,14 +631,15 @@
</property> </property>
<property name="font"> <property name="font">
<font> <font>
<pointsize>11</pointsize> <family>Lucida Grande</family>
<pointsize>12</pointsize>
</font> </font>
</property> </property>
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Do not convert images to grayscale.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Don't convert images to grayscale.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>Color mode</string> <string>Color mode</string>
@@ -612,24 +648,30 @@
<widget class="QFrame" name="OptionsExpertInternal"> <widget class="QFrame" name="OptionsExpertInternal">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>90</x> <x>95</x>
<y>0</y> <y>0</y>
<width>315</width> <width>315</width>
<height>40</height> <height>40</height>
</rect> </rect>
</property> </property>
<property name="font">
<font>
<family>Lucida Grande</family>
</font>
</property>
<layout class="QGridLayout" name="gridLayout_2"> <layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="wLabel"> <widget class="QLabel" name="wLabel">
<property name="font"> <property name="font">
<font> <font>
<family>Lucida Grande</family>
<pointsize>12</pointsize> <pointsize>12</pointsize>
<weight>50</weight> <weight>50</weight>
<bold>false</bold> <bold>false</bold>
</font> </font>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Resolution of target device.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Resolution of target device.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>Custom width: </string> <string>Custom width: </string>
@@ -652,6 +694,7 @@
</property> </property>
<property name="font"> <property name="font">
<font> <font>
<family>Lucida Grande</family>
<pointsize>12</pointsize> <pointsize>12</pointsize>
</font> </font>
</property> </property>
@@ -662,10 +705,10 @@
<bool>false</bool> <bool>false</bool>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Resolution of target device.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Resolution of target device.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="inputMask"> <property name="inputMask">
<string>0000; </string> <string>0000</string>
</property> </property>
<property name="maxLength"> <property name="maxLength">
<number>4</number> <number>4</number>
@@ -676,13 +719,14 @@
<widget class="QLabel" name="hLabel"> <widget class="QLabel" name="hLabel">
<property name="font"> <property name="font">
<font> <font>
<family>Lucida Grande</family>
<pointsize>12</pointsize> <pointsize>12</pointsize>
<weight>50</weight> <weight>50</weight>
<bold>false</bold> <bold>false</bold>
</font> </font>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Resolution of target device.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Resolution of target device.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>Custom height: </string> <string>Custom height: </string>
@@ -705,6 +749,7 @@
</property> </property>
<property name="font"> <property name="font">
<font> <font>
<family>Lucida Grande</family>
<pointsize>12</pointsize> <pointsize>12</pointsize>
</font> </font>
</property> </property>
@@ -715,10 +760,10 @@
<bool>false</bool> <bool>false</bool>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Resolution of target device.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Resolution of target device.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="inputMask"> <property name="inputMask">
<string>0000; </string> <string>0000</string>
</property> </property>
<property name="maxLength"> <property name="maxLength">
<number>4</number> <number>4</number>
@@ -728,9 +773,34 @@
</layout> </layout>
</widget> </widget>
</widget> </widget>
<widget class="QPushButton" name="EditorButton">
<property name="geometry">
<rect>
<x>160</x>
<y>10</y>
<width>101</width>
<height>41</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="text">
<string>Editor</string>
</property>
<property name="icon">
<iconset resource="KCC.qrc">
<normaloff>:/Other/icons/editor.png</normaloff>:/Other/icons/editor.png</iconset>
</property>
</widget>
<zorder>BasicModeButton</zorder> <zorder>BasicModeButton</zorder>
<zorder>AdvModeButton</zorder> <zorder>AdvModeButton</zorder>
<zorder>ProgressBar</zorder>
<zorder>JobList</zorder> <zorder>JobList</zorder>
<zorder>OptionsAdvanced</zorder> <zorder>OptionsAdvanced</zorder>
<zorder>DeviceBox</zorder> <zorder>DeviceBox</zorder>
@@ -742,6 +812,19 @@
<zorder>OptionsBasic</zorder> <zorder>OptionsBasic</zorder>
<zorder>OptionsAdvancedGamma</zorder> <zorder>OptionsAdvancedGamma</zorder>
<zorder>OptionsExpert</zorder> <zorder>OptionsExpert</zorder>
<zorder>EditorButton</zorder>
<zorder>ProgressBar</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> </widget>
<action name="ActionBasic"> <action name="ActionBasic">
<property name="checkable"> <property name="checkable">

28
gui/KCC.qrc Normal file
View File

@@ -0,0 +1,28 @@
<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/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>

View File

@@ -7,19 +7,19 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>420</width> <width>420</width>
<height>380</height> <height>397</height>
</rect> </rect>
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>420</width> <width>420</width>
<height>380</height> <height>397</height>
</size> </size>
</property> </property>
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>420</width> <width>420</width>
<height>380</height> <height>397</height>
</size> </size>
</property> </property>
<property name="font"> <property name="font">
@@ -27,9 +27,6 @@
<pointsize>9</pointsize> <pointsize>9</pointsize>
</font> </font>
</property> </property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="windowTitle"> <property name="windowTitle">
<string>Kindle Comic Converter</string> <string>Kindle Comic Converter</string>
</property> </property>
@@ -59,13 +56,16 @@
</font> </font>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>9</number>
</property>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QCheckBox" name="ProcessingBox"> <widget class="QCheckBox" name="ProcessingBox">
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>Disable image optimizations.</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Disable image optimizations.&lt;br/&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Input images must be already resized.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>No optimisation</string> <string>No optimisation</string>
@@ -78,23 +78,26 @@
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Enable image upscaling.&lt;br/&gt;Aspect ratio will be preserved.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - Nothing&lt;br/&gt;&lt;/span&gt;Images smaller than device resolution will not be resized.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - Stretching&lt;br/&gt;&lt;/span&gt;Images smaller than device resolution will be resized. Aspect ratio will be not preserved.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - Upscaling&lt;br/&gt;&lt;/span&gt;Images smaller than device resolution will be resized. Aspect ratio will be preserved.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>Upscale images</string> <string>Stretch/Upscale</string>
</property>
<property name="tristate">
<bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1"> <item row="3" column="1">
<widget class="QCheckBox" name="StretchBox"> <widget class="QCheckBox" name="WebtoonBox">
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Enable image stretching.&lt;br/&gt;Aspect ratio will be not preserved.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Enable special parsing mode for WebToons.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>Stretch images</string> <string>Webtoon mode</string>
</property> </property>
</widget> </widget>
</item> </item>
@@ -104,7 +107,7 @@
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Create PNG files instead JPEG.&lt;br/&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Only for non-Kindle devices!&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Create PNG files instead JPEG.&lt;br/&gt;Quality increase is not noticeable on most of devices.&lt;br/&gt;Output files &lt;span style=&quot; font-weight:600;&quot;&gt;might&lt;/span&gt; be smaller.&lt;br/&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;MOBI conversion will be much slower.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>PNG output</string> <string>PNG output</string>
@@ -117,10 +120,13 @@
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>Fill space around images with black color.</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - Autodetection&lt;br/&gt;&lt;/span&gt;Color of margins fill will be detected automatically.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - White&lt;br/&gt;&lt;/span&gt;Margins will be filled with white color.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - Black&lt;br/&gt;&lt;/span&gt;Margins will be filled with black color.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>Black borders</string> <string>W/B margins</string>
</property>
<property name="tristate">
<bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
@@ -130,7 +136,7 @@
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Disable splitting and rotation.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Disable page splitting and rotation.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>No split/rotate</string> <string>No split/rotate</string>
@@ -157,7 +163,7 @@
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>Target device.</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Target device.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
</widget> </widget>
<widget class="QComboBox" name="FormatBox"> <widget class="QComboBox" name="FormatBox">
@@ -178,7 +184,7 @@
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>Output format.</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Output format.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
</widget> </widget>
<widget class="QPushButton" name="ConvertButton"> <widget class="QPushButton" name="ConvertButton">
@@ -200,6 +206,9 @@
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Shift+Click to select the output directory.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text"> <property name="text">
<string>Convert</string> <string>Convert</string>
</property> </property>
@@ -225,6 +234,9 @@
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Add directory containing JPG, PNG or GIF files to queue.&lt;br/&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;CBR, CBZ and CB7 files inside will not be processed!&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text"> <property name="text">
<string>Add directory</string> <string>Add directory</string>
</property> </property>
@@ -250,6 +262,9 @@
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Add CBR, CBZ, CB7 or PDF file to queue.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text"> <property name="text">
<string>Add file</string> <string>Add file</string>
</property> </property>
@@ -310,7 +325,7 @@
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>Enable right-to-left reading.</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Enable right-to-left reading.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>Manga mode</string> <string>Manga mode</string>
@@ -329,13 +344,7 @@
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt; <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Quality of Panel View/zoom. Highly impact size of output file.&lt;br/&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;This option control only quality of magnification!&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - Normal quality mode&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;Use it when Panel View support is not needed.&lt;/span&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;&lt;br /&gt;&lt;/span&gt;- Maximum quality when zoom is not enabled.&lt;br /&gt;- Poor quality when zoom is enabled.&lt;br /&gt;- Lowest file size.&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - High quality mode&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;Not zoomed image &lt;/span&gt;&lt;span style=&quot; font-weight:600; font-style:italic;&quot;&gt;might &lt;/span&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;be &lt;/span&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;a little blurry.&lt;/span&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;&lt;br /&gt;&lt;/span&gt;- Medium/High quality when zoom is not enabled.&lt;br /&gt;- Maximum quality when zoom is enabled.&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - Ultra quality mode&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;Maximum possible quality.&lt;/span&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;&lt;br /&gt;&lt;/span&gt;- Maximum quality when zoom is not enabled.&lt;br /&gt;- Maximum quality when zoom is enabled.&lt;br /&gt;- Very high file size.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>High/Ultra quality</string> <string>High/Ultra quality</string>
@@ -357,7 +366,7 @@ p, li { white-space: pre-wrap; }
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Disable page spliting.&lt;br/&gt;They will be rotated instead.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Disable splitting of two-page spreads.&lt;br/&gt;They will be rotated instead.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>Horizontal mode</string> <string>Horizontal mode</string>
@@ -379,6 +388,9 @@ p, li { white-space: pre-wrap; }
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </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"> <property name="showDropIndicator" stdset="0">
<bool>false</bool> <bool>false</bool>
</property> </property>
@@ -391,7 +403,7 @@ p, li { white-space: pre-wrap; }
<rect> <rect>
<x>10</x> <x>10</x>
<y>10</y> <y>10</y>
<width>195</width> <width>141</width>
<height>32</height> <height>32</height>
</rect> </rect>
</property> </property>
@@ -410,9 +422,9 @@ p, li { white-space: pre-wrap; }
<widget class="QPushButton" name="AdvModeButton"> <widget class="QPushButton" name="AdvModeButton">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>217</x> <x>261</x>
<y>10</y> <y>10</y>
<width>195</width> <width>151</width>
<height>32</height> <height>32</height>
</rect> </rect>
</property> </property>
@@ -454,9 +466,6 @@ p, li { white-space: pre-wrap; }
<height>40</height> <height>40</height>
</rect> </rect>
</property> </property>
<property name="toolTip">
<string>When converting color images setting this option to 1.0 MIGHT improve readability.</string>
</property>
<property name="text"> <property name="text">
<string>Gamma: Auto</string> <string>Gamma: Auto</string>
</property> </property>
@@ -473,9 +482,6 @@ p, li { white-space: pre-wrap; }
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::ClickFocus</enum> <enum>Qt::ClickFocus</enum>
</property> </property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;When converting color images setting this option to 1.0 &lt;span style=&quot; font-weight:600;&quot;&gt;might&lt;/span&gt; improve readability.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="maximum"> <property name="maximum">
<number>500</number> <number>500</number>
</property> </property>
@@ -540,7 +546,7 @@ p, li { white-space: pre-wrap; }
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>Do not convert images to grayscale.</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Don't convert images to grayscale.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>Color mode</string> <string>Color mode</string>
@@ -559,7 +565,7 @@ p, li { white-space: pre-wrap; }
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="wLabel"> <widget class="QLabel" name="wLabel">
<property name="toolTip"> <property name="toolTip">
<string>Resolution of target device.</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Resolution of target device.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>Custom width: </string> <string>Custom width: </string>
@@ -587,10 +593,10 @@ p, li { white-space: pre-wrap; }
<bool>false</bool> <bool>false</bool>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>Resolution of target device.</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Resolution of target device.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="inputMask"> <property name="inputMask">
<string>0000; </string> <string>0000</string>
</property> </property>
<property name="maxLength"> <property name="maxLength">
<number>4</number> <number>4</number>
@@ -600,7 +606,7 @@ p, li { white-space: pre-wrap; }
<item row="0" column="2"> <item row="0" column="2">
<widget class="QLabel" name="hLabel"> <widget class="QLabel" name="hLabel">
<property name="toolTip"> <property name="toolTip">
<string>Resolution of target device.</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Resolution of target device.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>Custom height: </string> <string>Custom height: </string>
@@ -628,10 +634,10 @@ p, li { white-space: pre-wrap; }
<bool>false</bool> <bool>false</bool>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>Resolution of target device.</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Resolution of target device.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="inputMask"> <property name="inputMask">
<string>0000; </string> <string>0000</string>
</property> </property>
<property name="maxLength"> <property name="maxLength">
<number>4</number> <number>4</number>
@@ -641,6 +647,31 @@ p, li { white-space: pre-wrap; }
</layout> </layout>
</widget> </widget>
</widget> </widget>
<widget class="QPushButton" name="EditorButton">
<property name="geometry">
<rect>
<x>160</x>
<y>10</y>
<width>91</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>Editor</string>
</property>
<property name="icon">
<iconset resource="KCC.qrc">
<normaloff>:/Other/icons/editor.png</normaloff>:/Other/icons/editor.png</iconset>
</property>
</widget>
<zorder>OptionsAdvanced</zorder> <zorder>OptionsAdvanced</zorder>
<zorder>DeviceBox</zorder> <zorder>DeviceBox</zorder>
<zorder>FormatBox</zorder> <zorder>FormatBox</zorder>
@@ -654,8 +685,20 @@ p, li { white-space: pre-wrap; }
<zorder>AdvModeButton</zorder> <zorder>AdvModeButton</zorder>
<zorder>OptionsAdvancedGamma</zorder> <zorder>OptionsAdvancedGamma</zorder>
<zorder>OptionsExpert</zorder> <zorder>OptionsExpert</zorder>
<zorder>EditorButton</zorder>
<zorder>ProgressBar</zorder> <zorder>ProgressBar</zorder>
</widget> </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"> <action name="ActionBasic">
<property name="checkable"> <property name="checkable">
<bool>true</bool> <bool>true</bool>

226
gui/MetaEditor-Linux.ui Normal file
View File

@@ -0,0 +1,226 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MetaEditorDialog</class>
<widget class="QDialog" name="MetaEditorDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>320</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>400</width>
<height>320</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>400</width>
<height>320</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>
<widget class="QWidget" name="horizontalLayoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>280</y>
<width>381</width>
<height>31</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="StatusLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<pointsize>10</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="styleSheet">
<string notr="true">color: rgb(255, 0, 0);</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="OKButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</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="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</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>
<widget class="QFrame" name="EditorFrame">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>381</width>
<height>271</height>
</rect>
</property>
<widget class="QWidget" name="formLayoutWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>381</width>
<height>266</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Series:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="SeriesLine"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Volume:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="VolumeLine"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Number:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="NumberLine"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Writer:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="WriterLine"/>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Penciller:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="PencillerLine"/>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Inker:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLineEdit" name="InkerLine"/>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Colorist:</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLineEdit" name="ColoristLine"/>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/ciromattia/kcc/wiki/Manga-Cover-Database-support&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;MUid:&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLineEdit" name="MUidLine"/>
</item>
</layout>
</widget>
</widget>
<zorder>horizontalLayoutWidget</zorder>
<zorder>EditorFrame</zorder>
<zorder>StatusLabel</zorder>
</widget>
<resources>
<include location="KCC.qrc"/>
</resources>
<connections/>
</ui>

223
gui/MetaEditor-OSX.ui Normal file
View File

@@ -0,0 +1,223 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MetaEditorDialog</class>
<widget class="QDialog" name="MetaEditorDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>295</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>400</width>
<height>295</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>400</width>
<height>295</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>
<widget class="QWidget" name="horizontalLayoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>260</y>
<width>381</width>
<height>32</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="StatusLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<pointsize>10</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="styleSheet">
<string notr="true">color: rgb(255, 0, 0);</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="OKButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</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="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</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>
<widget class="QFrame" name="EditorFrame">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>381</width>
<height>251</height>
</rect>
</property>
<widget class="QWidget" name="formLayoutWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>381</width>
<height>250</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Series:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="SeriesLine"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Volume:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="VolumeLine"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Number:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="NumberLine"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Writer:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="WriterLine"/>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Penciller:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="PencillerLine"/>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Inker:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLineEdit" name="InkerLine"/>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Colorist:</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLineEdit" name="ColoristLine"/>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/ciromattia/kcc/wiki/Manga-Cover-Database-support&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;MUid:&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLineEdit" name="MUidLine"/>
</item>
</layout>
</widget>
</widget>
</widget>
<resources>
<include location="KCC.qrc"/>
</resources>
<connections/>
</ui>

222
gui/MetaEditor.ui Normal file
View File

@@ -0,0 +1,222 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MetaEditorDialog</class>
<widget class="QDialog" name="MetaEditorDialog">
<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="maximumSize">
<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>
<widget class="QWidget" name="horizontalLayoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>220</y>
<width>381</width>
<height>31</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="StatusLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="styleSheet">
<string notr="true">color: rgb(255, 0, 0);</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="OKButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</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="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</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>
<widget class="QFrame" name="EditorFrame">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>381</width>
<height>211</height>
</rect>
</property>
<widget class="QWidget" name="formLayoutWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>381</width>
<height>211</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Series:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="SeriesLine"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Volume:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="VolumeLine"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Number:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="NumberLine"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Writer:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="WriterLine"/>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Penciller:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="PencillerLine"/>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Inker:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLineEdit" name="InkerLine"/>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Colorist:</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLineEdit" name="ColoristLine"/>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/ciromattia/kcc/wiki/Manga-Cover-Database-support&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;MUid:&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLineEdit" name="MUidLine"/>
</item>
</layout>
</widget>
</widget>
</widget>
<resources>
<include location="KCC.qrc"/>
</resources>
<connections/>
</ui>

BIN
icons/Kobo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
icons/Wizard-Small.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
icons/Wizard.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 KiB

BIN
icons/editor.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
icons/list_background.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

BIN
icons/list_background.xcf Normal file

Binary file not shown.

37
kcc-c2e.py Executable file
View File

@@ -0,0 +1,37 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
# Copyright (c) 2013-2015 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 kcc.shared import dependencyCheck
dependencyCheck(2)
from multiprocessing import freeze_support
from kcc import __version__
from kcc.comic2ebook import main
if __name__ == "__main__":
freeze_support()
print('comic2ebook v' + __version__ + ' - Written by Ciro Mattia Gonano and Pawel Jastrzebski.')
main(sys.argv[1:])
sys.exit(0)

37
kcc-c2p.py Executable file
View File

@@ -0,0 +1,37 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
# Copyright (c) 2013-2015 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 kcc.shared import dependencyCheck
dependencyCheck(1)
from multiprocessing import freeze_support
from kcc import __version__
from kcc.comic2panel import main
if __name__ == "__main__":
freeze_support()
print('comic2panel v' + __version__ + ' - Written by Ciro Mattia Gonano and Pawel Jastrzebski.')
main(sys.argv[1:])
sys.exit(0)

133
kcc.iss Normal file
View File

@@ -0,0 +1,133 @@
#define MyAppName "Kindle Comic Converter"
#define MyAppVersion "4.5.1"
#define MyAppPublisher "Ciro Mattia Gonano, Paweł Jastrzębski"
#define MyAppURL "http://kcc.iosphe.re/"
#define MyAppExeName "KCC.exe"
[Setup]
AppId={{7D279A59-C65E-4DA7-B165-56DD06596216}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
AppCopyright=Copyright (C) 2012-2015 Ciro Mattia Gonano and Paweł Jastrzębski
DefaultDirName={pf}\{#MyAppName}
DefaultGroupName={#MyAppName}
AllowNoIcons=yes
LicenseFile=LICENSE.txt
OutputBaseFilename=KindleComicConverter_win_{#MyAppVersion}
SetupIconFile=icons\comic2ebook.ico
SolidCompression=yes
ArchitecturesInstallIn64BitMode=x64
ShowLanguageDialog=no
LanguageDetectionMethod=none
WizardImageFile=icons\Wizard.bmp
WizardSmallImageFile=icons\Wizard-Small.bmp
UninstallDisplayName={#MyAppName}
UninstallDisplayIcon={app}\{#MyAppExeName}
ChangesAssociations=True
InfoAfterFile=other\InstallWarning.rtf
SignTool=SignTool /d $q{#MyAppName}$q /du $q{#MyAppURL}$q $f
MinVersion=0,6.0
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
Name: "CBZassociation"; Description: "CBZ"; GroupDescription: "File associations:"
Name: "CBRassociation"; Description: "CBR"; GroupDescription: "File associations:"
Name: "CB7association"; Description: "CB7"; GroupDescription: "File associations:"
[Files]
; x64 files
Source: "dist_64\platforms\*"; DestDir: "{app}\platforms\"; Flags: ignoreversion; Check: Is64BitInstallMode
Source: "dist_64\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
Source: "dist_64\*.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
Source: "other\vcredist_x64.exe"; DestDir: "{tmp}"; Flags: ignoreversion deleteafterinstall; Check: Is64BitInstallMode
; x86 files
Source: "dist\platforms\*"; DestDir: "{app}\platforms\"; Flags: ignoreversion; Check: not Is64BitInstallMode
Source: "dist\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
Source: "dist\*.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
Source: "other\vcredist_x86.exe"; DestDir: "{tmp}"; Flags: ignoreversion deleteafterinstall; Check: not Is64BitInstallMode
; Common files
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
[Icons]
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
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
Filename: "{tmp}\vcredist_x64.exe"; Parameters: "/passive /Q:a /c:""msiexec /qb /i vcredist.msi"" "; StatusMsg: "Installing Microsoft Visual C++ 2010 Redistributable Package..."; Check: Is64BitInstallMode
Filename: "{tmp}\vcredist_x86.exe"; Parameters: "/passive /Q:a /c:""msiexec /qb /i vcredist.msi"" "; StatusMsg: "Installing Microsoft Visual C++ 2010 Redistributable Package..."; Check: not Is64BitInstallMode
[Messages]
WelcomeLabel1=Welcome to the KCC Setup Wizard
FinishedHeadingLabel=Completing the KCC Setup Wizard
[Registry]
Root: HKCR; SubKey: ".cbz"; ValueType: string; ValueData: "KCCZIP"; Flags: uninsdeletekey; Tasks: CBZassociation
Root: HKCR; SubKey: "KCCZIP"; ValueType: string; ValueData: "KCC ZIP Archive"; Flags: uninsdeletekey; Tasks: CBZassociation
Root: HKCR; SubKey: "KCCZIP\Shell\Open\Command"; ValueType: string; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey; Tasks: CBZassociation
Root: HKCR; Subkey: "KCCZIP\DefaultIcon"; ValueType: string; ValueData: "{app}\{#MyAppExeName},0"; Flags: uninsdeletevalue; Tasks: CBZassociation
Root: HKCR; SubKey: ".cbr"; ValueType: string; ValueData: "KCCRAR"; Flags: uninsdeletekey; Tasks: CBRassociation
Root: HKCR; SubKey: "KCCRAR"; ValueType: string; ValueData: "KCC RAR Archive"; Flags: uninsdeletekey; Tasks: CBRassociation
Root: HKCR; SubKey: "KCCRAR\Shell\Open\Command"; ValueType: string; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey; Tasks: CBRassociation
Root: HKCR; Subkey: "KCCRAR\DefaultIcon"; ValueType: string; ValueData: "{app}\{#MyAppExeName},0"; Flags: uninsdeletevalue; Tasks: CBRassociation
Root: HKCR; SubKey: ".cb7"; ValueType: string; ValueData: "KCCCB7"; Flags: uninsdeletekey; Tasks: CB7association
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;

78
kcc.py Normal file → Executable file
View File

@@ -1,7 +1,8 @@
#!/usr/bin/env python #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# Copyright (c) 2012 Ciro Mattia Gonano <ciromattia@gmail.com> # Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
# Copyright (c) 2013-2015 Pawel Jastrzebski <pawelj@iosphe.re>
# #
# Permission to use, copy, modify, and/or distribute this software for # Permission to use, copy, modify, and/or distribute this software for
# any purpose with or without fee is hereby granted, provided that the # any purpose with or without fee is hereby granted, provided that the
@@ -16,36 +17,53 @@
# OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER # OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE. # PERFORMANCE OF THIS SOFTWARE.
#
__version__ = '3.0'
__license__ = 'ISC'
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
__docformat__ = 'restructuredtext en'
import sys import sys
import os if sys.version_info[0] != 3:
try: print('ERROR: This is Python 3 script!')
# noinspection PyUnresolvedReferences
from PyQt4 import QtGui
except ImportError:
print "ERROR: PyQT4 is not installed!"
exit(1) exit(1)
from kcc import KCC_gui
# OS specific PATH variable workarounds
import os
if sys.platform.startswith('darwin'):
if 'RESOURCEPATH' not in os.environ:
os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + '/other/:' + os.environ['PATH']
else:
os.environ['PATH'] = './../Resources:/usr/local/bin:/usr/bin:/bin'
elif sys.platform.startswith('win'):
if getattr(sys, 'frozen', False):
os.chdir(os.path.dirname(os.path.abspath(sys.executable)))
# Implementing dummy stdout and stderr for frozen Windows release
class FakeSTD(object):
def write(self, string):
pass
def flush(self):
pass
sys.stdout = FakeSTD()
sys.stderr = FakeSTD()
else:
os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + '/other/;' + os.environ['PATH']
os.chdir(os.path.dirname(os.path.abspath(__file__)))
from kcc.shared import dependencyCheck
dependencyCheck(3)
from multiprocessing import freeze_support from multiprocessing import freeze_support
from kcc import KCC_gui
if sys.platform == 'darwin': if __name__ == "__main__":
os.environ['PATH'] = '/usr/local/bin:' + os.environ['PATH'] freeze_support()
from kcc import KCC_ui_osx as KCC_ui KCCAplication = KCC_gui.QApplicationMessaging(sys.argv)
else: if KCCAplication.isRunning():
from kcc import KCC_ui if len(sys.argv) > 1:
KCCAplication.sendMessage(sys.argv[1])
freeze_support() else:
APP = QtGui.QApplication(sys.argv) KCCAplication.sendMessage('ARISE')
KCC = QtGui.QMainWindow() else:
UI = KCC_ui.Ui_KCC() KCCWindow = KCC_gui.QMainWindowKCC()
UI.setupUi(KCC) KCCUI = KCC_gui.KCCGUI(KCCAplication, KCCWindow)
GUI = KCC_gui.Ui_KCC(UI, KCC) if len(sys.argv) > 1:
KCC.setWindowTitle("Kindle Comic Converter " + __version__) KCCUI.handleMessage(sys.argv[1])
KCC.show() sys.exit(KCCAplication.exec_())
KCC.raise_()
sys.exit(APP.exec_())

147
kcc/KCC_MetaEditor_ui.py Normal file
View File

@@ -0,0 +1,147 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'MetaEditor.ui'
#
# Created: Sun Feb 8 11:52:00 2015
# by: PyQt5 UI code generator 5.4
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MetaEditorDialog(object):
def setupUi(self, MetaEditorDialog):
MetaEditorDialog.setObjectName("MetaEditorDialog")
MetaEditorDialog.resize(400, 260)
MetaEditorDialog.setMinimumSize(QtCore.QSize(400, 260))
MetaEditorDialog.setMaximumSize(QtCore.QSize(400, 260))
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/Icon/icons/comic2ebook.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
MetaEditorDialog.setWindowIcon(icon)
self.horizontalLayoutWidget = QtWidgets.QWidget(MetaEditorDialog)
self.horizontalLayoutWidget.setGeometry(QtCore.QRect(10, 220, 381, 31))
self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.StatusLabel = QtWidgets.QLabel(self.horizontalLayoutWidget)
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)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.StatusLabel.setFont(font)
self.StatusLabel.setStyleSheet("color: rgb(255, 0, 0);")
self.StatusLabel.setObjectName("StatusLabel")
self.horizontalLayout.addWidget(self.StatusLabel)
self.OKButton = QtWidgets.QPushButton(self.horizontalLayoutWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.OKButton.sizePolicy().hasHeightForWidth())
self.OKButton.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.OKButton.setFont(font)
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.horizontalLayoutWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.CancelButton.sizePolicy().hasHeightForWidth())
self.CancelButton.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.CancelButton.setFont(font)
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.EditorFrame = QtWidgets.QFrame(MetaEditorDialog)
self.EditorFrame.setGeometry(QtCore.QRect(10, 10, 381, 211))
self.EditorFrame.setObjectName("EditorFrame")
self.formLayoutWidget = QtWidgets.QWidget(self.EditorFrame)
self.formLayoutWidget.setGeometry(QtCore.QRect(0, 0, 381, 211))
self.formLayoutWidget.setObjectName("formLayoutWidget")
self.formLayout = QtWidgets.QFormLayout(self.formLayoutWidget)
self.formLayout.setContentsMargins(0, 0, 0, 0)
self.formLayout.setObjectName("formLayout")
self.label = QtWidgets.QLabel(self.formLayoutWidget)
self.label.setObjectName("label")
self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label)
self.SeriesLine = QtWidgets.QLineEdit(self.formLayoutWidget)
self.SeriesLine.setObjectName("SeriesLine")
self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.SeriesLine)
self.label_2 = QtWidgets.QLabel(self.formLayoutWidget)
self.label_2.setObjectName("label_2")
self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.label_2)
self.VolumeLine = QtWidgets.QLineEdit(self.formLayoutWidget)
self.VolumeLine.setObjectName("VolumeLine")
self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.VolumeLine)
self.label_3 = QtWidgets.QLabel(self.formLayoutWidget)
self.label_3.setObjectName("label_3")
self.formLayout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.label_3)
self.NumberLine = QtWidgets.QLineEdit(self.formLayoutWidget)
self.NumberLine.setObjectName("NumberLine")
self.formLayout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.NumberLine)
self.label_4 = QtWidgets.QLabel(self.formLayoutWidget)
self.label_4.setObjectName("label_4")
self.formLayout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.label_4)
self.WriterLine = QtWidgets.QLineEdit(self.formLayoutWidget)
self.WriterLine.setObjectName("WriterLine")
self.formLayout.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.WriterLine)
self.label_5 = QtWidgets.QLabel(self.formLayoutWidget)
self.label_5.setObjectName("label_5")
self.formLayout.setWidget(5, QtWidgets.QFormLayout.LabelRole, self.label_5)
self.PencillerLine = QtWidgets.QLineEdit(self.formLayoutWidget)
self.PencillerLine.setObjectName("PencillerLine")
self.formLayout.setWidget(5, QtWidgets.QFormLayout.FieldRole, self.PencillerLine)
self.label_6 = QtWidgets.QLabel(self.formLayoutWidget)
self.label_6.setObjectName("label_6")
self.formLayout.setWidget(6, QtWidgets.QFormLayout.LabelRole, self.label_6)
self.InkerLine = QtWidgets.QLineEdit(self.formLayoutWidget)
self.InkerLine.setObjectName("InkerLine")
self.formLayout.setWidget(6, QtWidgets.QFormLayout.FieldRole, self.InkerLine)
self.label_7 = QtWidgets.QLabel(self.formLayoutWidget)
self.label_7.setObjectName("label_7")
self.formLayout.setWidget(7, QtWidgets.QFormLayout.LabelRole, self.label_7)
self.ColoristLine = QtWidgets.QLineEdit(self.formLayoutWidget)
self.ColoristLine.setObjectName("ColoristLine")
self.formLayout.setWidget(7, QtWidgets.QFormLayout.FieldRole, self.ColoristLine)
self.label_8 = QtWidgets.QLabel(self.formLayoutWidget)
self.label_8.setTextFormat(QtCore.Qt.RichText)
self.label_8.setOpenExternalLinks(True)
self.label_8.setObjectName("label_8")
self.formLayout.setWidget(8, QtWidgets.QFormLayout.LabelRole, self.label_8)
self.MUidLine = QtWidgets.QLineEdit(self.formLayoutWidget)
self.MUidLine.setObjectName("MUidLine")
self.formLayout.setWidget(8, QtWidgets.QFormLayout.FieldRole, self.MUidLine)
self.retranslateUi(MetaEditorDialog)
QtCore.QMetaObject.connectSlotsByName(MetaEditorDialog)
def retranslateUi(self, MetaEditorDialog):
_translate = QtCore.QCoreApplication.translate
MetaEditorDialog.setWindowTitle(_translate("MetaEditorDialog", "Metadata editor"))
self.OKButton.setText(_translate("MetaEditorDialog", "Save"))
self.CancelButton.setText(_translate("MetaEditorDialog", "Cancel"))
self.label.setText(_translate("MetaEditorDialog", "Series:"))
self.label_2.setText(_translate("MetaEditorDialog", "Volume:"))
self.label_3.setText(_translate("MetaEditorDialog", "Number:"))
self.label_4.setText(_translate("MetaEditorDialog", "Writer:"))
self.label_5.setText(_translate("MetaEditorDialog", "Penciller:"))
self.label_6.setText(_translate("MetaEditorDialog", "Inker:"))
self.label_7.setText(_translate("MetaEditorDialog", "Colorist:"))
self.label_8.setText(_translate("MetaEditorDialog", "<html><head/><body><p><a href=\"https://github.com/ciromattia/kcc/wiki/Manga-Cover-Database-support\"><span style=\" text-decoration: underline; color:#0000ff;\">MUid:</span></a></p></body></html>"))
from . import KCC_rc

View File

@@ -0,0 +1,148 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'gui/MetaEditor.ui'
#
# Created: Sun Feb 8 03:24:23 2015
# by: PyQt5 UI code generator 5.2.1
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MetaEditorDialog(object):
def setupUi(self, MetaEditorDialog):
MetaEditorDialog.setObjectName("MetaEditorDialog")
MetaEditorDialog.resize(400, 320)
MetaEditorDialog.setMinimumSize(QtCore.QSize(400, 320))
MetaEditorDialog.setMaximumSize(QtCore.QSize(400, 320))
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/Icon/icons/comic2ebook.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
MetaEditorDialog.setWindowIcon(icon)
self.horizontalLayoutWidget = QtWidgets.QWidget(MetaEditorDialog)
self.horizontalLayoutWidget.setGeometry(QtCore.QRect(10, 280, 381, 31))
self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.StatusLabel = QtWidgets.QLabel(self.horizontalLayoutWidget)
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)
font = QtGui.QFont()
font.setPointSize(10)
font.setBold(True)
font.setWeight(75)
self.StatusLabel.setFont(font)
self.StatusLabel.setStyleSheet("color: rgb(255, 0, 0);")
self.StatusLabel.setObjectName("StatusLabel")
self.horizontalLayout.addWidget(self.StatusLabel)
self.OKButton = QtWidgets.QPushButton(self.horizontalLayoutWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.OKButton.sizePolicy().hasHeightForWidth())
self.OKButton.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.OKButton.setFont(font)
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.horizontalLayoutWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.CancelButton.sizePolicy().hasHeightForWidth())
self.CancelButton.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.CancelButton.setFont(font)
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.EditorFrame = QtWidgets.QFrame(MetaEditorDialog)
self.EditorFrame.setGeometry(QtCore.QRect(10, 10, 381, 271))
self.EditorFrame.setObjectName("EditorFrame")
self.formLayoutWidget = QtWidgets.QWidget(self.EditorFrame)
self.formLayoutWidget.setGeometry(QtCore.QRect(0, 0, 381, 266))
self.formLayoutWidget.setObjectName("formLayoutWidget")
self.formLayout = QtWidgets.QFormLayout(self.formLayoutWidget)
self.formLayout.setContentsMargins(0, 0, 0, 0)
self.formLayout.setObjectName("formLayout")
self.label = QtWidgets.QLabel(self.formLayoutWidget)
self.label.setObjectName("label")
self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label)
self.SeriesLine = QtWidgets.QLineEdit(self.formLayoutWidget)
self.SeriesLine.setObjectName("SeriesLine")
self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.SeriesLine)
self.label_2 = QtWidgets.QLabel(self.formLayoutWidget)
self.label_2.setObjectName("label_2")
self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.label_2)
self.VolumeLine = QtWidgets.QLineEdit(self.formLayoutWidget)
self.VolumeLine.setObjectName("VolumeLine")
self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.VolumeLine)
self.label_3 = QtWidgets.QLabel(self.formLayoutWidget)
self.label_3.setObjectName("label_3")
self.formLayout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.label_3)
self.NumberLine = QtWidgets.QLineEdit(self.formLayoutWidget)
self.NumberLine.setObjectName("NumberLine")
self.formLayout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.NumberLine)
self.label_4 = QtWidgets.QLabel(self.formLayoutWidget)
self.label_4.setObjectName("label_4")
self.formLayout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.label_4)
self.WriterLine = QtWidgets.QLineEdit(self.formLayoutWidget)
self.WriterLine.setObjectName("WriterLine")
self.formLayout.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.WriterLine)
self.label_5 = QtWidgets.QLabel(self.formLayoutWidget)
self.label_5.setObjectName("label_5")
self.formLayout.setWidget(5, QtWidgets.QFormLayout.LabelRole, self.label_5)
self.PencillerLine = QtWidgets.QLineEdit(self.formLayoutWidget)
self.PencillerLine.setObjectName("PencillerLine")
self.formLayout.setWidget(5, QtWidgets.QFormLayout.FieldRole, self.PencillerLine)
self.label_6 = QtWidgets.QLabel(self.formLayoutWidget)
self.label_6.setObjectName("label_6")
self.formLayout.setWidget(6, QtWidgets.QFormLayout.LabelRole, self.label_6)
self.InkerLine = QtWidgets.QLineEdit(self.formLayoutWidget)
self.InkerLine.setObjectName("InkerLine")
self.formLayout.setWidget(6, QtWidgets.QFormLayout.FieldRole, self.InkerLine)
self.label_7 = QtWidgets.QLabel(self.formLayoutWidget)
self.label_7.setObjectName("label_7")
self.formLayout.setWidget(7, QtWidgets.QFormLayout.LabelRole, self.label_7)
self.ColoristLine = QtWidgets.QLineEdit(self.formLayoutWidget)
self.ColoristLine.setObjectName("ColoristLine")
self.formLayout.setWidget(7, QtWidgets.QFormLayout.FieldRole, self.ColoristLine)
self.label_8 = QtWidgets.QLabel(self.formLayoutWidget)
self.label_8.setTextFormat(QtCore.Qt.RichText)
self.label_8.setOpenExternalLinks(True)
self.label_8.setObjectName("label_8")
self.formLayout.setWidget(8, QtWidgets.QFormLayout.LabelRole, self.label_8)
self.MUidLine = QtWidgets.QLineEdit(self.formLayoutWidget)
self.MUidLine.setObjectName("MUidLine")
self.formLayout.setWidget(8, QtWidgets.QFormLayout.FieldRole, self.MUidLine)
self.retranslateUi(MetaEditorDialog)
QtCore.QMetaObject.connectSlotsByName(MetaEditorDialog)
def retranslateUi(self, MetaEditorDialog):
_translate = QtCore.QCoreApplication.translate
MetaEditorDialog.setWindowTitle(_translate("MetaEditorDialog", "Metadata editor"))
self.OKButton.setText(_translate("MetaEditorDialog", "Save"))
self.CancelButton.setText(_translate("MetaEditorDialog", "Cancel"))
self.label.setText(_translate("MetaEditorDialog", "Series:"))
self.label_2.setText(_translate("MetaEditorDialog", "Volume:"))
self.label_3.setText(_translate("MetaEditorDialog", "Number:"))
self.label_4.setText(_translate("MetaEditorDialog", "Writer:"))
self.label_5.setText(_translate("MetaEditorDialog", "Penciller:"))
self.label_6.setText(_translate("MetaEditorDialog", "Inker:"))
self.label_7.setText(_translate("MetaEditorDialog", "Colorist:"))
self.label_8.setText(_translate("MetaEditorDialog", "<html><head/><body><p><a href=\"https://github.com/ciromattia/kcc/wiki/Manga-Cover-Database-support\"><span style=\" text-decoration: underline; color:#0000ff;\">MUid:</span></a></p></body></html>"))
from . import KCC_rc

View File

@@ -0,0 +1,148 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file '/Users/pawelj/Documents/KCC/gui/MetaEditor.ui'
#
# Created: Sun Feb 8 12:47:09 2015
# by: PyQt5 UI code generator 5.4
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MetaEditorDialog(object):
def setupUi(self, MetaEditorDialog):
MetaEditorDialog.setObjectName("MetaEditorDialog")
MetaEditorDialog.resize(400, 295)
MetaEditorDialog.setMinimumSize(QtCore.QSize(400, 295))
MetaEditorDialog.setMaximumSize(QtCore.QSize(400, 295))
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/Icon/icons/comic2ebook.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
MetaEditorDialog.setWindowIcon(icon)
self.horizontalLayoutWidget = QtWidgets.QWidget(MetaEditorDialog)
self.horizontalLayoutWidget.setGeometry(QtCore.QRect(10, 260, 381, 32))
self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.StatusLabel = QtWidgets.QLabel(self.horizontalLayoutWidget)
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)
font = QtGui.QFont()
font.setPointSize(10)
font.setBold(True)
font.setWeight(75)
self.StatusLabel.setFont(font)
self.StatusLabel.setStyleSheet("color: rgb(255, 0, 0);")
self.StatusLabel.setObjectName("StatusLabel")
self.horizontalLayout.addWidget(self.StatusLabel)
self.OKButton = QtWidgets.QPushButton(self.horizontalLayoutWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.OKButton.sizePolicy().hasHeightForWidth())
self.OKButton.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.OKButton.setFont(font)
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.horizontalLayoutWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.CancelButton.sizePolicy().hasHeightForWidth())
self.CancelButton.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.CancelButton.setFont(font)
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.EditorFrame = QtWidgets.QFrame(MetaEditorDialog)
self.EditorFrame.setGeometry(QtCore.QRect(10, 10, 381, 251))
self.EditorFrame.setObjectName("EditorFrame")
self.formLayoutWidget = QtWidgets.QWidget(self.EditorFrame)
self.formLayoutWidget.setGeometry(QtCore.QRect(0, 0, 381, 250))
self.formLayoutWidget.setObjectName("formLayoutWidget")
self.formLayout = QtWidgets.QFormLayout(self.formLayoutWidget)
self.formLayout.setContentsMargins(0, 0, 0, 0)
self.formLayout.setObjectName("formLayout")
self.label = QtWidgets.QLabel(self.formLayoutWidget)
self.label.setObjectName("label")
self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label)
self.SeriesLine = QtWidgets.QLineEdit(self.formLayoutWidget)
self.SeriesLine.setObjectName("SeriesLine")
self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.SeriesLine)
self.label_2 = QtWidgets.QLabel(self.formLayoutWidget)
self.label_2.setObjectName("label_2")
self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.label_2)
self.VolumeLine = QtWidgets.QLineEdit(self.formLayoutWidget)
self.VolumeLine.setObjectName("VolumeLine")
self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.VolumeLine)
self.label_3 = QtWidgets.QLabel(self.formLayoutWidget)
self.label_3.setObjectName("label_3")
self.formLayout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.label_3)
self.NumberLine = QtWidgets.QLineEdit(self.formLayoutWidget)
self.NumberLine.setObjectName("NumberLine")
self.formLayout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.NumberLine)
self.label_4 = QtWidgets.QLabel(self.formLayoutWidget)
self.label_4.setObjectName("label_4")
self.formLayout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.label_4)
self.WriterLine = QtWidgets.QLineEdit(self.formLayoutWidget)
self.WriterLine.setObjectName("WriterLine")
self.formLayout.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.WriterLine)
self.label_5 = QtWidgets.QLabel(self.formLayoutWidget)
self.label_5.setObjectName("label_5")
self.formLayout.setWidget(5, QtWidgets.QFormLayout.LabelRole, self.label_5)
self.PencillerLine = QtWidgets.QLineEdit(self.formLayoutWidget)
self.PencillerLine.setObjectName("PencillerLine")
self.formLayout.setWidget(5, QtWidgets.QFormLayout.FieldRole, self.PencillerLine)
self.label_6 = QtWidgets.QLabel(self.formLayoutWidget)
self.label_6.setObjectName("label_6")
self.formLayout.setWidget(6, QtWidgets.QFormLayout.LabelRole, self.label_6)
self.InkerLine = QtWidgets.QLineEdit(self.formLayoutWidget)
self.InkerLine.setObjectName("InkerLine")
self.formLayout.setWidget(6, QtWidgets.QFormLayout.FieldRole, self.InkerLine)
self.label_7 = QtWidgets.QLabel(self.formLayoutWidget)
self.label_7.setObjectName("label_7")
self.formLayout.setWidget(7, QtWidgets.QFormLayout.LabelRole, self.label_7)
self.ColoristLine = QtWidgets.QLineEdit(self.formLayoutWidget)
self.ColoristLine.setObjectName("ColoristLine")
self.formLayout.setWidget(7, QtWidgets.QFormLayout.FieldRole, self.ColoristLine)
self.label_8 = QtWidgets.QLabel(self.formLayoutWidget)
self.label_8.setTextFormat(QtCore.Qt.RichText)
self.label_8.setOpenExternalLinks(True)
self.label_8.setObjectName("label_8")
self.formLayout.setWidget(8, QtWidgets.QFormLayout.LabelRole, self.label_8)
self.MUidLine = QtWidgets.QLineEdit(self.formLayoutWidget)
self.MUidLine.setObjectName("MUidLine")
self.formLayout.setWidget(8, QtWidgets.QFormLayout.FieldRole, self.MUidLine)
self.retranslateUi(MetaEditorDialog)
QtCore.QMetaObject.connectSlotsByName(MetaEditorDialog)
def retranslateUi(self, MetaEditorDialog):
_translate = QtCore.QCoreApplication.translate
MetaEditorDialog.setWindowTitle(_translate("MetaEditorDialog", "Metadata editor"))
self.OKButton.setText(_translate("MetaEditorDialog", "Save"))
self.CancelButton.setText(_translate("MetaEditorDialog", "Cancel"))
self.label.setText(_translate("MetaEditorDialog", "Series:"))
self.label_2.setText(_translate("MetaEditorDialog", "Volume:"))
self.label_3.setText(_translate("MetaEditorDialog", "Number:"))
self.label_4.setText(_translate("MetaEditorDialog", "Writer:"))
self.label_5.setText(_translate("MetaEditorDialog", "Penciller:"))
self.label_6.setText(_translate("MetaEditorDialog", "Inker:"))
self.label_7.setText(_translate("MetaEditorDialog", "Colorist:"))
self.label_8.setText(_translate("MetaEditorDialog", "<html><head/><body><p><a href=\"https://github.com/ciromattia/kcc/wiki/Manga-Cover-Database-support\"><span style=\" text-decoration: underline; color:#0000ff;\">MUid:</span></a></p></body></html>"))
from . import KCC_rc

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

225
kcc/KCC_rc_web.py Normal file
View File

@@ -0,0 +1,225 @@
# -*- 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'

View File

@@ -2,91 +2,79 @@
# Form implementation generated from reading ui file 'KCC.ui' # Form implementation generated from reading ui file 'KCC.ui'
# #
# Created: Fri Jun 21 18:23:19 2013 # Created: Sun Feb 8 09:50:43 2015
# by: PyQt4 UI code generator 4.10.1 # by: PyQt5 UI code generator 5.4
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui from PyQt5 import QtCore, QtGui, QtWidgets
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): class Ui_KCC(object):
def setupUi(self, KCC): def setupUi(self, KCC):
KCC.setObjectName(_fromUtf8("KCC")) KCC.setObjectName("KCC")
KCC.resize(420, 380) KCC.resize(420, 397)
KCC.setMinimumSize(QtCore.QSize(420, 380)) KCC.setMinimumSize(QtCore.QSize(420, 397))
KCC.setMaximumSize(QtCore.QSize(420, 380)) KCC.setMaximumSize(QtCore.QSize(420, 397))
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(9) font.setPointSize(9)
KCC.setFont(font) KCC.setFont(font)
KCC.setFocusPolicy(QtCore.Qt.NoFocus)
icon = QtGui.QIcon() icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/Icon/icons/comic2ebook.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) icon.addPixmap(QtGui.QPixmap(":/Icon/icons/comic2ebook.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
KCC.setWindowIcon(icon) KCC.setWindowIcon(icon)
KCC.setLocale(QtCore.QLocale(QtCore.QLocale.C, QtCore.QLocale.AnyCountry)) KCC.setLocale(QtCore.QLocale(QtCore.QLocale.C, QtCore.QLocale.AnyCountry))
self.Form = QtGui.QWidget(KCC) self.Form = QtWidgets.QWidget(KCC)
self.Form.setObjectName(_fromUtf8("Form")) self.Form.setObjectName("Form")
self.OptionsAdvanced = QtGui.QFrame(self.Form) self.OptionsAdvanced = QtWidgets.QFrame(self.Form)
self.OptionsAdvanced.setEnabled(True) self.OptionsAdvanced.setEnabled(True)
self.OptionsAdvanced.setGeometry(QtCore.QRect(10, 254, 421, 61)) self.OptionsAdvanced.setGeometry(QtCore.QRect(10, 254, 421, 61))
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(9) font.setPointSize(9)
self.OptionsAdvanced.setFont(font) self.OptionsAdvanced.setFont(font)
self.OptionsAdvanced.setObjectName(_fromUtf8("OptionsAdvanced")) self.OptionsAdvanced.setObjectName("OptionsAdvanced")
self.gridLayout = QtGui.QGridLayout(self.OptionsAdvanced) self.gridLayout = QtWidgets.QGridLayout(self.OptionsAdvanced)
self.gridLayout.setObjectName(_fromUtf8("gridLayout")) self.gridLayout.setContentsMargins(9, -1, -1, -1)
self.ProcessingBox = QtGui.QCheckBox(self.OptionsAdvanced) self.gridLayout.setObjectName("gridLayout")
self.ProcessingBox = QtWidgets.QCheckBox(self.OptionsAdvanced)
self.ProcessingBox.setFocusPolicy(QtCore.Qt.NoFocus) self.ProcessingBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.ProcessingBox.setObjectName(_fromUtf8("ProcessingBox")) self.ProcessingBox.setObjectName("ProcessingBox")
self.gridLayout.addWidget(self.ProcessingBox, 1, 0, 1, 1) self.gridLayout.addWidget(self.ProcessingBox, 1, 0, 1, 1)
self.UpscaleBox = QtGui.QCheckBox(self.OptionsAdvanced) self.UpscaleBox = QtWidgets.QCheckBox(self.OptionsAdvanced)
self.UpscaleBox.setFocusPolicy(QtCore.Qt.NoFocus) self.UpscaleBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.UpscaleBox.setObjectName(_fromUtf8("UpscaleBox")) self.UpscaleBox.setTristate(True)
self.UpscaleBox.setObjectName("UpscaleBox")
self.gridLayout.addWidget(self.UpscaleBox, 1, 1, 1, 1) self.gridLayout.addWidget(self.UpscaleBox, 1, 1, 1, 1)
self.StretchBox = QtGui.QCheckBox(self.OptionsAdvanced) self.WebtoonBox = QtWidgets.QCheckBox(self.OptionsAdvanced)
self.StretchBox.setFocusPolicy(QtCore.Qt.NoFocus) self.WebtoonBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.StretchBox.setObjectName(_fromUtf8("StretchBox")) self.WebtoonBox.setObjectName("WebtoonBox")
self.gridLayout.addWidget(self.StretchBox, 3, 1, 1, 1) self.gridLayout.addWidget(self.WebtoonBox, 3, 1, 1, 1)
self.NoDitheringBox = QtGui.QCheckBox(self.OptionsAdvanced) self.NoDitheringBox = QtWidgets.QCheckBox(self.OptionsAdvanced)
self.NoDitheringBox.setFocusPolicy(QtCore.Qt.NoFocus) self.NoDitheringBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.NoDitheringBox.setObjectName(_fromUtf8("NoDitheringBox")) self.NoDitheringBox.setObjectName("NoDitheringBox")
self.gridLayout.addWidget(self.NoDitheringBox, 3, 2, 1, 1) self.gridLayout.addWidget(self.NoDitheringBox, 3, 2, 1, 1)
self.BorderBox = QtGui.QCheckBox(self.OptionsAdvanced) self.BorderBox = QtWidgets.QCheckBox(self.OptionsAdvanced)
self.BorderBox.setFocusPolicy(QtCore.Qt.NoFocus) self.BorderBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.BorderBox.setObjectName(_fromUtf8("BorderBox")) self.BorderBox.setTristate(True)
self.BorderBox.setObjectName("BorderBox")
self.gridLayout.addWidget(self.BorderBox, 3, 0, 1, 1) self.gridLayout.addWidget(self.BorderBox, 3, 0, 1, 1)
self.NoRotateBox = QtGui.QCheckBox(self.OptionsAdvanced) self.NoRotateBox = QtWidgets.QCheckBox(self.OptionsAdvanced)
self.NoRotateBox.setFocusPolicy(QtCore.Qt.NoFocus) self.NoRotateBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.NoRotateBox.setObjectName(_fromUtf8("NoRotateBox")) self.NoRotateBox.setObjectName("NoRotateBox")
self.gridLayout.addWidget(self.NoRotateBox, 1, 2, 1, 1) self.gridLayout.addWidget(self.NoRotateBox, 1, 2, 1, 1)
self.DeviceBox = QtGui.QComboBox(self.Form) self.DeviceBox = QtWidgets.QComboBox(self.Form)
self.DeviceBox.setGeometry(QtCore.QRect(10, 200, 141, 31)) self.DeviceBox.setGeometry(QtCore.QRect(10, 200, 141, 31))
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(8) font.setPointSize(8)
self.DeviceBox.setFont(font) self.DeviceBox.setFont(font)
self.DeviceBox.setFocusPolicy(QtCore.Qt.NoFocus) self.DeviceBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.DeviceBox.setObjectName(_fromUtf8("DeviceBox")) self.DeviceBox.setObjectName("DeviceBox")
self.FormatBox = QtGui.QComboBox(self.Form) self.FormatBox = QtWidgets.QComboBox(self.Form)
self.FormatBox.setGeometry(QtCore.QRect(260, 200, 151, 31)) self.FormatBox.setGeometry(QtCore.QRect(260, 200, 151, 31))
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(8) font.setPointSize(8)
self.FormatBox.setFont(font) self.FormatBox.setFont(font)
self.FormatBox.setFocusPolicy(QtCore.Qt.NoFocus) self.FormatBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.FormatBox.setObjectName(_fromUtf8("FormatBox")) self.FormatBox.setObjectName("FormatBox")
self.ConvertButton = QtGui.QPushButton(self.Form) self.ConvertButton = QtWidgets.QPushButton(self.Form)
self.ConvertButton.setGeometry(QtCore.QRect(160, 200, 91, 32)) self.ConvertButton.setGeometry(QtCore.QRect(160, 200, 91, 32))
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(9) font.setPointSize(9)
@@ -95,96 +83,97 @@ class Ui_KCC(object):
self.ConvertButton.setFont(font) self.ConvertButton.setFont(font)
self.ConvertButton.setFocusPolicy(QtCore.Qt.NoFocus) self.ConvertButton.setFocusPolicy(QtCore.Qt.NoFocus)
icon1 = QtGui.QIcon() icon1 = QtGui.QIcon()
icon1.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/convert.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) icon1.addPixmap(QtGui.QPixmap(":/Other/icons/convert.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.ConvertButton.setIcon(icon1) self.ConvertButton.setIcon(icon1)
self.ConvertButton.setObjectName(_fromUtf8("ConvertButton")) self.ConvertButton.setObjectName("ConvertButton")
self.DirectoryButton = QtGui.QPushButton(self.Form) self.DirectoryButton = QtWidgets.QPushButton(self.Form)
self.DirectoryButton.setGeometry(QtCore.QRect(10, 160, 141, 32)) self.DirectoryButton.setGeometry(QtCore.QRect(10, 160, 141, 32))
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(8) font.setPointSize(8)
self.DirectoryButton.setFont(font) self.DirectoryButton.setFont(font)
self.DirectoryButton.setFocusPolicy(QtCore.Qt.NoFocus) self.DirectoryButton.setFocusPolicy(QtCore.Qt.NoFocus)
icon2 = QtGui.QIcon() icon2 = QtGui.QIcon()
icon2.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/folder_new.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) icon2.addPixmap(QtGui.QPixmap(":/Other/icons/folder_new.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.DirectoryButton.setIcon(icon2) self.DirectoryButton.setIcon(icon2)
self.DirectoryButton.setObjectName(_fromUtf8("DirectoryButton")) self.DirectoryButton.setObjectName("DirectoryButton")
self.FileButton = QtGui.QPushButton(self.Form) self.FileButton = QtWidgets.QPushButton(self.Form)
self.FileButton.setGeometry(QtCore.QRect(260, 160, 151, 32)) self.FileButton.setGeometry(QtCore.QRect(260, 160, 151, 32))
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(8) font.setPointSize(8)
self.FileButton.setFont(font) self.FileButton.setFont(font)
self.FileButton.setFocusPolicy(QtCore.Qt.NoFocus) self.FileButton.setFocusPolicy(QtCore.Qt.NoFocus)
icon3 = QtGui.QIcon() icon3 = QtGui.QIcon()
icon3.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/document_new.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) icon3.addPixmap(QtGui.QPixmap(":/Other/icons/document_new.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.FileButton.setIcon(icon3) self.FileButton.setIcon(icon3)
self.FileButton.setObjectName(_fromUtf8("FileButton")) self.FileButton.setObjectName("FileButton")
self.ClearButton = QtGui.QPushButton(self.Form) self.ClearButton = QtWidgets.QPushButton(self.Form)
self.ClearButton.setGeometry(QtCore.QRect(160, 160, 91, 32)) self.ClearButton.setGeometry(QtCore.QRect(160, 160, 91, 32))
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(8) font.setPointSize(8)
self.ClearButton.setFont(font) self.ClearButton.setFont(font)
self.ClearButton.setFocusPolicy(QtCore.Qt.NoFocus) self.ClearButton.setFocusPolicy(QtCore.Qt.NoFocus)
icon4 = QtGui.QIcon() icon4 = QtGui.QIcon()
icon4.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/clear.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) icon4.addPixmap(QtGui.QPixmap(":/Other/icons/clear.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.ClearButton.setIcon(icon4) self.ClearButton.setIcon(icon4)
self.ClearButton.setObjectName(_fromUtf8("ClearButton")) self.ClearButton.setObjectName("ClearButton")
self.OptionsBasic = QtGui.QFrame(self.Form) self.OptionsBasic = QtWidgets.QFrame(self.Form)
self.OptionsBasic.setGeometry(QtCore.QRect(10, 230, 421, 41)) self.OptionsBasic.setGeometry(QtCore.QRect(10, 230, 421, 41))
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(9) font.setPointSize(9)
self.OptionsBasic.setFont(font) self.OptionsBasic.setFont(font)
self.OptionsBasic.setObjectName(_fromUtf8("OptionsBasic")) self.OptionsBasic.setObjectName("OptionsBasic")
self.MangaBox = QtGui.QCheckBox(self.OptionsBasic) self.MangaBox = QtWidgets.QCheckBox(self.OptionsBasic)
self.MangaBox.setGeometry(QtCore.QRect(9, 10, 130, 18)) self.MangaBox.setGeometry(QtCore.QRect(9, 10, 130, 18))
self.MangaBox.setFocusPolicy(QtCore.Qt.NoFocus) self.MangaBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.MangaBox.setObjectName(_fromUtf8("MangaBox")) self.MangaBox.setObjectName("MangaBox")
self.QualityBox = QtGui.QCheckBox(self.OptionsBasic) self.QualityBox = QtWidgets.QCheckBox(self.OptionsBasic)
self.QualityBox.setGeometry(QtCore.QRect(282, 10, 130, 18)) self.QualityBox.setGeometry(QtCore.QRect(282, 10, 130, 18))
self.QualityBox.setFocusPolicy(QtCore.Qt.NoFocus) self.QualityBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.QualityBox.setTristate(True) self.QualityBox.setTristate(True)
self.QualityBox.setObjectName(_fromUtf8("QualityBox")) self.QualityBox.setObjectName("QualityBox")
self.RotateBox = QtGui.QCheckBox(self.OptionsBasic) self.RotateBox = QtWidgets.QCheckBox(self.OptionsBasic)
self.RotateBox.setGeometry(QtCore.QRect(145, 10, 130, 18)) self.RotateBox.setGeometry(QtCore.QRect(145, 10, 130, 18))
self.RotateBox.setFocusPolicy(QtCore.Qt.NoFocus) self.RotateBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.RotateBox.setObjectName(_fromUtf8("RotateBox")) self.RotateBox.setObjectName("RotateBox")
self.JobList = QtGui.QListWidget(self.Form) self.JobList = QtWidgets.QListWidget(self.Form)
self.JobList.setGeometry(QtCore.QRect(10, 50, 401, 101)) self.JobList.setGeometry(QtCore.QRect(10, 50, 401, 101))
self.JobList.setFocusPolicy(QtCore.Qt.NoFocus) self.JobList.setFocusPolicy(QtCore.Qt.NoFocus)
self.JobList.setStyleSheet("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.setProperty("showDropIndicator", False)
self.JobList.setSelectionMode(QtGui.QAbstractItemView.NoSelection) self.JobList.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
self.JobList.setObjectName(_fromUtf8("JobList")) self.JobList.setObjectName("JobList")
self.BasicModeButton = QtGui.QPushButton(self.Form) self.BasicModeButton = QtWidgets.QPushButton(self.Form)
self.BasicModeButton.setGeometry(QtCore.QRect(10, 10, 195, 32)) self.BasicModeButton.setGeometry(QtCore.QRect(10, 10, 141, 32))
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(9) font.setPointSize(9)
self.BasicModeButton.setFont(font) self.BasicModeButton.setFont(font)
self.BasicModeButton.setFocusPolicy(QtCore.Qt.NoFocus) self.BasicModeButton.setFocusPolicy(QtCore.Qt.NoFocus)
self.BasicModeButton.setObjectName(_fromUtf8("BasicModeButton")) self.BasicModeButton.setObjectName("BasicModeButton")
self.AdvModeButton = QtGui.QPushButton(self.Form) self.AdvModeButton = QtWidgets.QPushButton(self.Form)
self.AdvModeButton.setGeometry(QtCore.QRect(217, 10, 195, 32)) self.AdvModeButton.setGeometry(QtCore.QRect(261, 10, 151, 32))
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(9) font.setPointSize(9)
self.AdvModeButton.setFont(font) self.AdvModeButton.setFont(font)
self.AdvModeButton.setFocusPolicy(QtCore.Qt.NoFocus) self.AdvModeButton.setFocusPolicy(QtCore.Qt.NoFocus)
self.AdvModeButton.setObjectName(_fromUtf8("AdvModeButton")) self.AdvModeButton.setObjectName("AdvModeButton")
self.OptionsAdvancedGamma = QtGui.QFrame(self.Form) self.OptionsAdvancedGamma = QtWidgets.QFrame(self.Form)
self.OptionsAdvancedGamma.setEnabled(True) self.OptionsAdvancedGamma.setEnabled(True)
self.OptionsAdvancedGamma.setGeometry(QtCore.QRect(10, 305, 401, 41)) self.OptionsAdvancedGamma.setGeometry(QtCore.QRect(10, 305, 401, 41))
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(9) font.setPointSize(9)
self.OptionsAdvancedGamma.setFont(font) self.OptionsAdvancedGamma.setFont(font)
self.OptionsAdvancedGamma.setObjectName(_fromUtf8("OptionsAdvancedGamma")) self.OptionsAdvancedGamma.setObjectName("OptionsAdvancedGamma")
self.GammaLabel = QtGui.QLabel(self.OptionsAdvancedGamma) self.GammaLabel = QtWidgets.QLabel(self.OptionsAdvancedGamma)
self.GammaLabel.setGeometry(QtCore.QRect(15, 0, 100, 40)) self.GammaLabel.setGeometry(QtCore.QRect(15, 0, 100, 40))
self.GammaLabel.setObjectName(_fromUtf8("GammaLabel")) self.GammaLabel.setObjectName("GammaLabel")
self.GammaSlider = QtGui.QSlider(self.OptionsAdvancedGamma) self.GammaSlider = QtWidgets.QSlider(self.OptionsAdvancedGamma)
self.GammaSlider.setGeometry(QtCore.QRect(110, 10, 270, 22)) self.GammaSlider.setGeometry(QtCore.QRect(110, 10, 270, 22))
self.GammaSlider.setFocusPolicy(QtCore.Qt.ClickFocus) self.GammaSlider.setFocusPolicy(QtCore.Qt.ClickFocus)
self.GammaSlider.setMaximum(500) self.GammaSlider.setMaximum(500)
self.GammaSlider.setSingleStep(5) self.GammaSlider.setSingleStep(5)
self.GammaSlider.setOrientation(QtCore.Qt.Horizontal) self.GammaSlider.setOrientation(QtCore.Qt.Horizontal)
self.GammaSlider.setObjectName(_fromUtf8("GammaSlider")) self.GammaSlider.setObjectName("GammaSlider")
self.ProgressBar = QtGui.QProgressBar(self.Form) self.ProgressBar = QtWidgets.QProgressBar(self.Form)
self.ProgressBar.setGeometry(QtCore.QRect(10, 10, 401, 31)) self.ProgressBar.setGeometry(QtCore.QRect(10, 10, 401, 31))
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(10) font.setPointSize(10)
@@ -193,28 +182,28 @@ class Ui_KCC(object):
self.ProgressBar.setFont(font) self.ProgressBar.setFont(font)
self.ProgressBar.setProperty("value", 0) self.ProgressBar.setProperty("value", 0)
self.ProgressBar.setAlignment(QtCore.Qt.AlignJustify|QtCore.Qt.AlignVCenter) self.ProgressBar.setAlignment(QtCore.Qt.AlignJustify|QtCore.Qt.AlignVCenter)
self.ProgressBar.setFormat(_fromUtf8("")) self.ProgressBar.setFormat("")
self.ProgressBar.setObjectName(_fromUtf8("ProgressBar")) self.ProgressBar.setObjectName("ProgressBar")
self.OptionsExpert = QtGui.QFrame(self.Form) self.OptionsExpert = QtWidgets.QFrame(self.Form)
self.OptionsExpert.setGeometry(QtCore.QRect(10, 337, 421, 41)) self.OptionsExpert.setGeometry(QtCore.QRect(10, 337, 421, 41))
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(9) font.setPointSize(9)
self.OptionsExpert.setFont(font) self.OptionsExpert.setFont(font)
self.OptionsExpert.setObjectName(_fromUtf8("OptionsExpert")) self.OptionsExpert.setObjectName("OptionsExpert")
self.ColorBox = QtGui.QCheckBox(self.OptionsExpert) self.ColorBox = QtWidgets.QCheckBox(self.OptionsExpert)
self.ColorBox.setGeometry(QtCore.QRect(9, 11, 130, 18)) self.ColorBox.setGeometry(QtCore.QRect(9, 11, 130, 18))
self.ColorBox.setFocusPolicy(QtCore.Qt.NoFocus) self.ColorBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.ColorBox.setObjectName(_fromUtf8("ColorBox")) self.ColorBox.setObjectName("ColorBox")
self.OptionsExpertInternal = QtGui.QFrame(self.OptionsExpert) self.OptionsExpertInternal = QtWidgets.QFrame(self.OptionsExpert)
self.OptionsExpertInternal.setGeometry(QtCore.QRect(100, 0, 295, 40)) self.OptionsExpertInternal.setGeometry(QtCore.QRect(100, 0, 295, 40))
self.OptionsExpertInternal.setObjectName(_fromUtf8("OptionsExpertInternal")) self.OptionsExpertInternal.setObjectName("OptionsExpertInternal")
self.gridLayout_2 = QtGui.QGridLayout(self.OptionsExpertInternal) self.gridLayout_2 = QtWidgets.QGridLayout(self.OptionsExpertInternal)
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2")) self.gridLayout_2.setObjectName("gridLayout_2")
self.wLabel = QtGui.QLabel(self.OptionsExpertInternal) self.wLabel = QtWidgets.QLabel(self.OptionsExpertInternal)
self.wLabel.setObjectName(_fromUtf8("wLabel")) self.wLabel.setObjectName("wLabel")
self.gridLayout_2.addWidget(self.wLabel, 0, 0, 1, 1) self.gridLayout_2.addWidget(self.wLabel, 0, 0, 1, 1)
self.customWidth = QtGui.QLineEdit(self.OptionsExpertInternal) self.customWidth = QtWidgets.QLineEdit(self.OptionsExpertInternal)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.customWidth.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.customWidth.sizePolicy().hasHeightForWidth())
@@ -223,13 +212,13 @@ class Ui_KCC(object):
self.customWidth.setFocusPolicy(QtCore.Qt.ClickFocus) self.customWidth.setFocusPolicy(QtCore.Qt.ClickFocus)
self.customWidth.setAcceptDrops(False) self.customWidth.setAcceptDrops(False)
self.customWidth.setMaxLength(4) self.customWidth.setMaxLength(4)
self.customWidth.setObjectName(_fromUtf8("customWidth")) self.customWidth.setObjectName("customWidth")
self.gridLayout_2.addWidget(self.customWidth, 0, 1, 1, 1) self.gridLayout_2.addWidget(self.customWidth, 0, 1, 1, 1)
self.hLabel = QtGui.QLabel(self.OptionsExpertInternal) self.hLabel = QtWidgets.QLabel(self.OptionsExpertInternal)
self.hLabel.setObjectName(_fromUtf8("hLabel")) self.hLabel.setObjectName("hLabel")
self.gridLayout_2.addWidget(self.hLabel, 0, 2, 1, 1) self.gridLayout_2.addWidget(self.hLabel, 0, 2, 1, 1)
self.customHeight = QtGui.QLineEdit(self.OptionsExpertInternal) self.customHeight = QtWidgets.QLineEdit(self.OptionsExpertInternal)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.customHeight.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.customHeight.sizePolicy().hasHeightForWidth())
@@ -238,19 +227,37 @@ class Ui_KCC(object):
self.customHeight.setFocusPolicy(QtCore.Qt.ClickFocus) self.customHeight.setFocusPolicy(QtCore.Qt.ClickFocus)
self.customHeight.setAcceptDrops(False) self.customHeight.setAcceptDrops(False)
self.customHeight.setMaxLength(4) self.customHeight.setMaxLength(4)
self.customHeight.setObjectName(_fromUtf8("customHeight")) self.customHeight.setObjectName("customHeight")
self.gridLayout_2.addWidget(self.customHeight, 0, 3, 1, 1) self.gridLayout_2.addWidget(self.customHeight, 0, 3, 1, 1)
self.EditorButton = QtWidgets.QPushButton(self.Form)
self.EditorButton.setGeometry(QtCore.QRect(160, 10, 91, 32))
font = QtGui.QFont()
font.setPointSize(9)
self.EditorButton.setFont(font)
self.EditorButton.setFocusPolicy(QtCore.Qt.NoFocus)
icon5 = QtGui.QIcon()
icon5.addPixmap(QtGui.QPixmap(":/Other/icons/editor.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.EditorButton.setIcon(icon5)
self.EditorButton.setObjectName("EditorButton")
KCC.setCentralWidget(self.Form) KCC.setCentralWidget(self.Form)
self.ActionBasic = QtGui.QAction(KCC) self.statusBar = QtWidgets.QStatusBar(KCC)
font = QtGui.QFont()
font.setFamily("MS Shell Dlg 2")
font.setPointSize(8)
self.statusBar.setFont(font)
self.statusBar.setSizeGripEnabled(False)
self.statusBar.setObjectName("statusBar")
KCC.setStatusBar(self.statusBar)
self.ActionBasic = QtWidgets.QAction(KCC)
self.ActionBasic.setCheckable(True) self.ActionBasic.setCheckable(True)
self.ActionBasic.setChecked(False) self.ActionBasic.setChecked(False)
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(9) font.setPointSize(9)
self.ActionBasic.setFont(font) self.ActionBasic.setFont(font)
self.ActionBasic.setObjectName(_fromUtf8("ActionBasic")) self.ActionBasic.setObjectName("ActionBasic")
self.ActionAdvanced = QtGui.QAction(KCC) self.ActionAdvanced = QtWidgets.QAction(KCC)
self.ActionAdvanced.setCheckable(True) self.ActionAdvanced.setCheckable(True)
self.ActionAdvanced.setObjectName(_fromUtf8("ActionAdvanced")) self.ActionAdvanced.setObjectName("ActionAdvanced")
self.retranslateUi(KCC) self.retranslateUi(KCC)
QtCore.QMetaObject.connectSlotsByName(KCC) QtCore.QMetaObject.connectSlotsByName(KCC)
@@ -259,53 +266,50 @@ class Ui_KCC(object):
KCC.setTabOrder(self.ConvertButton, self.ClearButton) KCC.setTabOrder(self.ConvertButton, self.ClearButton)
def retranslateUi(self, KCC): def retranslateUi(self, KCC):
KCC.setWindowTitle(_translate("KCC", "Kindle Comic Converter", None)) _translate = QtCore.QCoreApplication.translate
self.ProcessingBox.setToolTip(_translate("KCC", "Disable image optimizations.", None)) KCC.setWindowTitle(_translate("KCC", "Kindle Comic Converter"))
self.ProcessingBox.setText(_translate("KCC", "No optimisation", None)) self.ProcessingBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Disable image optimizations.<br/><span style=\" font-weight:600;\">Input images must be already resized.</span></p></body></html>"))
self.UpscaleBox.setToolTip(_translate("KCC", "<html><head/><body><p>Enable image upscaling.<br/>Aspect ratio will be preserved.</p></body></html>", None)) self.ProcessingBox.setText(_translate("KCC", "No optimisation"))
self.UpscaleBox.setText(_translate("KCC", "Upscale images", 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>"))
self.StretchBox.setToolTip(_translate("KCC", "<html><head/><body><p>Enable image stretching.<br/>Aspect ratio will be not preserved.</p></body></html>", None)) self.UpscaleBox.setText(_translate("KCC", "Stretch/Upscale"))
self.StretchBox.setText(_translate("KCC", "Stretch images", None)) self.WebtoonBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Enable special parsing mode for WebToons.</p></body></html>"))
self.NoDitheringBox.setToolTip(_translate("KCC", "<html><head/><body><p>Create PNG files instead JPEG.<br/><span style=\" font-weight:600;\">Only for non-Kindle devices!</span></p></body></html>", None)) self.WebtoonBox.setText(_translate("KCC", "Webtoon mode"))
self.NoDitheringBox.setText(_translate("KCC", "PNG output", None)) self.NoDitheringBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>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>"))
self.BorderBox.setToolTip(_translate("KCC", "Fill space around images with black color.", None)) self.NoDitheringBox.setText(_translate("KCC", "PNG output"))
self.BorderBox.setText(_translate("KCC", "Black borders", 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>"))
self.NoRotateBox.setToolTip(_translate("KCC", "<html><head/><body><p>Disable splitting and rotation.</p></body></html>", None)) self.BorderBox.setText(_translate("KCC", "W/B margins"))
self.NoRotateBox.setText(_translate("KCC", "No split/rotate", None)) self.NoRotateBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Disable page splitting and rotation.</p></body></html>"))
self.DeviceBox.setToolTip(_translate("KCC", "Target device.", None)) self.NoRotateBox.setText(_translate("KCC", "No split/rotate"))
self.FormatBox.setToolTip(_translate("KCC", "Output format.", None)) self.DeviceBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Target device.</p></body></html>"))
self.ConvertButton.setText(_translate("KCC", "Convert", None)) self.FormatBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Output format.</p></body></html>"))
self.DirectoryButton.setText(_translate("KCC", "Add directory", None)) self.ConvertButton.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Shift+Click to select the output directory.</p></body></html>"))
self.FileButton.setText(_translate("KCC", "Add file", None)) self.ConvertButton.setText(_translate("KCC", "Convert"))
self.ClearButton.setText(_translate("KCC", "Clear list", None)) self.DirectoryButton.setToolTip(_translate("KCC", "<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.MangaBox.setToolTip(_translate("KCC", "Enable right-to-left reading.", None)) self.DirectoryButton.setText(_translate("KCC", "Add directory"))
self.MangaBox.setText(_translate("KCC", "Manga mode", None)) self.FileButton.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Add CBR, CBZ, CB7 or PDF file to queue.</p></body></html>"))
self.QualityBox.setToolTip(_translate("KCC", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n" self.FileButton.setText(_translate("KCC", "Add file"))
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n" self.ClearButton.setText(_translate("KCC", "Clear list"))
"p, li { white-space: pre-wrap; }\n" self.MangaBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Enable right-to-left reading.</p></body></html>"))
"</style></head><body style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt; font-weight:400; font-style:normal;\">\n" self.MangaBox.setText(_translate("KCC", "Manga mode"))
"<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" self.QualityBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Quality of Panel View/zoom. Highly impact size of output file.<br/><span style=\" font-weight:600;\">This option control only quality of magnification!</span></p></body></html>"))
"<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" self.QualityBox.setText(_translate("KCC", "High/Ultra quality"))
"<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.RotateBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Disable splitting of two-page spreads.<br/>They will be rotated instead.</p></body></html>"))
self.QualityBox.setText(_translate("KCC", "High/Ultra quality", None)) self.RotateBox.setText(_translate("KCC", "Horizontal mode"))
self.RotateBox.setToolTip(_translate("KCC", "<html><head/><body><p>Disable page spliting.<br/>They will be rotated instead.</p></body></html>", None)) self.BasicModeButton.setText(_translate("KCC", "Basic"))
self.RotateBox.setText(_translate("KCC", "Horizontal mode", None)) self.AdvModeButton.setText(_translate("KCC", "Advanced"))
self.BasicModeButton.setText(_translate("KCC", "Basic", None)) self.GammaLabel.setText(_translate("KCC", "Gamma: Auto"))
self.AdvModeButton.setText(_translate("KCC", "Advanced", None)) self.ColorBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Don\'t convert images to grayscale.</p></body></html>"))
self.GammaLabel.setToolTip(_translate("KCC", "When converting color images setting this option to 1.0 MIGHT improve readability.", None)) self.ColorBox.setText(_translate("KCC", "Color mode"))
self.GammaLabel.setText(_translate("KCC", "Gamma: Auto", None)) self.wLabel.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Resolution of target device.</p></body></html>"))
self.GammaSlider.setToolTip(_translate("KCC", "<html><head/><body><p>When converting color images setting this option to 1.0 <span style=\" font-weight:600;\">might</span> improve readability.</p></body></html>", None)) self.wLabel.setText(_translate("KCC", "Custom width: "))
self.ColorBox.setToolTip(_translate("KCC", "Do not convert images to grayscale.", None)) self.customWidth.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Resolution of target device.</p></body></html>"))
self.ColorBox.setText(_translate("KCC", "Color mode", None)) self.customWidth.setInputMask(_translate("KCC", "0000"))
self.wLabel.setToolTip(_translate("KCC", "Resolution of target device.", None)) self.hLabel.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Resolution of target device.</p></body></html>"))
self.wLabel.setText(_translate("KCC", "Custom width: ", None)) self.hLabel.setText(_translate("KCC", "Custom height: "))
self.customWidth.setToolTip(_translate("KCC", "Resolution of target device.", None)) self.customHeight.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Resolution of target device.</p></body></html>"))
self.customWidth.setInputMask(_translate("KCC", "0000; ", None)) self.customHeight.setInputMask(_translate("KCC", "0000"))
self.hLabel.setToolTip(_translate("KCC", "Resolution of target device.", None)) self.EditorButton.setText(_translate("KCC", "Editor"))
self.hLabel.setText(_translate("KCC", "Custom height: ", None)) self.ActionBasic.setText(_translate("KCC", "Basic"))
self.customHeight.setToolTip(_translate("KCC", "Resolution of target device.", None)) self.ActionAdvanced.setText(_translate("KCC", "Advanced"))
self.customHeight.setInputMask(_translate("KCC", "0000; ", None))
self.ActionBasic.setText(_translate("KCC", "Basic", None))
self.ActionAdvanced.setText(_translate("KCC", "Advanced", None))
import KCC_rc from . import KCC_rc

385
kcc/KCC_ui_linux.py Normal file
View File

@@ -0,0 +1,385 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'gui/KCC-Linux.ui'
#
# Created: Sun Feb 8 03:10:09 2015
# by: PyQt5 UI code generator 5.2.1
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_KCC(object):
def setupUi(self, KCC):
KCC.setObjectName("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(":/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 = QtWidgets.QWidget(KCC)
self.Form.setObjectName("Form")
self.OptionsAdvanced = QtWidgets.QFrame(self.Form)
self.OptionsAdvanced.setEnabled(True)
self.OptionsAdvanced.setGeometry(QtCore.QRect(1, 254, 421, 61))
font = QtGui.QFont()
font.setFamily("DejaVu Sans")
font.setPointSize(9)
self.OptionsAdvanced.setFont(font)
self.OptionsAdvanced.setObjectName("OptionsAdvanced")
self.gridLayout = QtWidgets.QGridLayout(self.OptionsAdvanced)
self.gridLayout.setContentsMargins(9, -1, -1, -1)
self.gridLayout.setObjectName("gridLayout")
self.ProcessingBox = QtWidgets.QCheckBox(self.OptionsAdvanced)
font = QtGui.QFont()
font.setFamily("DejaVu Sans")
self.ProcessingBox.setFont(font)
self.ProcessingBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.ProcessingBox.setObjectName("ProcessingBox")
self.gridLayout.addWidget(self.ProcessingBox, 1, 0, 1, 1)
self.UpscaleBox = QtWidgets.QCheckBox(self.OptionsAdvanced)
font = QtGui.QFont()
font.setFamily("DejaVu Sans")
self.UpscaleBox.setFont(font)
self.UpscaleBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.UpscaleBox.setTristate(True)
self.UpscaleBox.setObjectName("UpscaleBox")
self.gridLayout.addWidget(self.UpscaleBox, 1, 1, 1, 1)
self.WebtoonBox = QtWidgets.QCheckBox(self.OptionsAdvanced)
font = QtGui.QFont()
font.setFamily("DejaVu Sans")
self.WebtoonBox.setFont(font)
self.WebtoonBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.WebtoonBox.setObjectName("WebtoonBox")
self.gridLayout.addWidget(self.WebtoonBox, 3, 1, 1, 1)
self.NoDitheringBox = QtWidgets.QCheckBox(self.OptionsAdvanced)
font = QtGui.QFont()
font.setFamily("DejaVu Sans")
self.NoDitheringBox.setFont(font)
self.NoDitheringBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.NoDitheringBox.setObjectName("NoDitheringBox")
self.gridLayout.addWidget(self.NoDitheringBox, 3, 2, 1, 1)
self.BorderBox = QtWidgets.QCheckBox(self.OptionsAdvanced)
font = QtGui.QFont()
font.setFamily("DejaVu Sans")
self.BorderBox.setFont(font)
self.BorderBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.BorderBox.setTristate(True)
self.BorderBox.setObjectName("BorderBox")
self.gridLayout.addWidget(self.BorderBox, 3, 0, 1, 1)
self.NoRotateBox = QtWidgets.QCheckBox(self.OptionsAdvanced)
font = QtGui.QFont()
font.setFamily("DejaVu Sans")
self.NoRotateBox.setFont(font)
self.NoRotateBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.NoRotateBox.setObjectName("NoRotateBox")
self.gridLayout.addWidget(self.NoRotateBox, 1, 2, 1, 1)
self.DeviceBox = QtWidgets.QComboBox(self.Form)
self.DeviceBox.setGeometry(QtCore.QRect(10, 200, 141, 31))
font = QtGui.QFont()
font.setFamily("DejaVu Sans")
font.setPointSize(8)
self.DeviceBox.setFont(font)
self.DeviceBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.DeviceBox.setObjectName("DeviceBox")
self.FormatBox = QtWidgets.QComboBox(self.Form)
self.FormatBox.setGeometry(QtCore.QRect(260, 200, 151, 31))
font = QtGui.QFont()
font.setFamily("DejaVu Sans")
font.setPointSize(8)
self.FormatBox.setFont(font)
self.FormatBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.FormatBox.setObjectName("FormatBox")
self.ConvertButton = QtWidgets.QPushButton(self.Form)
self.ConvertButton.setGeometry(QtCore.QRect(160, 200, 91, 32))
font = QtGui.QFont()
font.setFamily("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(":/Other/icons/convert.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.ConvertButton.setIcon(icon1)
self.ConvertButton.setObjectName("ConvertButton")
self.DirectoryButton = QtWidgets.QPushButton(self.Form)
self.DirectoryButton.setGeometry(QtCore.QRect(10, 160, 141, 32))
font = QtGui.QFont()
font.setFamily("DejaVu Sans")
font.setPointSize(8)
self.DirectoryButton.setFont(font)
self.DirectoryButton.setFocusPolicy(QtCore.Qt.NoFocus)
icon2 = QtGui.QIcon()
icon2.addPixmap(QtGui.QPixmap(":/Other/icons/folder_new.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.DirectoryButton.setIcon(icon2)
self.DirectoryButton.setObjectName("DirectoryButton")
self.FileButton = QtWidgets.QPushButton(self.Form)
self.FileButton.setGeometry(QtCore.QRect(260, 160, 151, 32))
font = QtGui.QFont()
font.setFamily("DejaVu Sans")
font.setPointSize(8)
self.FileButton.setFont(font)
self.FileButton.setFocusPolicy(QtCore.Qt.NoFocus)
icon3 = QtGui.QIcon()
icon3.addPixmap(QtGui.QPixmap(":/Other/icons/document_new.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.FileButton.setIcon(icon3)
self.FileButton.setObjectName("FileButton")
self.ClearButton = QtWidgets.QPushButton(self.Form)
self.ClearButton.setGeometry(QtCore.QRect(160, 160, 91, 32))
font = QtGui.QFont()
font.setFamily("DejaVu Sans")
font.setPointSize(8)
self.ClearButton.setFont(font)
self.ClearButton.setFocusPolicy(QtCore.Qt.NoFocus)
icon4 = QtGui.QIcon()
icon4.addPixmap(QtGui.QPixmap(":/Other/icons/clear.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.ClearButton.setIcon(icon4)
self.ClearButton.setObjectName("ClearButton")
self.OptionsBasic = QtWidgets.QFrame(self.Form)
self.OptionsBasic.setGeometry(QtCore.QRect(1, 230, 421, 41))
font = QtGui.QFont()
font.setFamily("DejaVu Sans")
font.setPointSize(9)
self.OptionsBasic.setFont(font)
self.OptionsBasic.setObjectName("OptionsBasic")
self.MangaBox = QtWidgets.QCheckBox(self.OptionsBasic)
self.MangaBox.setGeometry(QtCore.QRect(9, 10, 130, 18))
font = QtGui.QFont()
font.setFamily("DejaVu Sans")
self.MangaBox.setFont(font)
self.MangaBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.MangaBox.setObjectName("MangaBox")
self.QualityBox = QtWidgets.QCheckBox(self.OptionsBasic)
self.QualityBox.setGeometry(QtCore.QRect(282, 10, 135, 18))
font = QtGui.QFont()
font.setFamily("DejaVu Sans")
self.QualityBox.setFont(font)
self.QualityBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.QualityBox.setTristate(True)
self.QualityBox.setObjectName("QualityBox")
self.RotateBox = QtWidgets.QCheckBox(self.OptionsBasic)
self.RotateBox.setGeometry(QtCore.QRect(145, 10, 130, 18))
font = QtGui.QFont()
font.setFamily("DejaVu Sans")
self.RotateBox.setFont(font)
self.RotateBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.RotateBox.setObjectName("RotateBox")
self.JobList = QtWidgets.QListWidget(self.Form)
self.JobList.setGeometry(QtCore.QRect(10, 50, 401, 101))
font = QtGui.QFont()
font.setFamily("DejaVu Sans")
font.setPointSize(8)
font.setItalic(False)
self.JobList.setFont(font)
self.JobList.setFocusPolicy(QtCore.Qt.NoFocus)
self.JobList.setStyleSheet("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(QtWidgets.QAbstractItemView.NoSelection)
self.JobList.setIconSize(QtCore.QSize(18, 18))
self.JobList.setObjectName("JobList")
self.BasicModeButton = QtWidgets.QPushButton(self.Form)
self.BasicModeButton.setGeometry(QtCore.QRect(10, 10, 141, 32))
font = QtGui.QFont()
font.setFamily("DejaVu Sans")
font.setPointSize(9)
self.BasicModeButton.setFont(font)
self.BasicModeButton.setFocusPolicy(QtCore.Qt.NoFocus)
self.BasicModeButton.setObjectName("BasicModeButton")
self.AdvModeButton = QtWidgets.QPushButton(self.Form)
self.AdvModeButton.setGeometry(QtCore.QRect(260, 10, 151, 32))
font = QtGui.QFont()
font.setFamily("DejaVu Sans")
font.setPointSize(9)
self.AdvModeButton.setFont(font)
self.AdvModeButton.setFocusPolicy(QtCore.Qt.NoFocus)
self.AdvModeButton.setObjectName("AdvModeButton")
self.OptionsAdvancedGamma = QtWidgets.QFrame(self.Form)
self.OptionsAdvancedGamma.setEnabled(True)
self.OptionsAdvancedGamma.setGeometry(QtCore.QRect(10, 305, 401, 41))
font = QtGui.QFont()
font.setFamily("DejaVu Sans")
font.setPointSize(9)
self.OptionsAdvancedGamma.setFont(font)
self.OptionsAdvancedGamma.setObjectName("OptionsAdvancedGamma")
self.GammaLabel = QtWidgets.QLabel(self.OptionsAdvancedGamma)
self.GammaLabel.setGeometry(QtCore.QRect(15, 0, 100, 40))
font = QtGui.QFont()
font.setFamily("DejaVu Sans")
self.GammaLabel.setFont(font)
self.GammaLabel.setObjectName("GammaLabel")
self.GammaSlider = QtWidgets.QSlider(self.OptionsAdvancedGamma)
self.GammaSlider.setGeometry(QtCore.QRect(110, 10, 275, 22))
font = QtGui.QFont()
font.setFamily("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("GammaSlider")
self.ProgressBar = QtWidgets.QProgressBar(self.Form)
self.ProgressBar.setGeometry(QtCore.QRect(10, 10, 401, 31))
font = QtGui.QFont()
font.setFamily("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("")
self.ProgressBar.setObjectName("ProgressBar")
self.OptionsExpert = QtWidgets.QFrame(self.Form)
self.OptionsExpert.setGeometry(QtCore.QRect(1, 337, 421, 41))
font = QtGui.QFont()
font.setFamily("DejaVu Sans")
font.setPointSize(9)
self.OptionsExpert.setFont(font)
self.OptionsExpert.setObjectName("OptionsExpert")
self.ColorBox = QtWidgets.QCheckBox(self.OptionsExpert)
self.ColorBox.setGeometry(QtCore.QRect(9, 11, 130, 18))
font = QtGui.QFont()
font.setFamily("DejaVu Sans")
self.ColorBox.setFont(font)
self.ColorBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.ColorBox.setObjectName("ColorBox")
self.OptionsExpertInternal = QtWidgets.QFrame(self.OptionsExpert)
self.OptionsExpertInternal.setGeometry(QtCore.QRect(105, 0, 295, 40))
font = QtGui.QFont()
font.setFamily("DejaVu Sans")
self.OptionsExpertInternal.setFont(font)
self.OptionsExpertInternal.setObjectName("OptionsExpertInternal")
self.gridLayout_2 = QtWidgets.QGridLayout(self.OptionsExpertInternal)
self.gridLayout_2.setObjectName("gridLayout_2")
self.wLabel = QtWidgets.QLabel(self.OptionsExpertInternal)
font = QtGui.QFont()
font.setFamily("DejaVu Sans")
self.wLabel.setFont(font)
self.wLabel.setObjectName("wLabel")
self.gridLayout_2.addWidget(self.wLabel, 0, 0, 1, 1)
self.customWidth = QtWidgets.QLineEdit(self.OptionsExpertInternal)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.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("DejaVu Sans")
self.customWidth.setFont(font)
self.customWidth.setFocusPolicy(QtCore.Qt.ClickFocus)
self.customWidth.setAcceptDrops(False)
self.customWidth.setMaxLength(4)
self.customWidth.setObjectName("customWidth")
self.gridLayout_2.addWidget(self.customWidth, 0, 1, 1, 1)
self.hLabel = QtWidgets.QLabel(self.OptionsExpertInternal)
font = QtGui.QFont()
font.setFamily("DejaVu Sans")
self.hLabel.setFont(font)
self.hLabel.setObjectName("hLabel")
self.gridLayout_2.addWidget(self.hLabel, 0, 2, 1, 1)
self.customHeight = QtWidgets.QLineEdit(self.OptionsExpertInternal)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.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("DejaVu Sans")
self.customHeight.setFont(font)
self.customHeight.setFocusPolicy(QtCore.Qt.ClickFocus)
self.customHeight.setAcceptDrops(False)
self.customHeight.setMaxLength(4)
self.customHeight.setObjectName("customHeight")
self.gridLayout_2.addWidget(self.customHeight, 0, 3, 1, 1)
self.EditorButton = QtWidgets.QPushButton(self.Form)
self.EditorButton.setGeometry(QtCore.QRect(160, 10, 91, 32))
font = QtGui.QFont()
font.setFamily("DejaVu Sans")
font.setPointSize(9)
self.EditorButton.setFont(font)
self.EditorButton.setFocusPolicy(QtCore.Qt.NoFocus)
icon5 = QtGui.QIcon()
icon5.addPixmap(QtGui.QPixmap(":/Other/icons/editor.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.EditorButton.setIcon(icon5)
self.EditorButton.setObjectName("EditorButton")
KCC.setCentralWidget(self.Form)
self.statusBar = QtWidgets.QStatusBar(KCC)
font = QtGui.QFont()
font.setFamily("DejaVu Sans")
font.setPointSize(8)
self.statusBar.setFont(font)
self.statusBar.setSizeGripEnabled(False)
self.statusBar.setObjectName("statusBar")
KCC.setStatusBar(self.statusBar)
self.ActionBasic = QtWidgets.QAction(KCC)
self.ActionBasic.setCheckable(True)
self.ActionBasic.setChecked(False)
font = QtGui.QFont()
self.ActionBasic.setFont(font)
self.ActionBasic.setObjectName("ActionBasic")
self.ActionAdvanced = QtWidgets.QAction(KCC)
self.ActionAdvanced.setCheckable(True)
self.ActionAdvanced.setObjectName("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):
_translate = QtCore.QCoreApplication.translate
KCC.setWindowTitle(_translate("KCC", "Kindle Comic Converter"))
self.ProcessingBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Disable image optimizations.<br/><span style=\" font-weight:600;\">Input images must be already resized.</span></p></body></html>"))
self.ProcessingBox.setText(_translate("KCC", "No optimisation"))
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>"))
self.UpscaleBox.setText(_translate("KCC", "Stretch/Upscale"))
self.WebtoonBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Enable special parsing mode for WebToons.</p></body></html>"))
self.WebtoonBox.setText(_translate("KCC", "Webtoon mode"))
self.NoDitheringBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>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>"))
self.NoDitheringBox.setText(_translate("KCC", "PNG output"))
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>"))
self.BorderBox.setText(_translate("KCC", "W/B margins"))
self.NoRotateBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Disable page splitting and rotation.</p></body></html>"))
self.NoRotateBox.setText(_translate("KCC", "No split/rotate"))
self.DeviceBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Target device.</p></body></html>"))
self.FormatBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Output format.</p></body></html>"))
self.ConvertButton.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Shift+Click to select the output directory.</p></body></html>"))
self.ConvertButton.setText(_translate("KCC", "Convert"))
self.DirectoryButton.setToolTip(_translate("KCC", "<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("KCC", "Add directory"))
self.FileButton.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Add CBR, CBZ, CB7 or PDF file to queue.</p></body></html>"))
self.FileButton.setText(_translate("KCC", "Add file"))
self.ClearButton.setText(_translate("KCC", "Clear list"))
self.MangaBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Enable right-to-left reading.</p></body></html>"))
self.MangaBox.setText(_translate("KCC", "Manga mode"))
self.QualityBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Quality of Panel View/zoom. Highly impact size of output file.<br/><span style=\" font-weight:600;\">This option control only quality of magnification!</span></p></body></html>"))
self.QualityBox.setText(_translate("KCC", "High/Ultra quality"))
self.RotateBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Disable splitting of two-page spreads.<br/>They will be rotated instead.</p></body></html>"))
self.RotateBox.setText(_translate("KCC", "Horizontal mode"))
self.BasicModeButton.setText(_translate("KCC", "Basic"))
self.AdvModeButton.setText(_translate("KCC", "Advanced"))
self.GammaLabel.setText(_translate("KCC", "Gamma: Auto"))
self.ColorBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Don\'t convert images to grayscale.</p></body></html>"))
self.ColorBox.setText(_translate("KCC", "Color mode"))
self.wLabel.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Resolution of target device.</p></body></html>"))
self.wLabel.setText(_translate("KCC", "Custom width: "))
self.customWidth.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Resolution of target device.</p></body></html>"))
self.customWidth.setInputMask(_translate("KCC", "0000"))
self.hLabel.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Resolution of target device.</p></body></html>"))
self.hLabel.setText(_translate("KCC", "Custom height: "))
self.customHeight.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Resolution of target device.</p></body></html>"))
self.customHeight.setInputMask(_translate("KCC", "0000"))
self.EditorButton.setText(_translate("KCC", "Editor"))
self.ActionBasic.setText(_translate("KCC", "Basic"))
self.ActionAdvanced.setText(_translate("KCC", "Advanced"))
from . import KCC_rc

View File

@@ -1,315 +1,356 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'KCC-OSX.ui' # Form implementation generated from reading ui file '/Users/pawelj/Documents/KCC/gui/KCC-OSX.ui'
# #
# Created: Fri Jun 21 18:23:35 2013 # Created: Sun Feb 8 12:37:33 2015
# by: PyQt4 UI code generator 4.10.1 # by: PyQt5 UI code generator 5.4
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui from PyQt5 import QtCore, QtGui, QtWidgets
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): class Ui_KCC(object):
def setupUi(self, KCC): def setupUi(self, KCC):
KCC.setObjectName(_fromUtf8("KCC")) KCC.setObjectName("KCC")
KCC.resize(420, 380) KCC.resize(420, 397)
KCC.setMinimumSize(QtCore.QSize(420, 380)) KCC.setMinimumSize(QtCore.QSize(420, 397))
KCC.setMaximumSize(QtCore.QSize(420, 380)) KCC.setMaximumSize(QtCore.QSize(420, 397))
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(9) font.setPointSize(9)
KCC.setFont(font) KCC.setFont(font)
KCC.setFocusPolicy(QtCore.Qt.NoFocus)
icon = QtGui.QIcon() icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/Icon/icons/comic2ebook.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) icon.addPixmap(QtGui.QPixmap(":/Icon/icons/comic2ebook.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
KCC.setWindowIcon(icon) KCC.setWindowIcon(icon)
KCC.setLocale(QtCore.QLocale(QtCore.QLocale.C, QtCore.QLocale.AnyCountry)) KCC.setLocale(QtCore.QLocale(QtCore.QLocale.C, QtCore.QLocale.AnyCountry))
self.Form = QtGui.QWidget(KCC) self.Form = QtWidgets.QWidget(KCC)
self.Form.setObjectName(_fromUtf8("Form")) self.Form.setObjectName("Form")
self.OptionsAdvanced = QtGui.QFrame(self.Form) self.OptionsAdvanced = QtWidgets.QFrame(self.Form)
self.OptionsAdvanced.setEnabled(True) self.OptionsAdvanced.setEnabled(True)
self.OptionsAdvanced.setGeometry(QtCore.QRect(9, 253, 421, 61)) self.OptionsAdvanced.setGeometry(QtCore.QRect(4, 253, 421, 61))
font = QtGui.QFont() font = QtGui.QFont()
font.setFamily("Lucida Grande")
font.setPointSize(9) font.setPointSize(9)
self.OptionsAdvanced.setFont(font) self.OptionsAdvanced.setFont(font)
self.OptionsAdvanced.setObjectName(_fromUtf8("OptionsAdvanced")) self.OptionsAdvanced.setObjectName("OptionsAdvanced")
self.gridLayout = QtGui.QGridLayout(self.OptionsAdvanced) self.gridLayout = QtWidgets.QGridLayout(self.OptionsAdvanced)
self.gridLayout.setObjectName(_fromUtf8("gridLayout")) self.gridLayout.setObjectName("gridLayout")
self.ProcessingBox = QtGui.QCheckBox(self.OptionsAdvanced) self.ProcessingBox = QtWidgets.QCheckBox(self.OptionsAdvanced)
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(11) font.setFamily("Lucida Grande")
font.setPointSize(12)
self.ProcessingBox.setFont(font) self.ProcessingBox.setFont(font)
self.ProcessingBox.setFocusPolicy(QtCore.Qt.NoFocus) self.ProcessingBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.ProcessingBox.setObjectName(_fromUtf8("ProcessingBox")) self.ProcessingBox.setObjectName("ProcessingBox")
self.gridLayout.addWidget(self.ProcessingBox, 1, 0, 1, 1) self.gridLayout.addWidget(self.ProcessingBox, 1, 0, 1, 1)
self.UpscaleBox = QtGui.QCheckBox(self.OptionsAdvanced) self.UpscaleBox = QtWidgets.QCheckBox(self.OptionsAdvanced)
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(11) font.setFamily("Lucida Grande")
font.setPointSize(12)
self.UpscaleBox.setFont(font) self.UpscaleBox.setFont(font)
self.UpscaleBox.setFocusPolicy(QtCore.Qt.NoFocus) self.UpscaleBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.UpscaleBox.setObjectName(_fromUtf8("UpscaleBox")) self.UpscaleBox.setTristate(True)
self.UpscaleBox.setObjectName("UpscaleBox")
self.gridLayout.addWidget(self.UpscaleBox, 1, 1, 1, 1) self.gridLayout.addWidget(self.UpscaleBox, 1, 1, 1, 1)
self.StretchBox = QtGui.QCheckBox(self.OptionsAdvanced) self.WebtoonBox = QtWidgets.QCheckBox(self.OptionsAdvanced)
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(11) font.setFamily("Lucida Grande")
self.StretchBox.setFont(font) font.setPointSize(12)
self.StretchBox.setFocusPolicy(QtCore.Qt.NoFocus) self.WebtoonBox.setFont(font)
self.StretchBox.setObjectName(_fromUtf8("StretchBox")) self.WebtoonBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.gridLayout.addWidget(self.StretchBox, 3, 1, 1, 1) self.WebtoonBox.setObjectName("WebtoonBox")
self.NoDitheringBox = QtGui.QCheckBox(self.OptionsAdvanced) self.gridLayout.addWidget(self.WebtoonBox, 3, 1, 1, 1)
self.NoDitheringBox = QtWidgets.QCheckBox(self.OptionsAdvanced)
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(11) font.setFamily("Lucida Grande")
font.setPointSize(12)
self.NoDitheringBox.setFont(font) self.NoDitheringBox.setFont(font)
self.NoDitheringBox.setFocusPolicy(QtCore.Qt.NoFocus) self.NoDitheringBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.NoDitheringBox.setObjectName(_fromUtf8("NoDitheringBox")) self.NoDitheringBox.setObjectName("NoDitheringBox")
self.gridLayout.addWidget(self.NoDitheringBox, 3, 2, 1, 1) self.gridLayout.addWidget(self.NoDitheringBox, 3, 2, 1, 1)
self.BorderBox = QtGui.QCheckBox(self.OptionsAdvanced) self.BorderBox = QtWidgets.QCheckBox(self.OptionsAdvanced)
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(11) font.setFamily("Lucida Grande")
font.setPointSize(12)
self.BorderBox.setFont(font) self.BorderBox.setFont(font)
self.BorderBox.setFocusPolicy(QtCore.Qt.NoFocus) self.BorderBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.BorderBox.setObjectName(_fromUtf8("BorderBox")) self.BorderBox.setTristate(True)
self.BorderBox.setObjectName("BorderBox")
self.gridLayout.addWidget(self.BorderBox, 3, 0, 1, 1) self.gridLayout.addWidget(self.BorderBox, 3, 0, 1, 1)
self.NoRotateBox = QtGui.QCheckBox(self.OptionsAdvanced) self.NoRotateBox = QtWidgets.QCheckBox(self.OptionsAdvanced)
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(11) font.setFamily("Lucida Grande")
font.setPointSize(12)
self.NoRotateBox.setFont(font) self.NoRotateBox.setFont(font)
self.NoRotateBox.setFocusPolicy(QtCore.Qt.NoFocus) self.NoRotateBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.NoRotateBox.setObjectName(_fromUtf8("NoRotateBox")) self.NoRotateBox.setObjectName("NoRotateBox")
self.gridLayout.addWidget(self.NoRotateBox, 1, 2, 1, 1) self.gridLayout.addWidget(self.NoRotateBox, 1, 2, 1, 1)
self.DeviceBox = QtGui.QComboBox(self.Form) self.DeviceBox = QtWidgets.QComboBox(self.Form)
self.DeviceBox.setGeometry(QtCore.QRect(8, 200, 151, 34)) self.DeviceBox.setGeometry(QtCore.QRect(8, 201, 151, 34))
font = QtGui.QFont() font = QtGui.QFont()
font.setFamily("Lucida Grande")
font.setPointSize(11) font.setPointSize(11)
self.DeviceBox.setFont(font) self.DeviceBox.setFont(font)
self.DeviceBox.setFocusPolicy(QtCore.Qt.NoFocus) self.DeviceBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.DeviceBox.setObjectName(_fromUtf8("DeviceBox")) self.DeviceBox.setObjectName("DeviceBox")
self.FormatBox = QtGui.QComboBox(self.Form) self.FormatBox = QtWidgets.QComboBox(self.Form)
self.FormatBox.setGeometry(QtCore.QRect(262, 200, 152, 34)) self.FormatBox.setGeometry(QtCore.QRect(262, 201, 152, 34))
font = QtGui.QFont() font = QtGui.QFont()
font.setFamily("Lucida Grande")
font.setPointSize(11) font.setPointSize(11)
self.FormatBox.setFont(font) self.FormatBox.setFont(font)
self.FormatBox.setFocusPolicy(QtCore.Qt.NoFocus) self.FormatBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.FormatBox.setObjectName(_fromUtf8("FormatBox")) self.FormatBox.setObjectName("FormatBox")
self.ConvertButton = QtGui.QPushButton(self.Form) self.ConvertButton = QtWidgets.QPushButton(self.Form)
self.ConvertButton.setGeometry(QtCore.QRect(160, 200, 101, 41)) self.ConvertButton.setGeometry(QtCore.QRect(160, 200, 101, 41))
font = QtGui.QFont() font = QtGui.QFont()
font.setFamily("Lucida Grande")
font.setPointSize(11) font.setPointSize(11)
font.setBold(True) font.setBold(True)
font.setWeight(75) font.setWeight(75)
self.ConvertButton.setFont(font) self.ConvertButton.setFont(font)
self.ConvertButton.setFocusPolicy(QtCore.Qt.NoFocus) self.ConvertButton.setFocusPolicy(QtCore.Qt.NoFocus)
icon1 = QtGui.QIcon() icon1 = QtGui.QIcon()
icon1.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/convert.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) icon1.addPixmap(QtGui.QPixmap(":/Other/icons/convert.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.ConvertButton.setIcon(icon1) self.ConvertButton.setIcon(icon1)
self.ConvertButton.setObjectName(_fromUtf8("ConvertButton")) self.ConvertButton.setObjectName("ConvertButton")
self.DirectoryButton = QtGui.QPushButton(self.Form) self.DirectoryButton = QtWidgets.QPushButton(self.Form)
self.DirectoryButton.setGeometry(QtCore.QRect(5, 160, 156, 41)) self.DirectoryButton.setGeometry(QtCore.QRect(5, 160, 156, 41))
font = QtGui.QFont() font = QtGui.QFont()
font.setFamily("Lucida Grande")
font.setPointSize(11) font.setPointSize(11)
self.DirectoryButton.setFont(font) self.DirectoryButton.setFont(font)
self.DirectoryButton.setFocusPolicy(QtCore.Qt.NoFocus) self.DirectoryButton.setFocusPolicy(QtCore.Qt.NoFocus)
icon2 = QtGui.QIcon() icon2 = QtGui.QIcon()
icon2.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/folder_new.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) icon2.addPixmap(QtGui.QPixmap(":/Other/icons/folder_new.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.DirectoryButton.setIcon(icon2) self.DirectoryButton.setIcon(icon2)
self.DirectoryButton.setObjectName(_fromUtf8("DirectoryButton")) self.DirectoryButton.setObjectName("DirectoryButton")
self.FileButton = QtGui.QPushButton(self.Form) self.FileButton = QtWidgets.QPushButton(self.Form)
self.FileButton.setGeometry(QtCore.QRect(260, 160, 157, 41)) self.FileButton.setGeometry(QtCore.QRect(260, 160, 157, 41))
font = QtGui.QFont() font = QtGui.QFont()
font.setFamily("Lucida Grande")
font.setPointSize(11) font.setPointSize(11)
self.FileButton.setFont(font) self.FileButton.setFont(font)
self.FileButton.setFocusPolicy(QtCore.Qt.NoFocus) self.FileButton.setFocusPolicy(QtCore.Qt.NoFocus)
icon3 = QtGui.QIcon() icon3 = QtGui.QIcon()
icon3.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/document_new.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) icon3.addPixmap(QtGui.QPixmap(":/Other/icons/document_new.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.FileButton.setIcon(icon3) self.FileButton.setIcon(icon3)
self.FileButton.setObjectName(_fromUtf8("FileButton")) self.FileButton.setObjectName("FileButton")
self.ClearButton = QtGui.QPushButton(self.Form) self.ClearButton = QtWidgets.QPushButton(self.Form)
self.ClearButton.setGeometry(QtCore.QRect(160, 160, 101, 41)) self.ClearButton.setGeometry(QtCore.QRect(160, 160, 101, 41))
font = QtGui.QFont() font = QtGui.QFont()
font.setFamily("Lucida Grande")
font.setPointSize(11) font.setPointSize(11)
self.ClearButton.setFont(font) self.ClearButton.setFont(font)
self.ClearButton.setFocusPolicy(QtCore.Qt.NoFocus) self.ClearButton.setFocusPolicy(QtCore.Qt.NoFocus)
icon4 = QtGui.QIcon() icon4 = QtGui.QIcon()
icon4.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/clear.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) icon4.addPixmap(QtGui.QPixmap(":/Other/icons/clear.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.ClearButton.setIcon(icon4) self.ClearButton.setIcon(icon4)
self.ClearButton.setObjectName(_fromUtf8("ClearButton")) self.ClearButton.setObjectName("ClearButton")
self.OptionsBasic = QtGui.QFrame(self.Form) self.OptionsBasic = QtWidgets.QFrame(self.Form)
self.OptionsBasic.setGeometry(QtCore.QRect(10, 233, 421, 41)) self.OptionsBasic.setGeometry(QtCore.QRect(5, 233, 421, 41))
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(9) font.setFamily("Lucida Grande")
font.setPointSize(12)
self.OptionsBasic.setFont(font) self.OptionsBasic.setFont(font)
self.OptionsBasic.setObjectName(_fromUtf8("OptionsBasic")) self.OptionsBasic.setObjectName("OptionsBasic")
self.MangaBox = QtGui.QCheckBox(self.OptionsBasic) self.MangaBox = QtWidgets.QCheckBox(self.OptionsBasic)
self.MangaBox.setGeometry(QtCore.QRect(9, 10, 130, 18)) self.MangaBox.setGeometry(QtCore.QRect(9, 10, 130, 18))
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(11) font.setFamily("Lucida Grande")
font.setPointSize(12)
self.MangaBox.setFont(font) self.MangaBox.setFont(font)
self.MangaBox.setFocusPolicy(QtCore.Qt.NoFocus) self.MangaBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.MangaBox.setObjectName(_fromUtf8("MangaBox")) self.MangaBox.setObjectName("MangaBox")
self.QualityBox = QtGui.QCheckBox(self.OptionsBasic) self.QualityBox = QtWidgets.QCheckBox(self.OptionsBasic)
self.QualityBox.setGeometry(QtCore.QRect(282, 10, 130, 18)) self.QualityBox.setGeometry(QtCore.QRect(282, 10, 135, 18))
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(11) font.setFamily("Lucida Grande")
font.setPointSize(12)
self.QualityBox.setFont(font) self.QualityBox.setFont(font)
self.QualityBox.setFocusPolicy(QtCore.Qt.NoFocus) self.QualityBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.QualityBox.setTristate(True) self.QualityBox.setTristate(True)
self.QualityBox.setObjectName(_fromUtf8("QualityBox")) self.QualityBox.setObjectName("QualityBox")
self.RotateBox = QtGui.QCheckBox(self.OptionsBasic) self.RotateBox = QtWidgets.QCheckBox(self.OptionsBasic)
self.RotateBox.setGeometry(QtCore.QRect(145, 10, 130, 18)) self.RotateBox.setGeometry(QtCore.QRect(145, 10, 130, 18))
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(11) font.setFamily("Lucida Grande")
font.setPointSize(12)
self.RotateBox.setFont(font) self.RotateBox.setFont(font)
self.RotateBox.setFocusPolicy(QtCore.Qt.NoFocus) self.RotateBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.RotateBox.setObjectName(_fromUtf8("RotateBox")) self.RotateBox.setObjectName("RotateBox")
self.JobList = QtGui.QListWidget(self.Form) self.JobList = QtWidgets.QListWidget(self.Form)
self.JobList.setGeometry(QtCore.QRect(10, 50, 401, 101)) self.JobList.setGeometry(QtCore.QRect(10, 50, 401, 101))
font = QtGui.QFont() font = QtGui.QFont()
font.setFamily("Lucida Grande")
font.setPointSize(11) font.setPointSize(11)
self.JobList.setFont(font) self.JobList.setFont(font)
self.JobList.setFocusPolicy(QtCore.Qt.NoFocus) self.JobList.setFocusPolicy(QtCore.Qt.NoFocus)
self.JobList.setStyleSheet("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.setProperty("showDropIndicator", False)
self.JobList.setSelectionMode(QtGui.QAbstractItemView.NoSelection) self.JobList.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
self.JobList.setObjectName(_fromUtf8("JobList")) self.JobList.setObjectName("JobList")
self.BasicModeButton = QtGui.QPushButton(self.Form) self.BasicModeButton = QtWidgets.QPushButton(self.Form)
self.BasicModeButton.setGeometry(QtCore.QRect(5, 10, 210, 41)) self.BasicModeButton.setGeometry(QtCore.QRect(5, 10, 156, 41))
font = QtGui.QFont() font = QtGui.QFont()
font.setFamily("Lucida Grande")
font.setPointSize(12) font.setPointSize(12)
font.setBold(False) font.setBold(False)
font.setWeight(50) font.setWeight(50)
self.BasicModeButton.setFont(font) self.BasicModeButton.setFont(font)
self.BasicModeButton.setFocusPolicy(QtCore.Qt.NoFocus) self.BasicModeButton.setFocusPolicy(QtCore.Qt.NoFocus)
self.BasicModeButton.setObjectName(_fromUtf8("BasicModeButton")) self.BasicModeButton.setObjectName("BasicModeButton")
self.AdvModeButton = QtGui.QPushButton(self.Form) self.AdvModeButton = QtWidgets.QPushButton(self.Form)
self.AdvModeButton.setGeometry(QtCore.QRect(207, 10, 210, 41)) self.AdvModeButton.setGeometry(QtCore.QRect(260, 10, 156, 41))
font = QtGui.QFont() font = QtGui.QFont()
font.setFamily("Lucida Grande")
font.setPointSize(12) font.setPointSize(12)
font.setBold(False) font.setBold(False)
font.setWeight(50) font.setWeight(50)
self.AdvModeButton.setFont(font) self.AdvModeButton.setFont(font)
self.AdvModeButton.setFocusPolicy(QtCore.Qt.NoFocus) self.AdvModeButton.setFocusPolicy(QtCore.Qt.NoFocus)
self.AdvModeButton.setObjectName(_fromUtf8("AdvModeButton")) self.AdvModeButton.setObjectName("AdvModeButton")
self.OptionsAdvancedGamma = QtGui.QFrame(self.Form) self.OptionsAdvancedGamma = QtWidgets.QFrame(self.Form)
self.OptionsAdvancedGamma.setEnabled(True) self.OptionsAdvancedGamma.setEnabled(True)
self.OptionsAdvancedGamma.setGeometry(QtCore.QRect(10, 303, 401, 41)) self.OptionsAdvancedGamma.setGeometry(QtCore.QRect(5, 303, 401, 41))
font = QtGui.QFont() font = QtGui.QFont()
font.setFamily("Lucida Grande")
font.setPointSize(9) font.setPointSize(9)
self.OptionsAdvancedGamma.setFont(font) self.OptionsAdvancedGamma.setFont(font)
self.OptionsAdvancedGamma.setObjectName(_fromUtf8("OptionsAdvancedGamma")) self.OptionsAdvancedGamma.setObjectName("OptionsAdvancedGamma")
self.GammaLabel = QtGui.QLabel(self.OptionsAdvancedGamma) self.GammaLabel = QtWidgets.QLabel(self.OptionsAdvancedGamma)
self.GammaLabel.setGeometry(QtCore.QRect(20, 0, 100, 40)) self.GammaLabel.setGeometry(QtCore.QRect(20, 0, 100, 40))
font = QtGui.QFont() font = QtGui.QFont()
font.setFamily("Lucida Grande")
font.setPointSize(12) font.setPointSize(12)
font.setBold(False) font.setBold(False)
font.setWeight(50) font.setWeight(50)
self.GammaLabel.setFont(font) self.GammaLabel.setFont(font)
self.GammaLabel.setObjectName(_fromUtf8("GammaLabel")) self.GammaLabel.setObjectName("GammaLabel")
self.GammaSlider = QtGui.QSlider(self.OptionsAdvancedGamma) self.GammaSlider = QtWidgets.QSlider(self.OptionsAdvancedGamma)
self.GammaSlider.setGeometry(QtCore.QRect(110, 10, 280, 22)) self.GammaSlider.setGeometry(QtCore.QRect(110, 10, 290, 22))
font = QtGui.QFont()
font.setFamily("Lucida Grande")
self.GammaSlider.setFont(font)
self.GammaSlider.setFocusPolicy(QtCore.Qt.ClickFocus) self.GammaSlider.setFocusPolicy(QtCore.Qt.ClickFocus)
self.GammaSlider.setMaximum(500) self.GammaSlider.setMaximum(500)
self.GammaSlider.setSingleStep(5) self.GammaSlider.setSingleStep(5)
self.GammaSlider.setOrientation(QtCore.Qt.Horizontal) self.GammaSlider.setOrientation(QtCore.Qt.Horizontal)
self.GammaSlider.setObjectName(_fromUtf8("GammaSlider")) self.GammaSlider.setObjectName("GammaSlider")
self.ProgressBar = QtGui.QProgressBar(self.Form) self.ProgressBar = QtWidgets.QProgressBar(self.Form)
self.ProgressBar.setGeometry(QtCore.QRect(10, 10, 401, 35)) self.ProgressBar.setGeometry(QtCore.QRect(10, 10, 401, 29))
font = QtGui.QFont() font = QtGui.QFont()
font.setFamily("Lucida Grande")
font.setPointSize(10) font.setPointSize(10)
font.setBold(True) font.setBold(True)
font.setWeight(75) font.setWeight(75)
self.ProgressBar.setFont(font) self.ProgressBar.setFont(font)
self.ProgressBar.setAutoFillBackground(True)
self.ProgressBar.setProperty("value", 0) self.ProgressBar.setProperty("value", 0)
self.ProgressBar.setAlignment(QtCore.Qt.AlignJustify|QtCore.Qt.AlignVCenter) self.ProgressBar.setAlignment(QtCore.Qt.AlignJustify|QtCore.Qt.AlignVCenter)
self.ProgressBar.setFormat(_fromUtf8("")) self.ProgressBar.setFormat("")
self.ProgressBar.setObjectName(_fromUtf8("ProgressBar")) self.ProgressBar.setObjectName("ProgressBar")
self.OptionsExpert = QtGui.QFrame(self.Form) self.OptionsExpert = QtWidgets.QFrame(self.Form)
self.OptionsExpert.setGeometry(QtCore.QRect(10, 335, 421, 41)) self.OptionsExpert.setGeometry(QtCore.QRect(5, 335, 421, 41))
font = QtGui.QFont() font = QtGui.QFont()
font.setFamily("Lucida Grande")
font.setPointSize(9) font.setPointSize(9)
self.OptionsExpert.setFont(font) self.OptionsExpert.setFont(font)
self.OptionsExpert.setObjectName(_fromUtf8("OptionsExpert")) self.OptionsExpert.setObjectName("OptionsExpert")
self.ColorBox = QtGui.QCheckBox(self.OptionsExpert) self.ColorBox = QtWidgets.QCheckBox(self.OptionsExpert)
self.ColorBox.setGeometry(QtCore.QRect(9, 11, 130, 18)) self.ColorBox.setGeometry(QtCore.QRect(9, 11, 130, 18))
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(11) font.setFamily("Lucida Grande")
font.setPointSize(12)
self.ColorBox.setFont(font) self.ColorBox.setFont(font)
self.ColorBox.setFocusPolicy(QtCore.Qt.NoFocus) self.ColorBox.setFocusPolicy(QtCore.Qt.NoFocus)
self.ColorBox.setObjectName(_fromUtf8("ColorBox")) self.ColorBox.setObjectName("ColorBox")
self.OptionsExpertInternal = QtGui.QFrame(self.OptionsExpert) self.OptionsExpertInternal = QtWidgets.QFrame(self.OptionsExpert)
self.OptionsExpertInternal.setGeometry(QtCore.QRect(90, 0, 315, 40)) self.OptionsExpertInternal.setGeometry(QtCore.QRect(95, 0, 315, 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)
font = QtGui.QFont() font = QtGui.QFont()
font.setFamily("Lucida Grande")
self.OptionsExpertInternal.setFont(font)
self.OptionsExpertInternal.setObjectName("OptionsExpertInternal")
self.gridLayout_2 = QtWidgets.QGridLayout(self.OptionsExpertInternal)
self.gridLayout_2.setObjectName("gridLayout_2")
self.wLabel = QtWidgets.QLabel(self.OptionsExpertInternal)
font = QtGui.QFont()
font.setFamily("Lucida Grande")
font.setPointSize(12) font.setPointSize(12)
font.setBold(False) font.setBold(False)
font.setWeight(50) font.setWeight(50)
self.wLabel.setFont(font) self.wLabel.setFont(font)
self.wLabel.setObjectName(_fromUtf8("wLabel")) self.wLabel.setObjectName("wLabel")
self.gridLayout_2.addWidget(self.wLabel, 0, 0, 1, 1) self.gridLayout_2.addWidget(self.wLabel, 0, 0, 1, 1)
self.customWidth = QtGui.QLineEdit(self.OptionsExpertInternal) self.customWidth = QtWidgets.QLineEdit(self.OptionsExpertInternal)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.customWidth.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.customWidth.sizePolicy().hasHeightForWidth())
self.customWidth.setSizePolicy(sizePolicy) self.customWidth.setSizePolicy(sizePolicy)
self.customWidth.setMaximumSize(QtCore.QSize(45, 16777215)) self.customWidth.setMaximumSize(QtCore.QSize(45, 16777215))
font = QtGui.QFont() font = QtGui.QFont()
font.setFamily("Lucida Grande")
font.setPointSize(12) font.setPointSize(12)
self.customWidth.setFont(font) self.customWidth.setFont(font)
self.customWidth.setFocusPolicy(QtCore.Qt.ClickFocus) self.customWidth.setFocusPolicy(QtCore.Qt.ClickFocus)
self.customWidth.setAcceptDrops(False) self.customWidth.setAcceptDrops(False)
self.customWidth.setMaxLength(4) self.customWidth.setMaxLength(4)
self.customWidth.setObjectName(_fromUtf8("customWidth")) self.customWidth.setObjectName("customWidth")
self.gridLayout_2.addWidget(self.customWidth, 0, 1, 1, 1) self.gridLayout_2.addWidget(self.customWidth, 0, 1, 1, 1)
self.hLabel = QtGui.QLabel(self.OptionsExpertInternal) self.hLabel = QtWidgets.QLabel(self.OptionsExpertInternal)
font = QtGui.QFont() font = QtGui.QFont()
font.setFamily("Lucida Grande")
font.setPointSize(12) font.setPointSize(12)
font.setBold(False) font.setBold(False)
font.setWeight(50) font.setWeight(50)
self.hLabel.setFont(font) self.hLabel.setFont(font)
self.hLabel.setObjectName(_fromUtf8("hLabel")) self.hLabel.setObjectName("hLabel")
self.gridLayout_2.addWidget(self.hLabel, 0, 2, 1, 1) self.gridLayout_2.addWidget(self.hLabel, 0, 2, 1, 1)
self.customHeight = QtGui.QLineEdit(self.OptionsExpertInternal) self.customHeight = QtWidgets.QLineEdit(self.OptionsExpertInternal)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.customHeight.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.customHeight.sizePolicy().hasHeightForWidth())
self.customHeight.setSizePolicy(sizePolicy) self.customHeight.setSizePolicy(sizePolicy)
self.customHeight.setMaximumSize(QtCore.QSize(45, 16777215)) self.customHeight.setMaximumSize(QtCore.QSize(45, 16777215))
font = QtGui.QFont() font = QtGui.QFont()
font.setFamily("Lucida Grande")
font.setPointSize(12) font.setPointSize(12)
self.customHeight.setFont(font) self.customHeight.setFont(font)
self.customHeight.setFocusPolicy(QtCore.Qt.ClickFocus) self.customHeight.setFocusPolicy(QtCore.Qt.ClickFocus)
self.customHeight.setAcceptDrops(False) self.customHeight.setAcceptDrops(False)
self.customHeight.setMaxLength(4) self.customHeight.setMaxLength(4)
self.customHeight.setObjectName(_fromUtf8("customHeight")) self.customHeight.setObjectName("customHeight")
self.gridLayout_2.addWidget(self.customHeight, 0, 3, 1, 1) self.gridLayout_2.addWidget(self.customHeight, 0, 3, 1, 1)
self.EditorButton = QtWidgets.QPushButton(self.Form)
self.EditorButton.setGeometry(QtCore.QRect(160, 10, 101, 41))
font = QtGui.QFont()
font.setFamily("Lucida Grande")
font.setPointSize(12)
self.EditorButton.setFont(font)
self.EditorButton.setFocusPolicy(QtCore.Qt.NoFocus)
icon5 = QtGui.QIcon()
icon5.addPixmap(QtGui.QPixmap(":/Other/icons/editor.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.EditorButton.setIcon(icon5)
self.EditorButton.setObjectName("EditorButton")
KCC.setCentralWidget(self.Form) KCC.setCentralWidget(self.Form)
self.ActionBasic = QtGui.QAction(KCC) self.statusBar = QtWidgets.QStatusBar(KCC)
font = QtGui.QFont()
font.setFamily("Aharoni")
font.setPointSize(8)
self.statusBar.setFont(font)
self.statusBar.setSizeGripEnabled(False)
self.statusBar.setObjectName("statusBar")
KCC.setStatusBar(self.statusBar)
self.ActionBasic = QtWidgets.QAction(KCC)
self.ActionBasic.setCheckable(True) self.ActionBasic.setCheckable(True)
self.ActionBasic.setChecked(False) self.ActionBasic.setChecked(False)
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(9) font.setPointSize(9)
self.ActionBasic.setFont(font) self.ActionBasic.setFont(font)
self.ActionBasic.setObjectName(_fromUtf8("ActionBasic")) self.ActionBasic.setObjectName("ActionBasic")
self.ActionAdvanced = QtGui.QAction(KCC) self.ActionAdvanced = QtWidgets.QAction(KCC)
self.ActionAdvanced.setCheckable(True) self.ActionAdvanced.setCheckable(True)
self.ActionAdvanced.setObjectName(_fromUtf8("ActionAdvanced")) self.ActionAdvanced.setObjectName("ActionAdvanced")
self.retranslateUi(KCC) self.retranslateUi(KCC)
QtCore.QMetaObject.connectSlotsByName(KCC) QtCore.QMetaObject.connectSlotsByName(KCC)
@@ -318,47 +359,50 @@ class Ui_KCC(object):
KCC.setTabOrder(self.ConvertButton, self.ClearButton) KCC.setTabOrder(self.ConvertButton, self.ClearButton)
def retranslateUi(self, KCC): def retranslateUi(self, KCC):
KCC.setWindowTitle(_translate("KCC", "Kindle Comic Converter", None)) _translate = QtCore.QCoreApplication.translate
self.ProcessingBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Disable image optimizations.</span></p></body></html>", None)) KCC.setWindowTitle(_translate("KCC", "Kindle Comic Converter"))
self.ProcessingBox.setText(_translate("KCC", "No optimisation", None)) self.ProcessingBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Disable image optimizations.<br/><span style=\" font-weight:600;\">Input images must be already resized.</span></p></body></html>"))
self.UpscaleBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Enable image upscaling.<br/>Aspect ratio will be preserved.</span></p></body></html>", None)) self.ProcessingBox.setText(_translate("KCC", "No optimisation"))
self.UpscaleBox.setText(_translate("KCC", "Upscale images", 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>"))
self.StretchBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Enable image stretching.<br/>Aspect ratio will be not preserved.</span></p></body></html>", None)) self.UpscaleBox.setText(_translate("KCC", "Stretch/Upscale"))
self.StretchBox.setText(_translate("KCC", "Stretch images", None)) self.WebtoonBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Enable special parsing mode for WebToons.</p></body></html>"))
self.NoDitheringBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Create PNG files instead JPEG.<br/></span><span style=\" font-size:12pt; font-weight:600;\">Only for non-Kindle devices!</span></p></body></html>", None)) self.WebtoonBox.setText(_translate("KCC", "Webtoon mode"))
self.NoDitheringBox.setText(_translate("KCC", "PNG output", None)) self.NoDitheringBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>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>"))
self.BorderBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Fill space around images with black color.</span></p></body></html>", None)) self.NoDitheringBox.setText(_translate("KCC", "PNG output"))
self.BorderBox.setText(_translate("KCC", "Black borders", 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>"))
self.NoRotateBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Disable splitting and rotation.</span></p></body></html>", None)) self.BorderBox.setText(_translate("KCC", "W/B margins"))
self.NoRotateBox.setText(_translate("KCC", "No split/rotate", None)) self.NoRotateBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Disable page splitting and rotation.</p></body></html>"))
self.DeviceBox.setToolTip(_translate("KCC", "Target device.", None)) self.NoRotateBox.setText(_translate("KCC", "No split/rotate"))
self.FormatBox.setToolTip(_translate("KCC", "Output format.", None)) self.DeviceBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Target device.</p></body></html>"))
self.ConvertButton.setText(_translate("KCC", "Convert", None)) self.FormatBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Output format.</p></body></html>"))
self.DirectoryButton.setText(_translate("KCC", "Add directory", None)) self.ConvertButton.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Shift+Click to select the output directory.</p></body></html>"))
self.FileButton.setText(_translate("KCC", "Add file", None)) self.ConvertButton.setText(_translate("KCC", "Convert"))
self.ClearButton.setText(_translate("KCC", "Clear list", None)) self.DirectoryButton.setToolTip(_translate("KCC", "<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.MangaBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Enable right-to-left reading.</span></p></body></html>", None)) self.DirectoryButton.setText(_translate("KCC", "Add directory"))
self.MangaBox.setText(_translate("KCC", "Manga mode", None)) self.FileButton.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Add CBR, CBZ, CB7 or PDF file to queue.</p></body></html>"))
self.QualityBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-weight:600; text-decoration: underline;\">Unchecked - Normal quality mode<br/></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-style:italic;\">Use it when Panel View support is not needed.</span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-weight:600; text-decoration: underline;\"><br/></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt;\">- Maximum quality when zoom is not enabled.<br/>- Poor quality when zoom is enabled.<br/>- Lowest file size.</span></p><p><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-weight:600; text-decoration: underline;\">Indeterminate - High quality mode<br/></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-style:italic;\">Not zoomed image </span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-weight:600; font-style:italic;\">might </span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-style:italic;\">be a little blurry.</span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-weight:600; text-decoration: underline;\"><br/></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt;\">- Medium/High quality when zoom is not enabled.<br/>- Maximum quality when zoom is enabled.</span></p><p><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-weight:600; text-decoration: underline;\">Checked - Ultra quality mode<br/></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-style:italic;\">Maximum possible quality.</span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-weight:600; text-decoration: underline;\"><br/></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt;\">- 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.FileButton.setText(_translate("KCC", "Add file"))
self.QualityBox.setText(_translate("KCC", "High/Ultra quality", None)) self.ClearButton.setText(_translate("KCC", "Clear list"))
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.MangaBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Enable right-to-left reading.</p></body></html>"))
self.RotateBox.setText(_translate("KCC", "Horizontal mode", None)) self.MangaBox.setText(_translate("KCC", "Manga mode"))
self.BasicModeButton.setText(_translate("KCC", "Basic", None)) self.QualityBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Quality of Panel View/zoom. Highly impact size of output file.<br/><span style=\" font-weight:600;\">This option control only quality of magnification!</span></p></body></html>"))
self.AdvModeButton.setText(_translate("KCC", "Advanced", None)) self.QualityBox.setText(_translate("KCC", "High/Ultra quality"))
self.GammaLabel.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">When converting color images setting this option to 1.0 MIGHT improve readability.</span></p></body></html>", None)) self.RotateBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Disable splitting of two-page spreads.<br/>They will be rotated instead.</p></body></html>"))
self.GammaLabel.setText(_translate("KCC", "Gamma: Auto", None)) self.RotateBox.setText(_translate("KCC", "Horizontal mode"))
self.GammaSlider.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">When converting color images setting this option to 1.0 </span><span style=\" font-size:12pt; font-weight:600;\">might</span><span style=\" font-size:12pt;\"> improve readability.</span></p></body></html>", None)) self.BasicModeButton.setText(_translate("KCC", "Basic"))
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.AdvModeButton.setText(_translate("KCC", "Advanced"))
self.ColorBox.setText(_translate("KCC", "Color mode", None)) self.GammaLabel.setText(_translate("KCC", "Gamma: Auto"))
self.wLabel.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Resolution of target device.</span></p></body></html>", None)) self.ColorBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Don\'t convert images to grayscale.</p></body></html>"))
self.wLabel.setText(_translate("KCC", "Custom width: ", None)) self.ColorBox.setText(_translate("KCC", "Color mode"))
self.customWidth.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Resolution of target device.</span></p></body></html>", None)) self.wLabel.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Resolution of target device.</p></body></html>"))
self.customWidth.setInputMask(_translate("KCC", "0000; ", None)) self.wLabel.setText(_translate("KCC", "Custom width: "))
self.hLabel.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Resolution of target device.</span></p></body></html>", None)) self.customWidth.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Resolution of target device.</p></body></html>"))
self.hLabel.setText(_translate("KCC", "Custom height: ", None)) self.customWidth.setInputMask(_translate("KCC", "0000"))
self.customHeight.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Resolution of target device.</span></p></body></html>", None)) self.hLabel.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Resolution of target device.</p></body></html>"))
self.customHeight.setInputMask(_translate("KCC", "0000; ", None)) self.hLabel.setText(_translate("KCC", "Custom height: "))
self.ActionBasic.setText(_translate("KCC", "Basic", None)) self.customHeight.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Resolution of target device.</p></body></html>"))
self.ActionAdvanced.setText(_translate("KCC", "Advanced", None)) self.customHeight.setInputMask(_translate("KCC", "0000"))
self.EditorButton.setText(_translate("KCC", "Editor"))
self.ActionBasic.setText(_translate("KCC", "Basic"))
self.ActionAdvanced.setText(_translate("KCC", "Advanced"))
import KCC_rc from . import KCC_rc

View File

@@ -1,4 +1,4 @@
__version__ = '3.0' __version__ = '4.5.1'
__license__ = 'ISC' __license__ = 'ISC'
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>' __copyright__ = '2012-2015, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'

View File

@@ -1,4 +1,5 @@
# Copyright (c) 2012 Ciro Mattia Gonano <ciromattia@gmail.com> # Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
# Copyright (c) 2013-2015 Pawel Jastrzebski <pawelj@iosphe.re>
# #
# Permission to use, copy, modify, and/or distribute this software for # Permission to use, copy, modify, and/or distribute this software for
# any purpose with or without fee is hereby granted, provided that the # any purpose with or without fee is hereby granted, provided that the
@@ -14,23 +15,27 @@
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE. # PERFORMANCE OF THIS SOFTWARE.
# #
__license__ = 'ISC'
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
__docformat__ = 'restructuredtext en'
import sys
import os import os
import zipfile from zipfile import is_zipfile, ZipFile
import rarfile from subprocess import STDOUT, PIPE
from psutil import Popen
from shutil import move, copy
from scandir import walk
from . import rarfile
from .shared import check7ZFile as is_7zfile, saferReplace
# noinspection PyBroadException
class CBxArchive: class CBxArchive:
def __init__(self, origFileName): def __init__(self, origFileName):
self.origFileName = origFileName self.origFileName = origFileName
if zipfile.is_zipfile(origFileName): if is_zipfile(origFileName):
self.compressor = 'zip' self.compressor = 'zip'
elif rarfile.is_rarfile(origFileName): elif rarfile.is_rarfile(origFileName):
self.compressor = 'rar' self.compressor = 'rar'
elif is_7zfile(origFileName):
self.compressor = '7z'
else: else:
self.compressor = None self.compressor = None
@@ -38,15 +43,15 @@ class CBxArchive:
return self.compressor is not None return self.compressor is not None
def extractCBZ(self, targetdir): def extractCBZ(self, targetdir):
cbzFile = zipfile.ZipFile(self.origFileName) cbzFile = ZipFile(self.origFileName)
filelist = [] filelist = []
for f in cbzFile.namelist(): for f in cbzFile.namelist():
if f.startswith('__MACOSX') or f.endswith('.DS_Store') or f.endswith('thumbs.db'): if f.startswith('__MACOSX') or f.endswith('.DS_Store') or f.endswith('humbs.db'):
pass # skip MacOS special files pass # skip MacOS special files
elif f.endswith('/'): elif f.endswith('/'):
try: try:
os.makedirs(os.path.join(targetdir, f)) os.makedirs(os.path.join(targetdir, f))
except: except Exception:
pass # the dir exists so we are going to extract the images only. pass # the dir exists so we are going to extract the images only.
else: else:
filelist.append(f) filelist.append(f)
@@ -54,29 +59,44 @@ class CBxArchive:
def extractCBR(self, targetdir): def extractCBR(self, targetdir):
cbrFile = rarfile.RarFile(self.origFileName) cbrFile = rarfile.RarFile(self.origFileName)
filelist = [] cbrFile.extractall(targetdir)
for f in cbrFile.namelist(): for root, dirnames, filenames in walk(targetdir):
if f.startswith('__MACOSX') or f.endswith('.DS_Store') or f.endswith('thumbs.db'): for filename in filenames:
pass # skip MacOS special files if filename.startswith('__MACOSX') or filename.endswith('.DS_Store') or filename.endswith('humbs.db'):
elif f.endswith('/'): os.remove(os.path.join(root, filename))
try:
os.makedirs(os.path.join(targetdir, f)) def extractCB7(self, targetdir):
except: # Workaround for some wide UTF-8 + Popen abnormalities
pass # the dir exists so we are going to extract the images only. if sys.platform.startswith('darwin'):
else: copy(self.origFileName, os.path.join(os.path.dirname(self.origFileName), 'TMP_KCC_TMP'))
filelist.append(f) self.origFileName = os.path.join(os.path.dirname(self.origFileName), 'TMP_KCC_TMP')
cbrFile.extractall(targetdir, filelist) output = Popen('7za x "' + self.origFileName + '" -xr!__MACOSX -xr!.DS_Store -xr!thumbs.db -xr!Thumbs.db -o"'
+ targetdir + '"', stdout=PIPE, stderr=STDOUT, shell=True)
extracted = False
for line in output.stdout:
if b"Everything is Ok" in line:
extracted = True
if sys.platform.startswith('darwin'):
os.remove(self.origFileName)
if not extracted:
raise OSError
def extract(self, targetdir): def extract(self, targetdir):
print "\n" + targetdir + "\n"
if self.compressor == 'rar': if self.compressor == 'rar':
self.extractCBR(targetdir) self.extractCBR(targetdir)
elif self.compressor == 'zip': elif self.compressor == 'zip':
self.extractCBZ(targetdir) self.extractCBZ(targetdir)
elif self.compressor == '7z':
self.extractCB7(targetdir)
adir = os.listdir(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])): if len(adir) == 1 and os.path.isdir(os.path.join(targetdir, adir[0])):
import shutil
for f in os.listdir(os.path.join(targetdir, adir[0])): for f in os.listdir(os.path.join(targetdir, adir[0])):
shutil.move(os.path.join(targetdir, adir[0], f), targetdir) # If directory names contain UTF-8 chars shutil.move can't clean up the mess alone
if os.path.isdir(os.path.join(targetdir, f)):
saferReplace(os.path.join(targetdir, adir[0], f), os.path.join(targetdir, adir[0], f + '-A'))
f += '-A'
move(os.path.join(targetdir, adir[0], f), targetdir)
os.rmdir(os.path.join(targetdir, adir[0])) os.rmdir(os.path.join(targetdir, adir[0]))
return targetdir return targetdir

File diff suppressed because it is too large Load Diff

300
kcc/comic2panel.py Normal file
View File

@@ -0,0 +1,300 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
# Copyright (c) 2013-2015 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, ImageStat, ImageOps
from scandir import walk
from .shared import getImageFileName, walkLevel, walkSort
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, dirs, 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)
img = img.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])
def sanitizePanelSize(panel, opt):
newPanels = []
if panel[2] > 6 * opt.height:
diff = int(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] > 3 * opt.height:
diff = int(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] > 1.5 * opt.height:
newPanels.append([panel[0], panel[1] - int(panel[2] / 2), int(panel[2] / 2)])
newPanels.append([panel[1] - int(panel[2] / 2), panel[1], int(panel[2] / 2)])
else:
newPanels = [panel]
return newPanels
def splitImageTick(output):
if output:
splitWorkerOutput.append(output)
splitWorkerPool.terminate()
if GUI:
GUI.progressBarTick.emit('tick')
if not GUI.conversionAlive:
splitWorkerPool.terminate()
def splitImage(work):
try:
path = work[0]
name = work[1]
opt = work[2]
# Hardcoded options
threshold = 1.0
delta = 15
fileExpanded = os.path.splitext(name)
filePath = os.path.join(path, name)
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:
# noinspection PyUnboundLocalVariable
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 Exception:
return str(sys.exc_info()[1])
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 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"
if os.path.isdir(options.sourceDir):
rmtree(options.targetDir, True)
copytree(options.sourceDir, options.targetDir)
work = []
pagenumber = 1
splitWorkerOutput = []
splitWorkerPool = Pool()
if options.merge:
print("\nMerging images...")
directoryNumer = 1
mergeWork = []
mergeWorkerOutput = []
mergeWorkerPool = Pool()
mergeWork.append([options.targetDir])
for root, dirs, files in 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])
print("\nSplitting images...")
for root, dirs, files in 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])
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.")

184
kcc/dualmetafix.py Normal file
View File

@@ -0,0 +1,184 @@
# -*- coding: utf-8 -*-
#
# Based on initial version of DualMetaFix. Copyright (C) 2013 Kevin Hendricks
# Changes for KCC Copyright (C) 2014-2015 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()

View File

@@ -1,6 +1,7 @@
# Copyright (C) 2010 Alex Yatskov # Copyright (C) 2010 Alex Yatskov
# Copyright (C) 2011 Stanislav (proDOOMman) Kosolapov <prodoomman@gmail.com> # Copyright (C) 2011 Stanislav (proDOOMman) Kosolapov <prodoomman@gmail.com>
# Copyright (C) 2012-2013 Ciro Mattia Gonano <ciromattia@gmail.com> # Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
# Copyright (c) 2013-2015 Pawel Jastrzebski <pawelj@iosphe.re>
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@@ -15,20 +16,20 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # 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 import os
try: from io import BytesIO
# noinspection PyUnresolvedReferences from urllib.request import Request, urlopen
from PIL import Image, ImageOps, ImageStat, ImageChops from urllib.parse import quote
except ImportError: from functools import reduce
print "ERROR: Pillow is not installed!" from PIL import Image, ImageOps, ImageStat, ImageChops
exit(1) from .shared import md5Checksum
from . import __version__
class ProfileData: class ProfileData:
def __init__(self):
pass
Palette4 = [ Palette4 = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
@@ -73,175 +74,242 @@ class ProfileData:
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
] ]
Profiles = { PalleteNull = [
'K1': ("Kindle 1", (600, 800), Palette4, 1.8, (900, 1200)), ]
'K2': ("Kindle 2", (600, 800), Palette15, 1.8, (900, 1200)),
'K3': ("Kindle Keyboard", (600, 800), Palette16, 1.8, (900, 1200)),
'K4NT': ("Kindle Non-Touch", (600, 800), Palette16, 1.8, (900, 1200)),
'K4T': ("Kindle Touch", (600, 800), Palette16, 1.8, (900, 1200)),
'KHD': ("Kindle Paperwhite", (758, 1024), Palette16, 1.8, (1137, 1536)),
'KDX': ("Kindle DX", (824, 1200), Palette15, 1.8, (1236, 1800)),
'KDXG': ("Kindle DXG", (824, 1200), Palette16, 1.8, (1236, 1800)),
'KF': ("Kindle Fire", (600, 1024), Palette16, 1.0, (900, 1536)),
'KFHD': ("Kindle Fire HD 7\"", (800, 1280), Palette16, 1.0, (1200, 1920)),
'KFHD8': ("Kindle Fire HD 8.9\"", (1200, 1920), Palette16, 1.0, (1800, 2880)),
'OTHER': ("Other", (0, 0), Palette16, 1.8, (0, 0)),
}
ProfileLabels = { Profiles = {
"Kindle 1": 'K1', 'K1': ("Kindle 1", (600, 670), Palette4, 1.8, (900, 1005)),
"Kindle 2": 'K2', 'K2': ("Kindle 2", (600, 670), Palette15, 1.8, (900, 1005)),
"Kindle 3/Keyboard": 'K3', 'K345': ("Kindle", (600, 800), Palette16, 1.8, (900, 1200)),
"Kindle 4/Non-Touch": 'K4NT', 'KDX': ("Kindle DX/DXG", (824, 1000), Palette16, 1.8, (1236, 1500)),
"Kindle 4/Touch": 'K4T', 'KPW': ("Kindle Paperwhite", (758, 1024), Palette16, 1.8, (1137, 1536)),
"Kindle Paperwhite": 'KHD', 'KV': ("Kindle Voyage", (1072, 1448), Palette16, 1.8, (1608, 2172)),
"Kindle DX": 'KDX', 'KFHD': ("K. Fire HD", (800, 1280), PalleteNull, 1.0, (1200, 1920)),
"Kindle DXG": 'KDXG', 'KFHDX': ("K. Fire HDX", (1200, 1920), PalleteNull, 1.0, (1800, 2880)),
"Kindle Fire": 'KF', 'KFHDX8': ("K. Fire HDX 8.9", (1600, 2560), PalleteNull, 1.0, (2400, 3840)),
"Kindle Fire HD 7\"": 'KFHD', 'KFA': ("Kindle for Android", (0, 0), PalleteNull, 1.0, (0, 0)),
"Kindle Fire HD 8.9\"": 'KFHD8', 'KoMT': ("Kobo Mini/Touch", (600, 800), Palette16, 1.8, (900, 1200)),
"Other": 'OTHER' 'KoG': ("Kobo Glo", (768, 1024), Palette16, 1.8, (1152, 1536)),
'KoGHD': ("Kobo Glo HD", (1072, 1448), Palette16, 1.8, (1608, 2172)),
'KoA': ("Kobo Aura", (758, 1024), Palette16, 1.8, (1137, 1536)),
'KoAHD': ("Kobo Aura HD", (1080, 1440), Palette16, 1.8, (1620, 2160)),
'KoAH2O': ("Kobo Aura H2O", (1080, 1430), Palette16, 1.8, (1620, 2145)),
'OTHER': ("Other", (0, 0), Palette16, 1.8, (0, 0)),
} }
class ComicPage: class ComicPage:
def __init__(self, source, device): def __init__(self, source, options, original=None):
try: try:
self.profile_label, self.size, self.palette, self.gamma, self.panelviewsize = device self.profile_label, self.size, self.palette, self.gamma, self.panelviewsize = options.profileData
except KeyError: except KeyError:
raise RuntimeError('Unexpected output device %s' % device) raise RuntimeError('Unexpected output device %s' % options.profileData)
# Detect corrupted files - Phase 2 self.origFileName = source
try: self.filename = os.path.basename(self.origFileName)
self.origFileName = source
self.image = Image.open(source)
except IOError:
raise RuntimeError('Cannot read image file %s' % source)
# Detect corrupted files - Phase 3
try:
self.image.verify()
except:
raise RuntimeError('Image file %s is corrupted' % source)
self.image = Image.open(source) self.image = Image.open(source)
self.image = self.image.convert('RGB') self.image = self.image.convert('RGB')
self.opt = options
if original:
self.second = True
self.rotated = original.rotated
self.border = original.border
self.noHPV = original.noHPV
self.noVPV = original.noVPV
self.noPV = original.noPV
self.noHQ = original.noHQ
self.fill = original.fill
self.color = original.color
if self.rotated:
self.image = self.image.rotate(90, Image.BICUBIC, True)
self.opt.quality = 0
else:
self.second = False
self.rotated = None
self.border = None
self.noHPV = None
self.noVPV = None
self.noPV = None
self.fill = None
self.noHQ = False
if options.webtoon:
self.color = True
else:
self.color = self.isImageColor()
def saveToDir(self, targetdir, forcepng, color, wipe, suffix=None): def saveToDir(self, targetdir):
filename = os.path.basename(self.origFileName)
try: try:
if not color: flags = []
self.image = self.image.convert('L') # convert to grayscale filename = os.path.join(targetdir, os.path.splitext(self.filename)[0]) + '-KCC'
if suffix == "R": if not self.opt.forcecolor and not self.opt.forcepng:
suffix = "_kccrotated" self.image = self.image.convert('L')
if self.rotated:
flags.append('Rotated')
if self.noPV:
flags.append('NoPanelView')
else: else:
suffix = "" if self.noHPV:
if wipe: flags.append('NoHorizontalPanelView')
os.remove(os.path.join(targetdir, filename)) if self.noVPV:
flags.append('NoVerticalPanelView')
if self.border:
flags.append('Margins-' + str(self.border[0]) + '-' + str(self.border[1]) + '-'
+ str(self.border[2]) + '-' + str(self.border[3]))
if self.fill != 'white':
flags.append('BlackFill')
if self.opt.quality == 2:
filename += '-HQ'
if self.opt.forcepng:
filename += '.png'
self.image.save(filename, 'PNG', optimize=1)
else: else:
suffix += "_kcchq" filename += '.jpg'
if forcepng: self.image.save(filename, 'JPEG', optimize=1, quality=80)
self.image.save(os.path.join(targetdir, os.path.splitext(filename)[0] + suffix + ".png"), "PNG") return [md5Checksum(filename), flags]
else:
self.image.save(os.path.join(targetdir, os.path.splitext(filename)[0] + suffix + ".jpg"), "JPEG")
except IOError as e: except IOError as e:
raise RuntimeError('Cannot write image in directory %s: %s' % (targetdir, e)) raise RuntimeError('Cannot write image in directory %s: %s' % (targetdir, e))
def optimizeImage(self, gamma): def autocontrastImage(self):
gamma = self.opt.gamma
if gamma < 0.1: if gamma < 0.1:
gamma = self.gamma gamma = self.gamma
if self.gamma != 1.0 and self.color:
gamma = 1.0
if gamma == 1.0: if gamma == 1.0:
self.image = ImageOps.autocontrast(self.image) self.image = ImageOps.autocontrast(self.image)
else: else:
self.image = ImageOps.autocontrast(Image.eval(self.image, lambda a: 255 * (a / 255.) ** gamma)) self.image = ImageOps.autocontrast(Image.eval(self.image, lambda a: 255 * (a / 255.) ** gamma))
def quantizeImage(self): def quantizeImage(self):
self.image = self.image.convert('L') # convert to grayscale colors = len(self.palette) // 3
self.image = self.image.convert("RGB") # convert back to RGB
colors = len(self.palette) / 3
if colors < 256: if colors < 256:
self.palette += self.palette[:3] * (256 - colors) self.palette += self.palette[:3] * (256 - colors)
palImg = Image.new('P', (1, 1)) palImg = Image.new('P', (1, 1))
palImg.putpalette(self.palette) 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) self.image = self.image.quantize(palette=palImg)
def resizeImage(self, upscale=False, stretch=False, black_borders=False, isSplit=False, toRight=False, def calculateBorder(self):
landscapeMode=False, qualityMode=0): if self.noPV:
method = Image.ANTIALIAS self.border = [0.0, 0.0, 0.0, 0.0]
if black_borders: return
fill = 'black' if self.fill == 'white':
border = ImageChops.invert(self.image).getbbox()
else: else:
fill = 'white' border = self.image.getbbox()
if qualityMode == 0: if self.opt.quality == 2:
multiplier = 1.0
else:
multiplier = 1.5
if border is not None:
self.border = [round(float(border[0])/float(self.image.size[0])*150, 3),
round(float(border[1])/float(self.image.size[1])*150, 3),
round(float(self.image.size[0]-border[2])/float(self.image.size[0])*150, 3),
round(float(self.image.size[1]-border[3])/float(self.image.size[1])*150, 3)]
if int((border[2] - border[0]) * multiplier) < self.size[0] + 10:
self.noHPV = True
if int((border[3] - border[1]) * multiplier) < self.size[1] + 10:
self.noVPV = True
else:
self.border = [0.0, 0.0, 0.0, 0.0]
self.noHPV = True
self.noVPV = True
def resizeImage(self):
if self.opt.bordersColor:
fill = self.opt.bordersColor
else:
fill = self.fill
# Set target size
if self.opt.quality == 0:
size = (self.size[0], self.size[1]) size = (self.size[0], self.size[1])
elif self.opt.quality == 1 and not self.opt.stretch and not self.opt.upscale and self.image.size[0] <=\
self.size[0] and self.image.size[1] <= self.size[1]:
size = (self.size[0], self.size[1])
elif self.opt.quality == 1:
# Forcing upscale to make sure that margins will be not too big
if not self.opt.stretch:
self.opt.upscale = True
size = (self.panelviewsize[0], self.panelviewsize[1])
elif self.opt.quality == 2 and not self.opt.stretch and not self.opt.upscale and self.image.size[0] <=\
self.size[0] and self.image.size[1] <= self.size[1]:
# HQ version will not be needed
self.noHQ = True
return
else: else:
size = (self.panelviewsize[0], self.panelviewsize[1]) size = (self.panelviewsize[0], self.panelviewsize[1])
# Kindle Paperwhite/Touch - Force upscale of splited pages to increase readability # If stretching is on - Resize without other considerations
if isSplit and landscapeMode: if self.opt.stretch:
upscale = True if self.image.size[0] <= size[0] and self.image.size[1] <= size[1]:
if self.image.size[0] <= self.size[0] and self.image.size[1] <= self.size[1]: method = Image.BICUBIC
if 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
else: else:
method = Image.BILINEAR method = Image.LANCZOS
if stretch: # if stretching call directly resize() without other considerations.
self.image = self.image.resize(size, method) self.image = self.image.resize(size, method)
return self.image return
ratioDev = float(self.size[0]) / float(self.size[1]) # If image is smaller than target resolution and upscale is off - Just expand it by adding margins
if self.image.size[0] <= size[0] and self.image.size[1] <= size[1] and not self.opt.upscale:
borderw = int((size[0] - self.image.size[0]) / 2)
borderh = int((size[1] - self.image.size[1]) / 2)
# PV is disabled when source image is smaller than device screen and upscale is off
if self.image.size[0] <= self.size[0] and self.image.size[1] <= self.size[1]:
self.noPV = True
self.image = ImageOps.expand(self.image, border=(borderw, borderh), fill=fill)
# Border can't be float so sometimes image might be 1px too small/large
if self.image.size[0] != size[0] or self.image.size[1] != size[1]:
self.image = ImageOps.fit(self.image, size, method=Image.BICUBIC, centering=(0.5, 0.5))
return
# Otherwise - Upscale/Downscale
ratioDev = float(size[0]) / float(size[1])
if (float(self.image.size[0]) / float(self.image.size[1])) < ratioDev: if (float(self.image.size[0]) / float(self.image.size[1])) < ratioDev:
if isSplit and landscapeMode: diff = int(self.image.size[1] * ratioDev) - self.image.size[0]
diff = int(self.image.size[1] * ratioDev) - self.image.size[0] self.image = ImageOps.expand(self.image, border=(int(diff / 2), 0), fill=fill)
self.image = ImageOps.expand(self.image, border=(diff / 2, 0), fill=fill)
tempImg = Image.new(self.image.mode, (self.image.size[0] + diff, self.image.size[1]), fill)
if toRight:
tempImg.paste(self.image, (diff, 0))
else:
tempImg.paste(self.image, (0, 0))
self.image = tempImg
else:
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: elif (float(self.image.size[0]) / float(self.image.size[1])) > ratioDev:
diff = int(self.image.size[0] / ratioDev) - self.image.size[1] diff = int(self.image.size[0] / ratioDev) - self.image.size[1]
self.image = ImageOps.expand(self.image, border=(0, diff / 2), fill=fill) self.image = ImageOps.expand(self.image, border=(0, int(diff / 2)), fill=fill)
if self.image.size[0] <= size[0] and self.image.size[1] <= size[1]:
method = Image.BICUBIC
else:
method = Image.LANCZOS
self.image = ImageOps.fit(self.image, size, method=method, centering=(0.5, 0.5)) self.image = ImageOps.fit(self.image, size, method=method, centering=(0.5, 0.5))
return self.image return
def splitPage(self, targetdir, righttoleft=False, rotate=False): def splitPage(self, targetdir):
width, height = self.image.size width, height = self.image.size
dstwidth, dstheight = self.size dstwidth, dstheight = self.size
#print "Image is %d x %d" % (width,height) # Only split if origin is not oriented the same as target
# only split if origin is not oriented the same as target
if (width > height) != (dstwidth > dstheight): if (width > height) != (dstwidth > dstheight):
if rotate: if self.opt.rotate:
self.image = self.image.rotate(90) self.image = self.image.rotate(90, Image.BICUBIC, True)
return "R" self.rotated = True
return None
else: else:
self.rotated = False
if width > height: if width > height:
# source is landscape, so split by the width # Source is landscape, so split by the width
leftbox = (0, 0, width / 2, height) leftbox = (0, 0, int(width / 2), height)
rightbox = (width / 2, 0, width, height) rightbox = (int(width / 2), 0, width, height)
else: else:
# source is portrait and target is landscape, so split by the height # Source is portrait and target is landscape, so split by the height
leftbox = (0, 0, width, height / 2) leftbox = (0, 0, width, int(height / 2))
rightbox = (0, height / 2, width, height) rightbox = (0, int(height / 2), width, height)
filename = os.path.splitext(os.path.basename(self.origFileName)) filename = os.path.splitext(self.filename)[0]
fileone = targetdir + '/' + filename[0] + '_kcca' + filename[1] fileone = targetdir + '/' + filename + '-AAA.png'
filetwo = targetdir + '/' + filename[0] + '_kccb' + filename[1] filetwo = targetdir + '/' + filename + '-BBB.png'
try: try:
if righttoleft: if self.opt.righttoleft:
pageone = self.image.crop(rightbox) pageone = self.image.crop(rightbox)
pagetwo = self.image.crop(leftbox) pagetwo = self.image.crop(leftbox)
else: else:
pageone = self.image.crop(leftbox) pageone = self.image.crop(leftbox)
pagetwo = self.image.crop(rightbox) pagetwo = self.image.crop(rightbox)
pageone.save(fileone) pageone.save(fileone, 'PNG', optimize=1)
pagetwo.save(filetwo) pagetwo.save(filetwo, 'PNG', optimize=1)
os.remove(self.origFileName)
except IOError as e: except IOError as e:
raise RuntimeError('Cannot write image in directory %s: %s' % (targetdir, e)) raise RuntimeError('Cannot write image in directory %s: %s' % (targetdir, e))
return fileone, filetwo return fileone, filetwo
else: else:
self.rotated = False
return None return None
def cutPageNumber(self): def cutPageNumber(self):
@@ -262,7 +330,7 @@ class ComicPage:
oldStat = ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg))).var[0] oldStat = ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg))).var[0]
diff += delta diff += delta
while ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg))).var[0] - oldStat > 0\ while ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg))).var[0] - oldStat > 0\
and diff < heightImg / 4: and diff < heightImg // 4:
oldStat = ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg))).var[0] oldStat = ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg))).var[0]
diff += delta diff += delta
diff -= delta diff -= delta
@@ -271,7 +339,7 @@ class ComicPage:
oldStat = ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, oldStat = ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg,
heightImg - pageNumberCut2))).var[0] heightImg - pageNumberCut2))).var[0]
while 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: < fixedThreshold + oldStat and diff < heightImg // 4:
diff += delta diff += delta
diff -= delta diff -= delta
pageNumberCut3 = diff pageNumberCut3 = diff
@@ -297,44 +365,156 @@ class ComicPage:
else: else:
diff = pageNumberCut1 diff = pageNumberCut1
self.image = self.image.crop((0, 0, widthImg, heightImg - diff)) self.image = self.image.crop((0, 0, widthImg, heightImg - diff))
return self.image
def cropWhiteSpace(self, threshold): def cropWhiteSpace(self):
if ImageChops.invert(self.image).getbbox() is not None: if ImageChops.invert(self.image).getbbox() is not None:
widthImg, heightImg = self.image.size widthImg, heightImg = self.image.size
delta = 10 delta = 10
diff = delta diff = delta
fixedThreshold = 0.1
# top # top
while ImageStat.Stat(self.image.crop((0, 0, widthImg, diff))).var[0] < threshold and diff < heightImg: while ImageStat.Stat(self.image.crop((0, 0, widthImg, diff))).var[0] < fixedThreshold and diff < heightImg:
diff += delta diff += delta
diff -= delta diff -= delta
# print "Top crop: %s"%diff
self.image = self.image.crop((0, diff, widthImg, heightImg)) self.image = self.image.crop((0, diff, widthImg, heightImg))
widthImg, heightImg = self.image.size widthImg, heightImg = self.image.size
diff = delta diff = delta
# left # left
while ImageStat.Stat(self.image.crop((0, 0, diff, heightImg))).var[0] < threshold and diff < widthImg: while ImageStat.Stat(self.image.crop((0, 0, diff, heightImg))).var[0] < fixedThreshold and diff < widthImg:
diff += delta diff += delta
diff -= delta diff -= delta
# print "Left crop: %s"%diff
self.image = self.image.crop((diff, 0, widthImg, heightImg)) self.image = self.image.crop((diff, 0, widthImg, heightImg))
widthImg, heightImg = self.image.size widthImg, heightImg = self.image.size
diff = delta diff = delta
# down # down
while ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg))).var[0] < threshold\ while ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg))).var[0] < fixedThreshold\
and diff < heightImg: and diff < heightImg:
diff += delta diff += delta
diff -= delta diff -= delta
# print "Down crop: %s"%diff
self.image = self.image.crop((0, 0, widthImg, heightImg - diff)) self.image = self.image.crop((0, 0, widthImg, heightImg - diff))
widthImg, heightImg = self.image.size widthImg, heightImg = self.image.size
diff = delta diff = delta
# right # right
while ImageStat.Stat(self.image.crop((widthImg - diff, 0, widthImg, heightImg))).var[0] < threshold\ while ImageStat.Stat(self.image.crop((widthImg - diff, 0, widthImg, heightImg))).var[0] < fixedThreshold\
and diff < widthImg: and diff < widthImg:
diff += delta diff += delta
diff -= delta diff -= delta
# print "Right crop: %s"%diff
self.image = self.image.crop((0, 0, widthImg - diff, heightImg)) self.image = self.image.crop((0, 0, widthImg - diff, heightImg))
# print "New size: %sx%s"%(self.image.size[0],self.image.size[1])
return self.image def getImageHistogram(self, image):
histogram = image.histogram()
if histogram[0] == 0:
return -1
elif histogram[255] == 0:
return 1
else:
return 0
def getImageFill(self):
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:
self.fill = 'white'
elif surfaceW > surfaceB:
self.fill = '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:
self.fill = 'black'
else:
self.fill = 'white'
def isImageColor(self):
v = ImageStat.Stat(self.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
class Cover:
def __init__(self, source, target, opt, tomeNumber):
self.options = opt
self.source = source
self.target = target
if tomeNumber == 0:
self.tomeNumber = 1
else:
self.tomeNumber = tomeNumber
if self.tomeNumber in self.options.remoteCovers:
try:
source = urlopen(Request(quote(self.options.remoteCovers[self.tomeNumber]).replace('%3A', ':', 1),
headers={'User-Agent': 'KindleComicConverter/' + __version__})).read()
self.image = Image.open(BytesIO(source))
self.processExternal()
except Exception:
self.image = Image.open(source)
self.processInternal()
else:
self.image = Image.open(source)
self.processInternal()
def processInternal(self):
self.image = self.image.convert('RGB')
self.image = self.trim()
self.save()
def processExternal(self):
self.image = self.image.convert('RGB')
self.image.thumbnail(self.options.profileData[1], Image.LANCZOS)
self.save()
def trim(self):
bg = Image.new(self.image.mode, self.image.size, self.image.getpixel((0, 0)))
diff = ImageChops.difference(self.image, bg)
diff = ImageChops.add(diff, diff, 2.0, -100)
bbox = diff.getbbox()
if bbox:
return self.image.crop(bbox)
else:
return self.image
def save(self):
try:
self.image.save(self.target, "JPEG", optimize=1, quality=80)
except IOError:
raise RuntimeError('Failed to save cover')

View File

@@ -1,236 +0,0 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
#
# This is a python script. You need a Python interpreter to run it.
# For example, ActiveState Python, which exists for windows.
#
# This script strips the penultimate record from a Mobipocket file.
# This is useful because the current KindleGen add a compressed copy
# of the source files used in this record, making the ebook produced
# about twice as big as it needs to be.
#
#
# This is free and unencumbered software released into the public domain.
#
# Anyone is free to copy, modify, publish, use, compile, sell, or
# distribute this software, either in source code form or as a compiled
# binary, for any purpose, commercial or non-commercial, and by any
# means.
#
# In jurisdictions that recognize copyright laws, the author or authors
# of this software dedicate any and all copyright interest in the
# software to the public domain. We make this dedication for the benefit
# of the public at large and to the detriment of our heirs and
# successors. We intend this dedication to be an overt act of
# relinquishment in perpetuity of all present and future rights to this
# software under copyright law.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
#
# For more information, please refer to <http://unlicense.org/>
#
# Written by Paul Durrant, 2010-2011, paul@durrant.co.uk, pdurrant on mobileread.com
# With enhancements by Kevin Hendricks, KevinH on mobileread.com
#
# Changelog
# 1.00 - Initial version
# 1.10 - Added an option to output the stripped data
# 1.20 - Added check for source files section (thanks Piquan)
# 1.30 - Added prelim Support for K8 style mobis
# 1.31 - removed the SRCS section but kept a 0 size entry for it
# 1.32 - removes the SRCS section and its entry, now updates metadata 121 if needed
# 1.33 - now uses and modifies mobiheader SRCS and CNT
# 1.34 - added credit for Kevin Hendricks
# 1.35 - fixed bug when more than one compilation (SRCS/CMET) records
__version__ = '1.35'
import sys
import struct
import binascii
class Unbuffered:
def __init__(self, stream):
self.stream = stream
def write(self, data):
self.stream.write(data)
self.stream.flush()
def __getattr__(self, attr):
return getattr(self.stream, attr)
class StripException(Exception):
pass
class SectionStripper:
def loadSection(self, section):
if (section + 1 == self.num_sections):
endoff = len(self.data_file)
else:
endoff = self.sections[section + 1][0]
off = self.sections[section][0]
return self.data_file[off:endoff]
def patch(self, off, new):
self.data_file = self.data_file[:off] + new + self.data_file[off+len(new):]
def strip(self, off, len):
self.data_file = self.data_file[:off] + self.data_file[off+len:]
def patchSection(self, section, new, in_off = 0):
if (section + 1 == self.num_sections):
endoff = len(self.data_file)
else:
endoff = self.sections[section + 1][0]
off = self.sections[section][0]
assert off + in_off + len(new) <= endoff
self.patch(off + in_off, new)
def updateEXTH121(self, srcs_secnum, srcs_cnt, mobiheader):
mobi_length, = struct.unpack('>L',mobiheader[0x14:0x18])
exth_flag, = struct.unpack('>L', mobiheader[0x80:0x84])
exth = 'NONE'
try:
if exth_flag & 0x40:
exth = mobiheader[16 + mobi_length:]
if (len(exth) >= 4) and (exth[:4] == 'EXTH'):
nitems, = struct.unpack('>I', exth[8:12])
pos = 12
for i in xrange(nitems):
type, size = struct.unpack('>II', exth[pos: pos + 8])
# print type, size
if type == 121:
boundaryptr, =struct.unpack('>L',exth[pos+8: pos + size])
if srcs_secnum <= boundaryptr:
boundaryptr -= srcs_cnt
prefix = mobiheader[0:16 + mobi_length + pos + 8]
suffix = mobiheader[16 + mobi_length + pos + 8 + 4:]
nval = struct.pack('>L',boundaryptr)
mobiheader = prefix + nval + suffix
pos += size
except:
pass
return mobiheader
def __init__(self, datain):
if datain[0x3C:0x3C+8] != 'BOOKMOBI':
raise StripException("invalid file format")
self.num_sections, = struct.unpack('>H', datain[76:78])
# get mobiheader and check SRCS section number and count
offset0, = struct.unpack_from('>L', datain, 78)
offset1, = struct.unpack_from('>L', datain, 86)
mobiheader = datain[offset0:offset1]
srcs_secnum, srcs_cnt = struct.unpack_from('>2L', mobiheader, 0xe0)
if srcs_secnum == 0xffffffff or srcs_cnt == 0:
raise StripException("File doesn't contain the sources section.")
print "Found SRCS section number %d, and count %d" % (srcs_secnum, srcs_cnt)
# find its offset and length
next = srcs_secnum + srcs_cnt
srcs_offset, flgval = struct.unpack_from('>2L', datain, 78+(srcs_secnum*8))
next_offset, flgval = struct.unpack_from('>2L', datain, 78+(next*8))
srcs_length = next_offset - srcs_offset
if datain[srcs_offset:srcs_offset+4] != 'SRCS':
raise StripException("SRCS section num does not point to SRCS.")
print " beginning at offset %0x and ending at offset %0x" % (srcs_offset, srcs_length)
# it appears bytes 68-71 always contain (2*num_sections) + 1
# this is not documented anyplace at all but it appears to be some sort of next
# available unique_id used to identify specific sections in the palm db
self.data_file = datain[:68] + struct.pack('>L',((self.num_sections-srcs_cnt)*2+1))
self.data_file += datain[72:76]
# write out the number of sections reduced by srtcs_cnt
self.data_file = self.data_file + struct.pack('>H',self.num_sections-srcs_cnt)
# we are going to remove srcs_cnt SRCS sections so the offset of every entry in the table
# up to the srcs secnum must begin 8 bytes earlier per section removed (each table entry is 8 )
delta = -8 * srcs_cnt
for i in xrange(srcs_secnum):
offset, flgval = struct.unpack_from('>2L', datain, 78+(i*8))
offset += delta
self.data_file += struct.pack('>L',offset) + struct.pack('>L',flgval)
# for every record after the srcs_cnt SRCS records we must start it
# earlier by 8*srcs_cnt + the length of the srcs sections themselves)
delta = delta - srcs_length
for i in xrange(srcs_secnum+srcs_cnt,self.num_sections):
offset, flgval = struct.unpack_from('>2L', datain, 78+(i*8))
offset += delta
flgval = 2 * (i - srcs_cnt)
self.data_file += struct.pack('>L',offset) + struct.pack('>L',flgval)
# now pad it out to begin right at the first offset
# typically this is 2 bytes of nulls
first_offset, flgval = struct.unpack_from('>2L', self.data_file, 78)
self.data_file += '\0' * (first_offset - len(self.data_file))
# now finally add on every thing up to the original src_offset
self.data_file += datain[offset0: srcs_offset]
# and everything afterwards
self.data_file += datain[srcs_offset+srcs_length:]
#store away the SRCS section in case the user wants it output
self.stripped_data_header = datain[srcs_offset:srcs_offset+16]
self.stripped_data = datain[srcs_offset+16:srcs_offset+srcs_length]
# update the number of sections count
self.num_section = self.num_sections - srcs_cnt
# update the srcs_secnum and srcs_cnt in the mobiheader
offset0, flgval0 = struct.unpack_from('>2L', self.data_file, 78)
offset1, flgval1 = struct.unpack_from('>2L', self.data_file, 86)
mobiheader = self.data_file[offset0:offset1]
mobiheader = mobiheader[:0xe0]+ struct.pack('>L', 0xffffffff) + struct.pack('>L', 0) + mobiheader[0xe8:]
# if K8 mobi, handle metadata 121 in old mobiheader
mobiheader = self.updateEXTH121(srcs_secnum, srcs_cnt, mobiheader)
self.data_file = self.data_file[0:offset0] + mobiheader + self.data_file[offset1:]
print "done"
def getResult(self):
return self.data_file
def getStrippedData(self):
return self.stripped_data
def getHeader(self):
return self.stripped_data_header
def main(argv=None):
infile = argv[0]
outfile = argv[1]
data_file = file(infile, 'rb').read()
try:
strippedFile = SectionStripper(data_file)
file(outfile, 'wb').write(strippedFile.getResult())
print "Header Bytes: " + binascii.b2a_hex(strippedFile.getHeader())
if len(argv)==3:
file(argv[2], 'wb').write(strippedFile.getStrippedData())
except StripException, e:
print "Error: %s" % e
sys.exit(1)
if __name__ == "__main__":
sys.stdout=Unbuffered(sys.stdout)
print ('KindleStrip v%(__version__)s. '
'Written 2010-2012 by Paul Durrant and Kevin Hendricks.' % globals())
if len(sys.argv)<3 or len(sys.argv)>4:
print "Strips the Sources record from Mobipocket ebooks"
print "For ebooks generated using KindleGen 1.1 and later that add the source"
print "Usage:"
print " %s <infile> <outfile> <strippeddatafile>" % sys.argv[0]
print "<strippeddatafile> is optional."
sys.exit(1)
else:
main(sys.argv[1:])
sys.exit(0)

169
kcc/metadata.py Normal file
View File

@@ -0,0 +1,169 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2013-2015 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 re import compile
from zipfile import is_zipfile, ZipFile, ZIP_DEFLATED
from subprocess import STDOUT, PIPE
from psutil import Popen
from tempfile import mkdtemp
from shutil import rmtree
from .shared import removeFromZIP, check7ZFile as is_7zfile
from . import rarfile
class MetadataParser:
def __init__(self, source):
self.source = source
self.data = {'Series': '',
'Volume': '',
'Number': '',
'Writers': [],
'Pencillers': [],
'Inkers': [],
'Colorists': [],
'MUid': '',
'Bookmarks': []}
self.rawdata = None
self.compressor = None
if self.source.endswith('.xml'):
self.rawdata = parse(self.source)
self.parseXML()
else:
if is_zipfile(self.source):
self.compressor = 'zip'
with ZipFile(self.source) as zip_file:
for member in zip_file.namelist():
if member != 'ComicInfo.xml':
continue
with zip_file.open(member) as xml_file:
self.rawdata = parse(xml_file)
elif rarfile.is_rarfile(self.source):
self.compressor = 'rar'
with rarfile.RarFile(self.source) as rar_file:
for member in rar_file.namelist():
if member != 'ComicInfo.xml':
continue
with rar_file.open(member) as xml_file:
self.rawdata = parse(xml_file)
elif is_7zfile(self.source):
self.compressor = '7z'
workdir = mkdtemp('', 'KCC-')
tmpXML = os.path.join(workdir, 'ComicInfo.xml')
output = Popen('7za e "' + self.source + '" ComicInfo.xml -o"' + workdir + '"',
stdout=PIPE, stderr=STDOUT, shell=True)
extracted = False
for line in output.stdout:
if b"Everything is Ok" in line or b"No files to process" in line:
extracted = True
if not extracted:
rmtree(workdir)
raise OSError
if os.path.isfile(tmpXML):
self.rawdata = parse(tmpXML)
rmtree(workdir)
else:
raise OSError
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
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('ScanInformation')) != 0:
coverId = compile('(MCD\\()(\\d+)(\\))')\
.search(self.rawdata.getElementsByTagName('ScanInformation')[0].firstChild.nodeValue)
if coverId:
self.data['MUid'] = coverId.group(2)
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'])],
['ScanInformation', 'MCD(' + self.data['MUid'] + ')' if self.data['MUid'] else '']):
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'])],
['ScanInformation', 'MCD(' + self.data['MUid'] + ')' if self.data['MUid'] else '']):
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')
if is_zipfile(self.source):
removeFromZIP(self.source, 'ComicInfo.xml')
with ZipFile(self.source, mode='a', compression=ZIP_DEFLATED) as zip_file:
zip_file.write(tmpXML, arcname=tmpXML.split(os.sep)[-1])
elif rarfile.is_rarfile(self.source):
raise NotImplementedError
elif is_7zfile(self.source):
output = Popen('7za a "' + self.source + '" "' + tmpXML + '"', stdout=PIPE, stderr=STDOUT, shell=True)
extracted = False
for line in output.stdout:
if b"Everything is Ok" in line:
extracted = True
if not extracted:
rmtree(workdir)
raise OSError
rmtree(workdir)

View File

@@ -1,4 +1,5 @@
# Copyright (c) 2012 Ciro Mattia Gonano <ciromattia@gmail.com> # Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
# Copyright (c) 2013-2015 Pawel Jastrzebski <pawelj@iosphe.re>
# #
# Based upon the code snippet by Ned Batchelder # Based upon the code snippet by Ned Batchelder
# (http://nedbatchelder.com/blog/200712/extracting_jpgs_from_pdfs.html) # (http://nedbatchelder.com/blog/200712/extracting_jpgs_from_pdfs.html)
@@ -18,56 +19,50 @@
# PERFORMANCE OF THIS SOFTWARE. # 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 os
from random import choice
from string import ascii_uppercase, digits
class PdfJpgExtract: class PdfJpgExtract:
def __init__(self, origFileName): def __init__(self, origFileName):
self.origFileName = origFileName self.origFileName = origFileName
self.filename = os.path.splitext(origFileName) self.filename = os.path.splitext(origFileName)
self.path = self.filename[0] # noinspection PyUnusedLocal
self.path = self.filename[0] + "-KCC-" + ''.join(choice(ascii_uppercase + digits) for x in range(3))
def getPath(self): def getPath(self):
return self.path return self.path
def extract(self): def extract(self):
pdf = file(self.origFileName, "rb").read() pdf = open(self.origFileName, "rb").read()
startmark = b"\xff\xd8"
startmark = "\xff\xd8"
startfix = 0 startfix = 0
endmark = "\xff\xd9" endmark = b"\xff\xd9"
endfix = 2 endfix = 2
i = 0 i = 0
njpg = 0 njpg = 0
os.makedirs(self.path) os.makedirs(self.path)
while True: while True:
istream = pdf.find("stream", i) istream = pdf.find(b"stream", i)
if istream < 0: if istream < 0:
break break
istart = pdf.find(startmark, istream, istream + 20) istart = pdf.find(startmark, istream, istream + 20)
if istart < 0: if istart < 0:
i = istream + 20 i = istream + 20
continue continue
iend = pdf.find("endstream", istart) iend = pdf.find(b"endstream", istart)
if iend < 0: if iend < 0:
raise Exception("Didn't find end of stream!") raise Exception("Didn't find end of stream!")
iend = pdf.find(endmark, iend - 20) iend = pdf.find(endmark, iend - 20)
if iend < 0: if iend < 0:
raise Exception("Didn't find end of JPG!") raise Exception("Didn't find end of JPG!")
istart += startfix istart += startfix
iend += endfix iend += endfix
print "JPG %d from %d to %d" % (njpg, istart, iend)
jpg = pdf[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.write(jpg)
jpgfile.close() jpgfile.close()
njpg += 1 njpg += 1
i = iend i = iend
return self.path return self.path, njpg

View File

@@ -1,6 +1,6 @@
# rarfile.py # rarfile.py
# #
# Copyright (c) 2005-2013 Marko Kreen <markokr@gmail.com> # Copyright (c) 2005-2014 Marko Kreen <markokr@gmail.com>
# #
# Permission to use, copy, modify, and/or distribute this software for any # Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above # purpose with or without fee is hereby granted, provided that the above
@@ -74,7 +74,7 @@ For more details, refer to source.
""" """
__version__ = '2.6' __version__ = '2.7-kcc'
# export only interesting items # export only interesting items
__all__ = ['is_rarfile', 'RarInfo', 'RarFile', 'RarExtFile'] __all__ = ['is_rarfile', 'RarInfo', 'RarFile', 'RarExtFile']
@@ -108,6 +108,8 @@ if sys.hexversion < 0x3000000:
# py2.6 has broken bytes() # py2.6 has broken bytes()
def bytes(s, enc): def bytes(s, enc):
return str(s) return str(s)
else:
unicode = str
# see if compat bytearray() is needed # see if compat bytearray() is needed
try: try:
@@ -176,8 +178,25 @@ EXTRACT_ARGS = ('x', '-y', '-idq')
#: args for testrar() #: args for testrar()
TEST_ARGS = ('t', '-idq') TEST_ARGS = ('t', '-idq')
#
# Allow use of tool that is not compatible with unrar.
#
# By default use 'bsdtar' which is 'tar' program that
# sits on top of libarchive.
#
# Problems with libarchive RAR backend:
# - Does not support solid archives.
# - Does not support password-protected archives.
#
ALT_TOOL = 'bsdtar'
ALT_OPEN_ARGS = ('-x', '--to-stdout', '-f')
ALT_EXTRACT_ARGS = ('-x', '-f')
ALT_TEST_ARGS = ('-t', '-f')
ALT_CHECK_ARGS = ('--help',)
#: whether to speed up decompression by using tmp archive #: whether to speed up decompression by using tmp archive
USE_EXTRACT_HACK = 1 USE_EXTRACT_HACK = 0
#: limit the filesize for tmp archive usage #: limit the filesize for tmp archive usage
HACK_SIZE_LIMIT = 20*1024*1024 HACK_SIZE_LIMIT = 20*1024*1024
@@ -188,10 +207,6 @@ NEED_COMMENTS = 1
#: whether to convert comments to unicode strings #: whether to convert comments to unicode strings
UNICODE_COMMENTS = 0 UNICODE_COMMENTS = 0
#: When RAR is corrupt, stopping on bad header is better
#: On unknown/misparsed RAR headers reporting is better
REPORT_BAD_HEADER = 0
#: Convert RAR time tuple into datetime() object #: Convert RAR time tuple into datetime() object
USE_DATETIME = 0 USE_DATETIME = 0
@@ -280,6 +295,7 @@ RAR_M5 = 0x35
## ##
RAR_ID = bytes("Rar!\x1a\x07\x00", 'ascii') RAR_ID = bytes("Rar!\x1a\x07\x00", 'ascii')
RAR5_ID = bytes("Rar!\x1a\x07\x01", 'ascii')
ZERO = bytes("\0", 'ascii') ZERO = bytes("\0", 'ascii')
EMPTY = bytes("", 'ascii') EMPTY = bytes("", 'ascii')
@@ -338,12 +354,19 @@ class RarUnknownError(RarExecError):
"""Unknown exit code""" """Unknown exit code"""
class RarSignalExit(RarExecError): class RarSignalExit(RarExecError):
"""Unrar exited with signal""" """Unrar exited with signal"""
class RarCannotExec(RarExecError):
"""Executable not found."""
def is_rarfile(fn): def is_rarfile(xfile):
'''Check quickly whether file is rar archive.''' '''Check quickly whether file is rar archive.'''
buf = open(fn, "rb").read(len(RAR_ID)) fd = XFile(xfile)
return buf == RAR_ID buf = fd.read(len(RAR_ID))
fd.close()
if buf == RAR_ID or buf == RAR5_ID:
return True
else:
return False
class RarInfo(object): class RarInfo(object):
@@ -453,11 +476,12 @@ class RarFile(object):
'''Parse RAR structure, provide access to files in archive. '''Parse RAR structure, provide access to files in archive.
''' '''
#: Archive comment. Byte string or None. Use UNICODE_COMMENTS #: Archive comment. Byte string or None. Use :data:`UNICODE_COMMENTS`
#: to get automatic decoding to unicode. #: to get automatic decoding to unicode.
comment = None comment = None
def __init__(self, rarfile, mode="r", charset=None, info_callback=None, crc_check = True): def __init__(self, rarfile, mode="r", charset=None, info_callback=None,
crc_check = True, errors = "stop"):
"""Open and parse a RAR archive. """Open and parse a RAR archive.
Parameters: Parameters:
@@ -472,6 +496,9 @@ class RarFile(object):
debug callback, gets to see all archive entries. debug callback, gets to see all archive entries.
crc_check crc_check
set to False to disable CRC checks set to False to disable CRC checks
errors
Either "stop" to quietly stop parsing on errors,
or "strict" to raise errors. Default is "stop".
""" """
self.rarfile = rarfile self.rarfile = rarfile
self.comment = None self.comment = None
@@ -485,6 +512,13 @@ class RarFile(object):
self._crc_check = crc_check self._crc_check = crc_check
self._vol_list = [] self._vol_list = []
if errors == "stop":
self._strict = False
elif errors == "strict":
self._strict = True
else:
raise ValueError("Invalid value for 'errors' parameter.")
self._main = None self._main = None
if mode != "r": if mode != "r":
@@ -548,8 +582,9 @@ class RarFile(object):
'''Returns file-like object (:class:`RarExtFile`), '''Returns file-like object (:class:`RarExtFile`),
from where the data can be read. from where the data can be read.
The object implements io.RawIOBase interface, so it can The object implements :class:`io.RawIOBase` interface, so it can
be further wrapped with io.BufferedReader and io.TextIOWrapper. be further wrapped with :class:`io.BufferedReader`
and :class:`io.TextIOWrapper`.
On older Python where io module is not available, it implements On older Python where io module is not available, it implements
only .read(), .seek(), .tell() and .close() methods. only .read(), .seek(), .tell() and .close() methods.
@@ -588,16 +623,19 @@ class RarFile(object):
psw = None psw = None
# is temp write usable? # is temp write usable?
if not USE_EXTRACT_HACK or not self._main: use_hack = 1
if not self._main:
use_hack = 0 use_hack = 0
elif self._main.flags & (RAR_MAIN_SOLID | RAR_MAIN_PASSWORD): elif self._main.flags & (RAR_MAIN_SOLID | RAR_MAIN_PASSWORD):
use_hack = 0 use_hack = 0
elif inf.flags & (RAR_FILE_SPLIT_BEFORE | RAR_FILE_SPLIT_AFTER): elif inf.flags & (RAR_FILE_SPLIT_BEFORE | RAR_FILE_SPLIT_AFTER):
use_hack = 0 use_hack = 0
elif is_filelike(self.rarfile):
pass
elif inf.file_size > HACK_SIZE_LIMIT: elif inf.file_size > HACK_SIZE_LIMIT:
use_hack = 0 use_hack = 0
else: elif not USE_EXTRACT_HACK:
use_hack = 1 use_hack = 0
# now extract # now extract
if inf.compress_type == RAR_M0 and (inf.flags & RAR_FILE_PASSWORD) == 0: if inf.compress_type == RAR_M0 and (inf.flags & RAR_FILE_PASSWORD) == 0:
@@ -610,7 +648,7 @@ class RarFile(object):
def read(self, fname, psw = None): def read(self, fname, psw = None):
"""Return uncompressed data for archive entry. """Return uncompressed data for archive entry.
For longer files using .open() may be better idea. For longer files using :meth:`RarFile.open` may be better idea.
Parameters: Parameters:
@@ -641,7 +679,7 @@ class RarFile(object):
Parameters: Parameters:
member member
filename or RarInfo instance filename or :class:`RarInfo` instance
path path
optional destination path optional destination path
pwd pwd
@@ -661,7 +699,7 @@ class RarFile(object):
path path
optional destination path optional destination path
members members
optional filename or RarInfo instance list to extract optional filename or :class:`RarInfo` instance list to extract
pwd pwd
optional password to use optional password to use
""" """
@@ -678,19 +716,29 @@ class RarFile(object):
"""Let 'unrar' test the archive. """Let 'unrar' test the archive.
""" """
cmd = [UNRAR_TOOL] + list(TEST_ARGS) cmd = [UNRAR_TOOL] + list(TEST_ARGS)
if self._password is not None: add_password_arg(cmd, self._password)
cmd.append('-p' + self._password)
else:
cmd.append('-p-')
cmd.append(self.rarfile) cmd.append(self.rarfile)
p = custom_popen(cmd) p = custom_popen(cmd)
output = p.communicate()[0] output = p.communicate()[0]
check_returncode(p, output) check_returncode(p, output)
def strerror(self):
"""Return error string if parsing failed,
or None if no problems.
"""
return self._parse_error
## ##
## private methods ## private methods
## ##
def _set_error(self, msg, *args):
if args:
msg = msg % args
self._parse_error = msg
if self._strict:
raise BadRarFile(msg)
# store entry # store entry
def _process_entry(self, item): def _process_entry(self, item):
if item.type == RAR_BLOCK_FILE: if item.type == RAR_BLOCK_FILE:
@@ -738,10 +786,10 @@ class RarFile(object):
self._fd = None self._fd = None
def _parse_real(self): def _parse_real(self):
fd = open(self.rarfile, "rb") fd = XFile(self.rarfile)
self._fd = fd self._fd = fd
id = fd.read(len(RAR_ID)) id = fd.read(len(RAR_ID))
if id != RAR_ID: if id != RAR_ID and id != RAR5_ID:
raise NotRarFile("Not a Rar archive: "+self.rarfile) raise NotRarFile("Not a Rar archive: "+self.rarfile)
volume = 0 # first vol (.rar) is 0 volume = 0 # first vol (.rar) is 0
@@ -757,9 +805,13 @@ class RarFile(object):
if not h: if not h:
if more_vols: if more_vols:
volume += 1 volume += 1
volfile = self._next_volname(volfile)
fd.close() fd.close()
fd = open(volfile, "rb") try:
volfile = self._next_volname(volfile)
fd = XFile(volfile)
except IOError:
self._set_error("Cannot open next volume: %s", volfile)
break
self._fd = fd self._fd = fd
more_vols = 0 more_vols = 0
endarc = 0 endarc = 0
@@ -824,8 +876,7 @@ class RarFile(object):
# now read actual header # now read actual header
return self._parse_block_header(fd) return self._parse_block_header(fd)
except struct.error: except struct.error:
if REPORT_BAD_HEADER: self._set_error('Broken header in RAR file')
raise BadRarFile('Broken header in RAR file')
return None return None
# common header # common header
@@ -852,8 +903,7 @@ class RarFile(object):
# unexpected EOF? # unexpected EOF?
if len(h.header_data) != h.header_size: if len(h.header_data) != h.header_size:
if REPORT_BAD_HEADER: self._set_error('Unexpected EOF when reading header')
raise BadRarFile('Unexpected EOF when reading header')
return None return None
# block has data assiciated with it? # block has data assiciated with it?
@@ -896,18 +946,9 @@ class RarFile(object):
if h.header_crc == calc_crc: if h.header_crc == calc_crc:
return h return h
# need to panic? # header parsing failed.
if REPORT_BAD_HEADER: self._set_error('Header CRC error (%02x): exp=%x got=%x (xlen = %d)',
xlen = len(crcdat) h.type, h.header_crc, calc_crc, len(crcdat))
crcdat = h.header_data[2:]
msg = 'Header CRC error (%02x): exp=%x got=%x (xlen = %d)' % ( h.type, h.header_crc, calc_crc, xlen )
xlen = len(crcdat)
while xlen >= S_BLK_HDR.size - 2:
crc = crc32(crcdat[:xlen]) & 0xFFFF
if crc == h.header_crc:
msg += ' / crc match, xlen = %d' % xlen
xlen -= 1
raise BadRarFile(msg)
# instead panicing, send eof # instead panicing, send eof
return None return None
@@ -1053,6 +1094,8 @@ class RarFile(object):
# given current vol name, construct next one # given current vol name, construct next one
def _next_volname(self, volfile): def _next_volname(self, volfile):
if is_filelike(volfile):
raise IOError("Working on single FD")
if self._main.flags & RAR_MAIN_NEWNUMBERING: if self._main.flags & RAR_MAIN_NEWNUMBERING:
return self._next_newvol(volfile) return self._next_newvol(volfile)
return self._next_oldvol(volfile) return self._next_oldvol(volfile)
@@ -1093,7 +1136,7 @@ class RarFile(object):
BSIZE = 32*1024 BSIZE = 32*1024
size = inf.compress_size + inf.header_size size = inf.compress_size + inf.header_size
rf = open(inf.volume_file, "rb", 0) rf = XFile(inf.volume_file, 0)
rf.seek(inf.header_offset) rf.seek(inf.header_offset)
tmpfd, tmpname = mkstemp(suffix='.rar') tmpfd, tmpname = mkstemp(suffix='.rar')
@@ -1125,7 +1168,7 @@ class RarFile(object):
def _read_comment_v3(self, inf, psw=None): def _read_comment_v3(self, inf, psw=None):
# read data # read data
rf = open(inf.volume_file, "rb") rf = XFile(inf.volume_file)
rf.seek(inf.file_offset) rf.seek(inf.file_offset)
data = rf.read(inf.compress_size) data = rf.read(inf.compress_size)
rf.close() rf.close()
@@ -1146,9 +1189,10 @@ class RarFile(object):
# extract using unrar # extract using unrar
def _open_unrar(self, rarfile, inf, psw = None, tmpfile = None): def _open_unrar(self, rarfile, inf, psw = None, tmpfile = None):
if is_filelike(rarfile):
raise ValueError("Cannot use unrar directly on memory buffer")
cmd = [UNRAR_TOOL] + list(OPEN_ARGS) cmd = [UNRAR_TOOL] + list(OPEN_ARGS)
if psw is not None: add_password_arg(cmd, psw)
cmd.append("-p" + psw)
cmd.append(rarfile) cmd.append(rarfile)
# not giving filename avoids encoding related problems # not giving filename avoids encoding related problems
@@ -1180,10 +1224,7 @@ class RarFile(object):
# pasoword # pasoword
psw = psw or self._password psw = psw or self._password
if psw is not None: add_password_arg(cmd, psw)
cmd.append('-p' + psw)
else:
cmd.append('-p-')
# rar file # rar file
cmd.append(self.rarfile) cmd.append(self.rarfile)
@@ -1553,7 +1594,7 @@ class DirectReader(RarExtFile):
RarExtFile._open(self) RarExtFile._open(self)
self.volfile = self.inf.volume_file self.volfile = self.inf.volume_file
self.fd = open(self.volfile, "rb", 0) self.fd = XFile(self.volfile, 0)
self.fd.seek(self.inf.header_offset, 0) self.fd.seek(self.inf.header_offset, 0)
self.cur = self.rf._parse_header(self.fd) self.cur = self.rf._parse_header(self.fd)
self.cur_avail = self.cur.add_size self.cur_avail = self.cur.add_size
@@ -1705,10 +1746,47 @@ class HeaderDecrypt:
return res return res
# handle (filename|filelike) object
class XFile(object):
__slots__ = ('_fd', '_need_close')
def __init__(self, xfile, bufsize = 1024):
if is_filelike(xfile):
self._need_close = False
self._fd = xfile
self._fd.seek(0)
else:
self._need_close = True
self._fd = open(xfile, 'rb', bufsize)
def read(self, n=None):
return self._fd.read(n)
def tell(self):
return self._fd.tell()
def seek(self, ofs, whence=0):
return self._fd.seek(ofs, whence)
def readinto(self, dst):
return self._fd.readinto(dst)
def close(self):
if self._need_close:
self._fd.close()
def __enter__(self):
return self
def __exit__(self, typ, val, tb):
self.close()
## ##
## Utility functions ## Utility functions
## ##
def is_filelike(obj):
if isinstance(obj, str) or isinstance(obj, unicode):
return False
res = True
for a in ('read', 'tell', 'seek'):
res = res and hasattr(obj, a)
if not res:
raise ValueError("Invalid object passed as file")
return True
def rar3_s2k(psw, salt): def rar3_s2k(psw, salt):
"""String-to-key hash for RAR3.""" """String-to-key hash for RAR3."""
@@ -1768,10 +1846,7 @@ def rar_decompress(vers, meth, data, declen=0, flags=0, crc=0, psw=None, salt=No
tmpf.close() tmpf.close()
cmd = [UNRAR_TOOL] + list(OPEN_ARGS) cmd = [UNRAR_TOOL] + list(OPEN_ARGS)
if psw is not None and (flags & RAR_FILE_PASSWORD): add_password_arg(cmd, psw, (flags & RAR_FILE_PASSWORD))
cmd.append("-p" + psw)
else:
cmd.append("-p-")
cmd.append(tmpname) cmd.append(tmpname)
p = custom_popen(cmd) p = custom_popen(cmd)
@@ -1840,22 +1915,43 @@ def custom_popen(cmd):
except OSError: except OSError:
ex = sys.exc_info()[1] ex = sys.exc_info()[1]
if ex.errno == errno.ENOENT: if ex.errno == errno.ENOENT:
raise RarExecError("Unrar not installed? (rarfile.UNRAR_TOOL=%r)" % UNRAR_TOOL) raise RarCannotExec("Unrar not installed? (rarfile.UNRAR_TOOL=%r)" % UNRAR_TOOL)
raise raise
return p return p
def custom_check(cmd, ignore_retcode=False):
"""Run command, collect output, raise error if needed."""
p = custom_popen(cmd)
out, err = p.communicate()
if p.returncode and not ignore_retcode:
raise RarExecError("Check-run failed")
return out
def add_password_arg(cmd, psw, required=False):
"""Append password switch to commandline."""
if UNRAR_TOOL == ALT_TOOL:
return
if psw is not None:
cmd.append('-p' + psw)
else:
cmd.append('-p-')
def check_returncode(p, out): def check_returncode(p, out):
"""Raise exception according to unrar exit code""" """Raise exception according to unrar exit code"""
code = p.returncode code = p.returncode
if code == 0: if code == 0:
return return
if code == 9:
return
# map return code to exception class # map return code to exception class
errmap = [None, errmap = [None,
RarWarning, RarFatalError, RarCRCError, RarLockedArchiveError, RarWarning, RarFatalError, RarCRCError, RarLockedArchiveError,
RarWriteError, RarOpenError, RarUserError, RarMemoryError, RarWriteError, RarOpenError, RarUserError, RarMemoryError,
RarCreateError, RarNoFilesError] # codes from rar.txt RarCreateError, RarNoFilesError] # codes from rar.txt
if UNRAR_TOOL == ALT_TOOL:
errmap = [None]
if code > 0 and code < len(errmap): if code > 0 and code < len(errmap):
exc = errmap[code] exc = errmap[code]
elif code == 255: elif code == 255:
@@ -1873,3 +1969,23 @@ def check_returncode(p, out):
raise exc(msg) raise exc(msg)
#
# Check if unrar works
#
try:
# does UNRAR_TOOL work?
custom_check([UNRAR_TOOL], True)
except RarCannotExec:
try:
# does ALT_TOOL work?
custom_check([ALT_TOOL] + list(ALT_CHECK_ARGS), True)
# replace config
UNRAR_TOOL = ALT_TOOL
OPEN_ARGS = ALT_OPEN_ARGS
EXTRACT_ARGS = ALT_EXTRACT_ARGS
TEST_ARGS = ALT_TEST_ARGS
except RarCannotExec:
# no usable tool, only uncompressed archives work
pass

157
kcc/shared.py Normal file
View File

@@ -0,0 +1,157 @@
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
# Copyright (c) 2013-2015 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 time import sleep
from shutil import rmtree, move
from tempfile import mkdtemp
from zipfile import ZipFile, ZIP_DEFLATED
from re import split
try:
from scandir import walk
except ImportError:
walk = None
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 getImageFileName(imgfile):
name, ext = os.path.splitext(imgfile)
ext = ext.lower()
if name.startswith('.') or (ext != '.png' and ext != '.jpg' and ext != '.jpeg' and ext != '.gif'):
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 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(filePath):
with open(filePath, 'rb') as fh:
m = md5()
while True:
data = fh.read(8192)
if not data:
break
m.update(data)
return m.hexdigest()
def check7ZFile(filePath):
with open(filePath, 'rb') as fh:
header = fh.read(6)
return header == b"7z\xbc\xaf'\x1c"
def saferReplace(old, new):
for x in range(5):
try:
os.replace(old, new)
except PermissionError:
sleep(5)
else:
break
else:
raise PermissionError
def removeFromZIP(zipfname, *filenames):
tempdir = mkdtemp('', 'KCC-')
try:
tempname = os.path.join(tempdir, 'KCC.zip')
with ZipFile(zipfname, 'r') as zipread:
with ZipFile(tempname, 'w', compression=ZIP_DEFLATED) as zipwrite:
for item in zipread.infolist():
if item.filename not in filenames:
zipwrite.writestr(item, zipread.read(item.filename))
move(tempname, zipfname)
finally:
rmtree(tempdir)
# noinspection PyUnresolvedReferences
def dependencyCheck(level):
missing = []
if level > 2:
try:
from PyQt5.QtCore import qVersion as qtVersion
if StrictVersion('5.2.0') > StrictVersion(qtVersion()):
missing.append('PyQt 5.2.0+')
except ImportError:
missing.append('PyQt 5.2.0+')
if level > 1:
try:
from psutil import __version__ as psutilVersion
if StrictVersion('2.0.0') > StrictVersion(psutilVersion):
missing.append('psutil 2.0.0+')
except ImportError:
missing.append('psutil 2.0.0+')
try:
from slugify import __version__ as slugifyVersion
if StrictVersion('0.1.0') > StrictVersion(slugifyVersion):
missing.append('python-slugify 0.1.0+')
except ImportError:
missing.append('python-slugify 0.1.0+')
try:
from PIL import PILLOW_VERSION as pillowVersion
if StrictVersion('2.7.0') > StrictVersion(pillowVersion):
missing.append('Pillow 2.7.0+')
except ImportError:
missing.append('Pillow 2.7.0+')
try:
from scandir import __version__ as scandirVersion
if StrictVersion('0.9') > StrictVersion(scandirVersion):
missing.append('scandir 0.9+')
except ImportError:
missing.append('scandir 0.9+')
if len(missing) > 0:
print('ERROR: ' + ', '.join(missing) + ' is not installed!')
exit(1)

BIN
other/7za Executable file

Binary file not shown.

BIN
other/7za.exe Normal file

Binary file not shown.

View File

@@ -0,0 +1,91 @@
****** ***** ****** 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

229
other/InstallWarning.rtf Normal file
View File

@@ -0,0 +1,229 @@
{\rtf1\adeflang1025\ansi\ansicpg1250\uc1\adeff0\deff0\stshfdbch0\stshfloch31506\stshfhich31506\stshfbi31506\deflang1045\deflangfe1045\themelang1045\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset238\fprq2{\*\panose 02020603050405020304}Times New Roman;}
{\f0\fbidi \froman\fcharset238\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f37\fbidi \fswiss\fcharset238\fprq2{\*\panose 020f0502020204030204}Calibri;}
{\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;}
{\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;}
{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\flominor\f31550\fbidi \froman\fcharset0\fprq2 Times New Roman;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
{\fdbminor\f31560\fbidi \froman\fcharset0\fprq2 Times New Roman;}{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}
{\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;}{\*
\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
\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
\asianbrkrule\rsidroot11107340\newtblstyruls\nogrowautofit\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal \nouicompat \fet0
{\*\wgrffmtfilter 2450}\nofeaturethrottle1\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\headery708\footery708\colsx708\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2
\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6
\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang
{\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\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 {\rtlch\fcs1 \af0 \ltrch\fcs0 \b\fs52\cf6\lang2057\langfe1033\langnp2057\insrsid3562894\charrsid3562894 Warning!}{\rtlch\fcs1 \af0 \ltrch\fcs0
\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
\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
\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
\af0\afs24 \ltrch\fcs0 \fs28\lang2057\langfe1033\langnp2057\insrsid5731975\charrsid12600926 }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \fs28\lang2057\langfe1033\langnp2057\insrsid3562894\charrsid12600926 inside }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0
\b\fs28\lang2057\langfe1033\langnp2057\insrsid3146412\charrsid3146412 Kindle}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \b\fs28\lang2057\langfe1033\langnp2057\insrsid3146412 }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0
\b\fs28\lang2057\langfe1033\langnp2057\insrsid3146412\charrsid3146412 Comic}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \b\fs28\lang2057\langfe1033\langnp2057\insrsid3146412 }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0
\b\fs28\lang2057\langfe1033\langnp2057\insrsid3146412\charrsid3146412 Converter}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \b\fs28\lang2057\langfe1033\langnp2057\insrsid3146412 }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0
\fs28\lang2057\langfe1033\langnp2057\insrsid3562894\charrsid12600926 directory.
\par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a
9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad
5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6
b01d583deee5f99824e290b4ba3f364eac4a430883b3c092d4eca8f946c916422ecab927f52ea42b89a1cd59c254f919b0e85e6535d135a8de20f20b8c12c3b0
0c895fcf6720192de6bf3b9e89ecdbd6596cbcdd8eb28e7c365ecc4ec1ff1460f53fe813d3cc7f5b7f020000ffff0300504b030414000600080000002100a5d6
a7e7c0000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4f
c7060abb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b6309512
0f88d94fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462
a1a82fe353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f746865
6d652f7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b
4b0d592c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b
4757e8d3f729e245eb2b260a0238fd010000ffff0300504b030414000600080000002100b7e72e45da060000a81a0000160000007468656d652f7468656d652f
7468656d65312e786d6cec595d8b1b37147d2ff43f0cf3eef86bc61f4bbcc11edbd936bbc9123b2979d4dab24759cdc88ce4dd981028c963a1509a963e34d0b7
3e94b68104fa92fe9a6d53da14f2177aa5198f255bdb4d96149692352c63f9dcaba37bef9cab195dbe722fa2ce114e386171cb2d5f2ab90e8e476c4ce269cbbd
35ec171aaec3058ac788b218b7dc05e6ee95ed0f3fb88cb6448823ec807dccb750cb0d85986d158b7c04c3885f62331cc36f13964448c0d7645a1c27e818fc46
b45829956ac50891d875621481db3d2616c7ce0c1d122ce6ce8dc9848cb0bbbd9ca44761a658703930a2c9404e8133cb7d65a39b8c0fcb12c8173ca089738468
cb8569c7ec7888ef09d7a1880bf8a1e596d49f5bdcbe5c445b991115a7d86a767df597d96506e3c38a9a33991ee4937a9eefd5dab97f05a06213d7abf76abd5a
ee4f01d068040b4eb9e83efd4eb3d3f533ac064a2f2dbebbf56eb56ce035ffd50dce6d5f7e0cbc02a5febd0d7cbf1f40140dbc02a5787f03ef79f54ae0197805
4af1b50d7cbdd4ee7a7503af402125f1e106bae4d7aac172b53964c2e88e15def4bd7ebd92395fa1a01af22293534c582cce28b908dd65491f70124f9120b123
16333c4123a8ed005172901067974c43a8bf198a1987e152a5d42f55e1bffc78ea4a05066d61a4594b7a40886f0c495a0e1f2564265aeec7e0d5d520af5ffcf8
fac533e7e4e1f39387bf9c3c7a74f2f0e7d49161b583e2a96ef5eafb2ffe7ef2a9f3d7b3ef5e3dfeca8ee73afef79f3efbedd72fed4058e92a042fbf7efac7f3
a72fbff9fccf1f1e5be0ed041de8f021893077aee363e7268b60612a0426737c90bc9dc5304444b768c7538e622467b1f8ef89d0405f5f208a2cb80e3623783b
01a5b101afceef1a8407613217c4e2f15a1819c03dc6688725d6285c937369611ecee3a97df264aee36e2274649b3b40b191dfde7c064a4b6c2e83101b34f729
8a059ae2180b47fec60e31b6acee0e21465cf7c828619c4d847387381d44ac21199203a39a56463b2482bc2c6c0421df466cf66e3b1d466dabeee22313097705
a216f2434c8d305e457381229bcb218aa81ef05d24421bc9c12219e9b81e1790e929a6cce98d31e7369b1b09ac574bfa3590177bdaf7e8223291892087369fbb
88311dd965874188a2990d3b2071a8633fe28750a2c8d967c206df63e61d22bf431e507c6aba6fc31e409fe06c35b805caaa5bac0a44fe324f2cb9bc8a9951bf
83059d20aca406f4dfd0f388c4678afb9aacfbffadac8390befcf68965551755d0db09b1de513b6b327e1a6e5dbc03968cc9c5d7ee2e9ac7fb186e97cd06f65e
badf4bb7fbbf97eed3eee7772fd82b8d06f9965bc574c7aef6efd159dbf709a174201614ef72b583e7d0a0c67d1894e6ea8116e74f75b3102ee50d0df318b869
82948d9330f10911e1204433d8e6975de964ca33d753eecc1887ddbf1ab6fa96783a8ff6d8387d782d97e5836aaa211c89d578c9cfc7e18943a4e85a7df54096
bb576ca7eaf9794940dabe0d096d329344d542a2be1c9441524feb10340b09b5b277c2a26961d190ee97a9da6001d4f2acc00eca817d57cbf53d30012378b042
148f659ed2542fb3ab92f92e337d5a308d0a80edc4b20256996e4aaea72e4fae2e2db537c8b441422b3793848a8c6a653c44639c55a71c7d131a6f9bebe62aa5
063d190a351f94d68a46bdf16f2cce9b6bb05bd7061aeb4a4163e7b8e5d6aa3e94cc08cd5aee049efee1329a41ed70b9f345740a2fd64622496ff8f328cb2ce1
a28b7898065c894eaa061111387128895aae5c7e9e061a2b0d51dcca1510840b4bae09b272d1c841d2cd24e3c9048f849e766d44463afd0a0a9f6a85f557657e
7eb0b4647348f7201c1f3b07749edc4450627ebd2c0338261c5e0295d3688e09bcdccc856c557f6b8d29935dfdeda2aaa1741cd15988b28ea28b790a57529ed3
51dff21868dfb2354340b590648df0602a1bac1e54a39be65d23e5706ad73ddb48464e13cd55cf345445764dbb8a19332cdbc05a2ccfd7e43556cb1083a6e91d
3e95ee75c96d2eb56e6d9f90770908781e3f4bd77d8386a0515b4d6650938c3765586a76366af68ee502cfa0f6264d4253fddad2ed5adcf21e619d0e06cfd5f9
c16ebd6a6168b2dc5eaa48ab4311fdbc821ddc05f1e8c2bbe039155ca5128e2112041ba281da93a4b201b7c83d91dd1a70e5cc13d272ef97fcb61754fca0506a
f8bd8257f54a8586dfae16dabe5f2df7fc72a9dba93c80c622c2a8eca707327d78234517d9b18c1adf389a89962fdd2e8d585464eab0a5a888aba39972c5389a
490f639ca13c73711d02a273bf56e937abcd4eadd0acb6fb05afdb69149a41ad53e8d6827ab7df0dfc46b3ffc0758e14d86b5703afd66b146ae5202878b592a4
df6816ea5ea5d2f6eaed46cf6b3fc8b631b0f2543eb258407815afed7f000000ffff0300504b0304140006000800000021000dd1909fb60000001b0100002700
00007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f78277086f6fd3ba109126dd88d0ad
d40384e4350d363f2451eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89d93b64b060828e6f37ed1567914b
284d262452282e3198720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd5001996509affb3fd381a89672f1f16
5dfe514173d9850528a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100e9de0fbfff0000001c0200001300000000
000000000000000000000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6a7e7c0000000360100000b000000
00000000000000000000300100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a0000001c00000000000000000000
000000190200007468656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d0014000600080000002100b7e72e45da060000a81a000016
00000000000000000000000000d60200007468656d652f7468656d652f7468656d65312e786d6c504b01022d00140006000800000021000dd1909fb60000001b
0100002700000000000000000000000000e40900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000df0a00000000}
{\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d
617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169
6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363
656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e}
{\*\latentstyles\lsdstimax371\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;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 5;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 9;
\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 1;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 2;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 3;
\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 4;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 5;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 6;
\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 7;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 8;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal Indent;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 header;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footer;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index heading;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of figures;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope return;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation reference;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 line number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 page number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote text;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of authorities;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 macro;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 toa heading;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 3;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 3;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 3;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 5;\lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Closing;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Signature;\lsdsemihidden1 \lsdunhideused1 \lsdpriority1 \lsdlocked0 Default Paragraph Font;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 4;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Message Header;\lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Salutation;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Date;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Heading;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 3;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Block Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Hyperlink;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 FollowedHyperlink;\lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;
\lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Document Map;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Plain Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 E-mail Signature;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Top of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Bottom of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal (Web);\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Acronym;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Cite;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Code;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Definition;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Keyboard;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Preformatted;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Sample;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Typewriter;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Variable;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation subject;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 No List;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 1;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Balloon Text;\lsdpriority39 \lsdlocked0 Table Grid;
\lsdsemihidden1 \lsdlocked0 Placeholder Text;\lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing;\lsdpriority60 \lsdlocked0 Light Shading;\lsdpriority61 \lsdlocked0 Light List;\lsdpriority62 \lsdlocked0 Light Grid;
\lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdpriority65 \lsdlocked0 Medium List 1;\lsdpriority66 \lsdlocked0 Medium List 2;\lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdpriority68 \lsdlocked0 Medium Grid 2;
\lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdpriority70 \lsdlocked0 Dark List;\lsdpriority71 \lsdlocked0 Colorful Shading;\lsdpriority72 \lsdlocked0 Colorful List;\lsdpriority73 \lsdlocked0 Colorful Grid;\lsdpriority60 \lsdlocked0 Light Shading Accent 1;
\lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;
\lsdsemihidden1 \lsdlocked0 Revision;\lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;
\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 1;
\lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdpriority60 \lsdlocked0 Light Shading Accent 2;\lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdpriority62 \lsdlocked0 Light Grid Accent 2;
\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 2;
\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2;\lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;
\lsdpriority72 \lsdlocked0 Colorful List Accent 2;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdpriority61 \lsdlocked0 Light List Accent 3;\lsdpriority62 \lsdlocked0 Light Grid Accent 3;
\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;
\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdpriority70 \lsdlocked0 Dark List Accent 3;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;
\lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 3;\lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdpriority62 \lsdlocked0 Light Grid Accent 4;
\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 4;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;
\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 4;
\lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdpriority60 \lsdlocked0 Light Shading Accent 5;\lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdpriority62 \lsdlocked0 Light Grid Accent 5;
\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 5;
\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5;\lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 5;
\lsdpriority72 \lsdlocked0 Colorful List Accent 5;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdpriority61 \lsdlocked0 Light List Accent 6;\lsdpriority62 \lsdlocked0 Light Grid Accent 6;
\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 6;
\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdpriority70 \lsdlocked0 Dark List Accent 6;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 6;
\lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 6;\lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis;
\lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference;\lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdsemihidden1 \lsdunhideused1 \lsdpriority37 \lsdlocked0 Bibliography;
\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;\lsdpriority41 \lsdlocked0 Plain Table 1;\lsdpriority42 \lsdlocked0 Plain Table 2;\lsdpriority43 \lsdlocked0 Plain Table 3;\lsdpriority44 \lsdlocked0 Plain Table 4;
\lsdpriority45 \lsdlocked0 Plain Table 5;\lsdpriority40 \lsdlocked0 Grid Table Light;\lsdpriority46 \lsdlocked0 Grid Table 1 Light;\lsdpriority47 \lsdlocked0 Grid Table 2;\lsdpriority48 \lsdlocked0 Grid Table 3;\lsdpriority49 \lsdlocked0 Grid Table 4;
\lsdpriority50 \lsdlocked0 Grid Table 5 Dark;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 1;
\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 1;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 1;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 1;
\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 1;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 2;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 2;
\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 2;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 2;
\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 3;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 3;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 3;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 3;
\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 3;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 4;
\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 4;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 4;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 4;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 4;
\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 4;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 5;
\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 5;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 5;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 5;
\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 5;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 6;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 6;
\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 6;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 6;
\lsdpriority46 \lsdlocked0 List Table 1 Light;\lsdpriority47 \lsdlocked0 List Table 2;\lsdpriority48 \lsdlocked0 List Table 3;\lsdpriority49 \lsdlocked0 List Table 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark;
\lsdpriority51 \lsdlocked0 List Table 6 Colorful;\lsdpriority52 \lsdlocked0 List Table 7 Colorful;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 List Table 2 Accent 1;\lsdpriority48 \lsdlocked0 List Table 3 Accent 1;
\lsdpriority49 \lsdlocked0 List Table 4 Accent 1;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 1;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 1;
\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 List Table 2 Accent 2;\lsdpriority48 \lsdlocked0 List Table 3 Accent 2;\lsdpriority49 \lsdlocked0 List Table 4 Accent 2;
\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 2;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 3;
\lsdpriority47 \lsdlocked0 List Table 2 Accent 3;\lsdpriority48 \lsdlocked0 List Table 3 Accent 3;\lsdpriority49 \lsdlocked0 List Table 4 Accent 3;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 3;
\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 4;\lsdpriority47 \lsdlocked0 List Table 2 Accent 4;
\lsdpriority48 \lsdlocked0 List Table 3 Accent 4;\lsdpriority49 \lsdlocked0 List Table 4 Accent 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 4;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 4;
\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
4d73786d6c322e534158584d4c5265616465722e362e30000000000000000000000e0000
d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff0900060000000000000000000000010000000100000000000000001000000200000001000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
fffffffffffffffffdffffff04000000feffffff05000000fefffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffff010000000c6ad98892f1d411a65f0040963251e50000000000000000000000006069
e214b3d4ce010300000080020000000000004d0073006f004400610074006100530074006f0072006500000000000000000000000000000000000000000000000000000000000000000000000000000000001a000101ffffffffffffffff0200000000000000000000000000000000000000000000006069e214b3d4ce01
6069e214b3d4ce010000000000000000000000003500d900ca00dd00ce004400cc00c8005a0045004700c400cd0057004900c500d400c900cb00ce00570051003d003d000000000000000000000000000000000032000101ffffffffffffffff0300000000000000000000000000000000000000000000006069e214b3d4
ce016069e214b3d4ce010000000000000000000000004900740065006d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000201ffffffff04000000ffffffff000000000000000000000000000000000000000000000000
00000000000000000000000000000000fc00000000000000010000000200000003000000feffffff0500000006000000070000000800000009000000feffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3c623a536f75726365732053656c65637465645374796c653d225c415041536978746845646974696f6e4f66666963654f6e6c696e652e78736c22205374796c654e616d653d22415041222056657273696f6e3d22362220786d6c6e733a
623d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f6f6666696365446f63756d656e742f323030362f6269626c696f6772617068792220786d6c6e733d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f6f6666696365446f63756d656e74
2f323030362f6269626c696f677261706879223e3c2f623a536f75726365733e000000003c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d226e6f223f3e0d0a3c64733a6461746173746f72654974656d2064733a6974656d49443d227b42384244
394137462d323833422d343136342d413442352d3632323544323941454535397d2220786d6c6e733a64733d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f6f6666696365446f63756d656e742f323030362f637573746f6d586d6c223e3c64733a736368656d61526566733e3c
64733a736368656d615265662064733a7572693d22687474703a2f2f736368656d61732e6f70656e500072006f007000650072007400690065007300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000200ffffffffffffffffffffffff000000000000
0000000000000000000000000000000000000000000000000000000000000400000055010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000786d6c666f726d6174732e6f72672f6f6666696365446f63756d656e742f323030362f6269626c696f677261706879222f3e3c2f64733a736368656d61526566733e3c2f64733a6461746173746f
72654974656d3e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000105000000000000}}

BIN
other/UnRAR.exe Normal file

Binary file not shown.

View File

@@ -1,2 +1,3 @@
; Qt Configuration file
[Paths] [Paths]
Plugins = DumbHackThatFixPY2APP Plugins = PlugIns

BIN
other/unrar Executable file

Binary file not shown.

175
setup.py Normal file → Executable file
View File

@@ -1,20 +1,32 @@
#!/usr/bin/env python3
""" """
cx_Freeze build script for KCC. pip/py2exe/py2app build script for KCC.
Usage (Mac OS X):
python setup.py py2app
Usage (Windows): Usage (Windows):
python setup.py build py -3.4 setup.py py2exe
Usage (Linux):
python3 setup.py make_pyz or python3 setup.py install
Usage (Mac OS X):
python3 setup.py py2app
""" """
from sys import platform from sys import platform, version_info, argv
from kcc import __version__
if version_info[0] != 3:
print('ERROR: This is Python 3 script!')
exit(1)
NAME = "KindleComicConverter" NAME = 'KindleComicConverter'
VERSION = "3.0" VERSION = __version__
MAIN = "kcc.py" MAIN = 'kcc.py'
extra_options = {}
if platform == "darwin": # noinspection PyUnresolvedReferences
if platform == 'darwin':
from setuptools import setup from setuptools import setup
from os import chmod, makedirs
from shutil import copyfile
extra_options = dict( extra_options = dict(
setup_requires=['py2app'], setup_requires=['py2app'],
app=[MAIN], app=[MAIN],
@@ -22,54 +34,129 @@ if platform == "darwin":
py2app=dict( py2app=dict(
argv_emulation=True, argv_emulation=True,
iconfile='icons/comic2ebook.icns', iconfile='icons/comic2ebook.icns',
includes=['PIL', 'sip', 'PyQt4', 'PyQt4.QtCore', 'PyQt4.QtGui'], includes=['sip', 'PyQt5.QtPrintSupport'],
resources=['other/qt.conf', 'LICENSE.txt'], resources=['LICENSE.txt', 'other/qt.conf', 'other/Additional-LICENSE.txt', 'other/unrar', 'other/7za'],
plist=dict( plist=dict(
CFBundleName=NAME, CFBundleName=NAME,
CFBundleShortVersionString=VERSION, CFBundleShortVersionString=VERSION,
CFBundleGetInfoString=NAME + " " + VERSION + CFBundleGetInfoString=NAME + ' ' + VERSION +
", written 2012-2013 by Ciro Mattia Gonano and Pawel Jastrzebski", ', written 2012-2015 by Ciro Mattia Gonano and Pawel Jastrzebski',
CFBundleExecutable=NAME, CFBundleExecutable=NAME,
CFBundleIdentifier='com.github.ciromattia.kcc', CFBundleDocumentTypes=[
CFBundleSignature='dplt', dict(
CFBundleTypeExtensions=['cbz', 'cbr', 'cb7', 'zip', 'rar', '7z', 'pdf'],
CFBundleTypeName='Comics',
CFBundleTypeIconFile='comic2ebook.icns',
CFBundleTypeRole='Editor',
)
],
LSMinimumSystemVersion='10.8.0',
LSEnvironment=dict(
PATH='./../Resources:/usr/local/bin:/usr/bin:/bin'
),
NSHumanReadableCopyright='ISC License (ISCL)' NSHumanReadableCopyright='ISC License (ISCL)'
) )
) )
) )
) )
elif platform == "win32": elif platform == 'win32':
from cx_Freeze import setup, Executable # noinspection PyUnresolvedReferences
base = "Win32GUI" import py2exe
from platform import architecture
from distutils.core import setup
if architecture()[0] == '64bit':
suffix = '_64'
else:
suffix = ''
additional_files = [('platforms', ['C:\Python34' + suffix +
'\Lib\site-packages\PyQt5\plugins\platforms\qwindows.dll']),
('', ['LICENSE.txt',
'other\\7za.exe',
'other\\UnRAR.exe',
'other\\Additional-LICENSE.txt',
'C:\Python34' + suffix + '\Lib\site-packages\PyQt5\libGLESv2.dll',
'C:\Python34' + suffix + '\Lib\site-packages\PyQt5\libEGL.dll'])]
extra_options = dict( extra_options = dict(
options={"build_exe": {"include_files": ['LICENSE.txt'], "compressed": True}}, options={'py2exe': {'bundle_files': 1,
executables=[Executable(MAIN, 'dist_dir': 'dist' + suffix,
base=base, 'compressed': True,
targetName="KCC.exe", 'includes': ['sip'],
icon="icons/comic2ebook.ico", 'excludes': ['tkinter'],
copyDependentFiles=True, 'optimize': 2}},
appendScriptToExe=True, windows=[{'script': MAIN,
appendScriptToLibrary=False, 'dest_base': 'KCC',
compress=True)]) 'version': VERSION,
'copyright': 'Ciro Mattia Gonano, Pawel Jastrzebski © 2012-2015',
'legal_copyright': 'ISC License (ISCL)',
'product_version': VERSION,
'product_name': 'Kindle Comic Converter',
'file_description': 'Kindle Comic Converter',
'icon_resources': [(1, 'icons\comic2ebook.ico')]}],
zipfile=None,
data_files=additional_files)
else: else:
from cx_Freeze import setup, Executable if argv[1] == 'make_pyz':
extra_options = dict( from os import system
options={"build_exe": {"include_files": ['LICENSE.txt'], "compressed": True}}, script = '''
executables=[Executable(MAIN, cp kcc.py __main__.py
icon="icons/comic2ebook.png", zip kcc.zip __main__.py kcc/*.py
copyDependentFiles=True, echo "#!/usr/bin/env python3" > kcc-bin
appendScriptToExe=True, cat kcc.zip >> kcc-bin
appendScriptToLibrary=False, chmod +x kcc-bin
compress=True)])
cp kcc-c2e.py __main__.py
zip kcc-c2e.zip __main__.py kcc/*.py
echo "#!/usr/bin/env python3" > kcc-c2e-bin
cat kcc-c2e.zip >> kcc-c2e-bin
chmod +x kcc-c2e-bin
cp kcc-c2p.py __main__.py
zip kcc-c2p.zip __main__.py kcc/*.py
echo "#!/usr/bin/env python3" > kcc-c2p-bin
cat kcc-c2p.zip >> kcc-c2p-bin
chmod +x kcc-c2p-bin
tar --xform s:^.*/:: --xform s/LICENSE.txt/LICENSE/ --xform s/kcc-bin/kcc/ --xform s/kcc-c2p-bin/kcc-c2p/ \
--xform s/kcc-c2e-bin/kcc-c2e/ --xform s/comic2ebook/kcc/ -czf KindleComicConverter_linux_'''\
+ VERSION + '''.tar.gz kcc-bin kcc-c2e-bin kcc-c2p-bin LICENSE.txt README.md icons/comic2ebook.png
rm __main__.py kcc.zip kcc-c2e.zip kcc-c2p.zip kcc-bin kcc-c2e-bin kcc-c2p-bin
'''
system("bash -c '%s'" % script)
exit(0)
else:
from setuptools import setup
from os import makedirs
from shutil import copyfile
makedirs('build/_scripts/', exist_ok=True)
copyfile('kcc.py', 'build/_scripts/kcc')
copyfile('kcc-c2e.py', 'build/_scripts/kcc-c2e')
copyfile('kcc-c2p.py', 'build/_scripts/kcc-c2p')
extra_options = dict(
scripts=['build/_scripts/kcc', 'build/_scripts/kcc-c2e', 'build/_scripts/kcc-c2p'],
packages=['kcc'],
install_requires=[
'Pillow>=2.7.0',
'psutil>=2.0',
'python-slugify>=0.1.0',
'scandir>=0.9',
],
zip_safe=False,
)
setup( setup(
name=NAME, name=NAME,
version=VERSION, version=VERSION,
author="Ciro Mattia Gonano, Pawel Jastrzebski", author='Ciro Mattia Gonano, Pawel Jastrzebski',
author_email="ciromattia@gmail.com, pawelj@vulturis.eu", author_email='ciromattia@gmail.com, pawelj@iosphe.re',
description="A tool to convert comics (CBR/CBZ/PDFs/image folders) to MOBI.", description='Comic and manga converter for E-Book readers.',
license="ISC License (ISCL)", license='ISC License (ISCL)',
keywords="kindle comic mobipocket mobi cbz cbr manga", keywords='kindle comic mobipocket mobi cbz cbr manga',
url="http://github.com/ciromattia/kcc", url='http://github.com/ciromattia/kcc',
packages=['kcc'], requires=['Pillow'],
**extra_options **extra_options
) )
if platform == 'darwin':
makedirs('dist/' + NAME + '.app/Contents/PlugIns/platforms', exist_ok=True)
copyfile('other/libqcocoa.dylib', 'dist/' + NAME + '.app/Contents/PlugIns/platforms/libqcocoa.dylib')
chmod('dist/' + NAME + '.app/Contents/Resources/unrar', 0o777)
chmod('dist/' + NAME + '.app/Contents/Resources/7za', 0o777)