Compare commits
89 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
01f65220ec | ||
|
|
078c7b78da | ||
|
|
25f00db9cf | ||
|
|
576ee17c4d | ||
|
|
e7f654f56a | ||
|
|
014277b574 | ||
|
|
043a49152f | ||
|
|
40592d197d | ||
|
|
80e3d0eab4 | ||
|
|
40da090fe8 | ||
|
|
795ccd9782 | ||
|
|
57bfd6b968 | ||
|
|
02d1fe308d | ||
|
|
3e117f46d5 | ||
|
|
dbb14e37fa | ||
|
|
8f2b534a68 | ||
|
|
224d2b89b1 | ||
|
|
4c2b5b010b | ||
|
|
b98a1fa100 | ||
|
|
bb51b53e11 | ||
|
|
19bd2431aa | ||
|
|
977ece64e3 | ||
|
|
f8f362fc10 | ||
|
|
fdc265eaea | ||
|
|
941a4fa14f | ||
|
|
e4fdbdaf8d | ||
|
|
c09e050084 | ||
|
|
d12a94401d | ||
|
|
e14d0d7c7f | ||
|
|
ee9c94aceb | ||
|
|
4b4424ae92 | ||
|
|
8a9f11b0f5 | ||
|
|
fd493dba9a | ||
|
|
75bc7c51b5 | ||
|
|
aab166c466 | ||
|
|
94c49f500f | ||
|
|
f353c4edf2 | ||
|
|
acb3e5058d | ||
|
|
6858aecda7 | ||
|
|
4411ca18aa | ||
|
|
dc9dbed683 | ||
|
|
860673bb0e | ||
|
|
ac54a40af5 | ||
|
|
92df52867d | ||
|
|
ab209c6f39 | ||
|
|
69dd23f27b | ||
|
|
c5577317f9 | ||
|
|
0d7cf6f37d | ||
|
|
1d425b3cd6 | ||
|
|
9b62a45100 | ||
|
|
db1f745a50 | ||
|
|
d56e9ef298 | ||
|
|
f278b7c2c5 | ||
|
|
916f3ca9ec | ||
|
|
30c695d988 | ||
|
|
7dcb120edf | ||
|
|
e570e25b24 | ||
|
|
3cbc7f163a | ||
|
|
21a8001f56 | ||
|
|
ebafb0006a | ||
|
|
37e42b2f0b | ||
|
|
1ae5b210b0 | ||
|
|
3f2fb67c04 | ||
|
|
dded30d6a6 | ||
|
|
047a585cc2 | ||
|
|
8cb7aebf86 | ||
|
|
439eedcec7 | ||
|
|
ed94e6508c | ||
|
|
9f33e756d5 | ||
|
|
9fee6568cd | ||
|
|
2a169d50ec | ||
|
|
b2d90c2ac1 | ||
|
|
64cd253618 | ||
|
|
98bc6fbe4c | ||
|
|
70e41eb0e3 | ||
|
|
b5e08df5d3 | ||
|
|
46034b0629 | ||
|
|
109da1056e | ||
|
|
e046565f22 | ||
|
|
ff99472278 | ||
|
|
a5a2c2a93f | ||
|
|
4cf7a531c2 | ||
|
|
b101dc780d | ||
|
|
1c7ff5c597 | ||
|
|
880f220355 | ||
|
|
a1d2acc845 | ||
|
|
60caf896bd | ||
|
|
f9d0ec864d | ||
|
|
6ca1aa532c |
4
.gitignore
vendored
@@ -3,5 +3,7 @@
|
|||||||
*.cbr
|
*.cbr
|
||||||
.idea
|
.idea
|
||||||
build
|
build
|
||||||
awkcc
|
dist
|
||||||
|
kindlegen*
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|||||||
781
KCC-OSX.ui
Normal file
@@ -0,0 +1,781 @@
|
|||||||
|
<?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>380</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>420</width>
|
||||||
|
<height>380</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>420</width>
|
||||||
|
<height>380</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</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>9</x>
|
||||||
|
<y>253</y>
|
||||||
|
<width>421</width>
|
||||||
|
<height>61</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QCheckBox" name="ProcessingBox">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>11</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p><span style=" font-size:12pt;">Disable image optimizations.</span></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>No optimisation</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QCheckBox" name="UpscaleBox">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>11</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p><span style=" font-size:12pt;">Enable image upscaling.<br/>Aspect ratio will be preserved.</span></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Upscale images</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QCheckBox" name="StretchBox">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>11</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p><span style=" font-size:12pt;">Enable image stretching.<br/>Aspect ratio will be not preserved.</span></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Stretch images</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="2">
|
||||||
|
<widget class="QCheckBox" name="NoDitheringBox">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>11</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p><span style=" font-size:12pt;">Create PNG files instead JPEG.<br/></span><span style=" font-size:12pt; font-weight:600;">Only for non-Kindle devices!</span></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>PNG output</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QCheckBox" name="BorderBox">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>11</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p><span style=" font-size:12pt;">Fill space around images with black color.</span></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Black borders</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="2">
|
||||||
|
<widget class="QCheckBox" name="NoRotateBox">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>11</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p><span style=" font-size:12pt;">Disable splitting and rotation.</span></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>No split/rotate</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QComboBox" name="DeviceBox">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>8</x>
|
||||||
|
<y>200</y>
|
||||||
|
<width>151</width>
|
||||||
|
<height>34</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>11</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Target device.</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QComboBox" name="FormatBox">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>262</x>
|
||||||
|
<y>200</y>
|
||||||
|
<width>152</width>
|
||||||
|
<height>34</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>11</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Output format.</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="ConvertButton">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>160</x>
|
||||||
|
<y>200</y>
|
||||||
|
<width>101</width>
|
||||||
|
<height>41</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>11</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Convert</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="KCC.qrc">
|
||||||
|
<normaloff>:/Other/icons/convert.png</normaloff>:/Other/icons/convert.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="DirectoryButton">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>5</x>
|
||||||
|
<y>160</y>
|
||||||
|
<width>156</width>
|
||||||
|
<height>41</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>11</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Add directory</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="KCC.qrc">
|
||||||
|
<normaloff>:/Other/icons/folder_new.png</normaloff>:/Other/icons/folder_new.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="FileButton">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>260</x>
|
||||||
|
<y>160</y>
|
||||||
|
<width>157</width>
|
||||||
|
<height>41</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>11</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Add file</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="KCC.qrc">
|
||||||
|
<normaloff>:/Other/icons/document_new.png</normaloff>:/Other/icons/document_new.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="ClearButton">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>160</x>
|
||||||
|
<y>160</y>
|
||||||
|
<width>101</width>
|
||||||
|
<height>41</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>11</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Clear list</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="KCC.qrc">
|
||||||
|
<normaloff>:/Other/icons/clear.png</normaloff>:/Other/icons/clear.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QFrame" name="OptionsBasic">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>233</y>
|
||||||
|
<width>421</width>
|
||||||
|
<height>41</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<widget class="QCheckBox" name="MangaBox">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>9</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>130</width>
|
||||||
|
<height>18</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>11</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p><span style=" font-size:12pt;">Enable right-to-left reading.</span></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Manga mode</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QCheckBox" name="QualityBox">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>282</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>130</width>
|
||||||
|
<height>18</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>11</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><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></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>
|
||||||
|
<pointsize>11</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p><span style=" font-size:12pt;">Disable page spliting.<br/>They will be rotated instead.</span></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Horizontal mode</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<zorder>RotateBox</zorder>
|
||||||
|
<zorder>MangaBox</zorder>
|
||||||
|
<zorder>QualityBox</zorder>
|
||||||
|
</widget>
|
||||||
|
<widget class="QListWidget" name="JobList">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>50</y>
|
||||||
|
<width>401</width>
|
||||||
|
<height>101</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>11</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="showDropIndicator" stdset="0">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="selectionMode">
|
||||||
|
<enum>QAbstractItemView::NoSelection</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="BasicModeButton">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>5</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>210</width>
|
||||||
|
<height>41</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
|
<weight>50</weight>
|
||||||
|
<bold>false</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Basic</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="AdvModeButton">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>207</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>210</width>
|
||||||
|
<height>41</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
|
<weight>50</weight>
|
||||||
|
<bold>false</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Advanced</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QFrame" name="OptionsAdvancedGamma">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>303</y>
|
||||||
|
<width>401</width>
|
||||||
|
<height>41</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<widget class="QLabel" name="GammaLabel">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>20</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>100</width>
|
||||||
|
<height>40</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
|
<weight>50</weight>
|
||||||
|
<bold>false</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><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></string>
|
||||||
|
</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>280</width>
|
||||||
|
<height>22</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::ClickFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><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></string>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>500</number>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<widget class="QProgressBar" name="ProgressBar">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>401</width>
|
||||||
|
<height>35</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="autoFillBackground">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignJustify|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="format">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QFrame" name="OptionsExpert">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>335</y>
|
||||||
|
<width>421</width>
|
||||||
|
<height>41</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<widget class="QCheckBox" name="ColorBox">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>9</x>
|
||||||
|
<y>11</y>
|
||||||
|
<width>130</width>
|
||||||
|
<height>18</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>11</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p><span style=" font-size:12pt;">Do not convert images to grayscale.</span></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Color mode</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QFrame" name="OptionsExpertInternal">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>90</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>315</width>
|
||||||
|
<height>40</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="wLabel">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
|
<weight>50</weight>
|
||||||
|
<bold>false</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p><span style=" font-size:12pt;">Resolution of target device.</span></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Custom width: </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="customWidth">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>45</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::ClickFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="acceptDrops">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p><span style=" font-size:12pt;">Resolution of target device.</span></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="inputMask">
|
||||||
|
<string>0000; </string>
|
||||||
|
</property>
|
||||||
|
<property name="maxLength">
|
||||||
|
<number>4</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="2">
|
||||||
|
<widget class="QLabel" name="hLabel">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
|
<weight>50</weight>
|
||||||
|
<bold>false</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p><span style=" font-size:12pt;">Resolution of target device.</span></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Custom height: </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="3">
|
||||||
|
<widget class="QLineEdit" name="customHeight">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>45</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::ClickFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="acceptDrops">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p><span style=" font-size:12pt;">Resolution of target device.</span></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="inputMask">
|
||||||
|
<string>0000; </string>
|
||||||
|
</property>
|
||||||
|
<property name="maxLength">
|
||||||
|
<number>4</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<zorder>BasicModeButton</zorder>
|
||||||
|
<zorder>AdvModeButton</zorder>
|
||||||
|
<zorder>ProgressBar</zorder>
|
||||||
|
<zorder>JobList</zorder>
|
||||||
|
<zorder>OptionsAdvanced</zorder>
|
||||||
|
<zorder>DeviceBox</zorder>
|
||||||
|
<zorder>FormatBox</zorder>
|
||||||
|
<zorder>ConvertButton</zorder>
|
||||||
|
<zorder>DirectoryButton</zorder>
|
||||||
|
<zorder>FileButton</zorder>
|
||||||
|
<zorder>ClearButton</zorder>
|
||||||
|
<zorder>OptionsBasic</zorder>
|
||||||
|
<zorder>OptionsAdvancedGamma</zorder>
|
||||||
|
<zorder>OptionsExpert</zorder>
|
||||||
|
</widget>
|
||||||
|
<action name="ActionBasic">
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Basic</string>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="ActionAdvanced">
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Advanced</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
</widget>
|
||||||
|
<tabstops>
|
||||||
|
<tabstop>DirectoryButton</tabstop>
|
||||||
|
<tabstop>FileButton</tabstop>
|
||||||
|
<tabstop>ConvertButton</tabstop>
|
||||||
|
<tabstop>ClearButton</tabstop>
|
||||||
|
</tabstops>
|
||||||
|
<resources>
|
||||||
|
<include location="KCC.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
25
KCC.qrc
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<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>
|
||||||
694
KCC.ui
Normal file
@@ -0,0 +1,694 @@
|
|||||||
|
<?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>380</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>420</width>
|
||||||
|
<height>380</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>420</width>
|
||||||
|
<height>380</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Kindle Comic Converter</string>
|
||||||
|
</property>
|
||||||
|
<property name="windowIcon">
|
||||||
|
<iconset resource="KCC.qrc">
|
||||||
|
<normaloff>:/Icon/icons/comic2ebook.png</normaloff>:/Icon/icons/comic2ebook.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="locale">
|
||||||
|
<locale language="C" country="AnyCountry"/>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="Form">
|
||||||
|
<widget class="QFrame" name="OptionsAdvanced">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>254</y>
|
||||||
|
<width>421</width>
|
||||||
|
<height>61</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QCheckBox" name="ProcessingBox">
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Disable image optimizations.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>No optimisation</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QCheckBox" name="UpscaleBox">
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Enable image upscaling.<br/>Aspect ratio will be preserved.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Upscale images</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QCheckBox" name="StretchBox">
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Enable image stretching.<br/>Aspect ratio will be not preserved.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Stretch images</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="2">
|
||||||
|
<widget class="QCheckBox" name="NoDitheringBox">
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Create PNG files instead JPEG.<br/><span style=" font-weight:600;">Only for non-Kindle devices!</span></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>PNG output</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QCheckBox" name="BorderBox">
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Fill space around images with black color.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Black borders</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="2">
|
||||||
|
<widget class="QCheckBox" name="NoRotateBox">
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Disable splitting and rotation.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>No split/rotate</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QComboBox" name="DeviceBox">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>200</y>
|
||||||
|
<width>141</width>
|
||||||
|
<height>31</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>8</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Target device.</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QComboBox" name="FormatBox">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>260</x>
|
||||||
|
<y>200</y>
|
||||||
|
<width>151</width>
|
||||||
|
<height>31</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>8</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Output format.</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="ConvertButton">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>160</x>
|
||||||
|
<y>200</y>
|
||||||
|
<width>91</width>
|
||||||
|
<height>32</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Convert</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="KCC.qrc">
|
||||||
|
<normaloff>:/Other/icons/convert.png</normaloff>:/Other/icons/convert.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="DirectoryButton">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>160</y>
|
||||||
|
<width>141</width>
|
||||||
|
<height>32</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>8</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Add directory</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="KCC.qrc">
|
||||||
|
<normaloff>:/Other/icons/folder_new.png</normaloff>:/Other/icons/folder_new.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="FileButton">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>260</x>
|
||||||
|
<y>160</y>
|
||||||
|
<width>151</width>
|
||||||
|
<height>32</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>8</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Add file</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="KCC.qrc">
|
||||||
|
<normaloff>:/Other/icons/document_new.png</normaloff>:/Other/icons/document_new.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="ClearButton">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>160</x>
|
||||||
|
<y>160</y>
|
||||||
|
<width>91</width>
|
||||||
|
<height>32</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>8</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Clear list</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="KCC.qrc">
|
||||||
|
<normaloff>:/Other/icons/clear.png</normaloff>:/Other/icons/clear.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QFrame" name="OptionsBasic">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>230</y>
|
||||||
|
<width>421</width>
|
||||||
|
<height>41</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<widget class="QCheckBox" name="MangaBox">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>9</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>130</width>
|
||||||
|
<height>18</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Enable right-to-left reading.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Manga mode</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QCheckBox" name="QualityBox">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>282</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>130</width>
|
||||||
|
<height>18</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||||
|
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||||
|
p, li { white-space: pre-wrap; }
|
||||||
|
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;">
|
||||||
|
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">Unchecked - Normal quality mode<br /></span><span style=" font-style:italic;">Use it when Panel View support is not needed.</span><span style=" font-weight:600; text-decoration: underline;"><br /></span>- Maximum quality when zoom is not enabled.<br />- Poor quality when zoom is enabled.<br />- Lowest file size.</p>
|
||||||
|
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">Indeterminate - High quality mode<br /></span><span style=" font-style:italic;">Not zoomed image </span><span style=" font-weight:600; font-style:italic;">might </span><span style=" font-style:italic;">be </span><span style=" font-style:italic;">a little blurry.</span><span style=" font-weight:600; text-decoration: underline;"><br /></span>- Medium/High quality when zoom is not enabled.<br />- Maximum quality when zoom is enabled.</p>
|
||||||
|
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">Checked - Ultra quality mode<br /></span><span style=" font-style:italic;">Maximum possible quality.</span><span style=" font-weight:600; text-decoration: underline;"><br /></span>- Maximum quality when zoom is not enabled.<br />- Maximum quality when zoom is enabled.<br />- Very high file size.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>High/Ultra quality</string>
|
||||||
|
</property>
|
||||||
|
<property name="tristate">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QCheckBox" name="RotateBox">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>145</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>130</width>
|
||||||
|
<height>18</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Disable page spliting.<br/>They will be rotated instead.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Horizontal mode</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<zorder>RotateBox</zorder>
|
||||||
|
<zorder>MangaBox</zorder>
|
||||||
|
<zorder>QualityBox</zorder>
|
||||||
|
</widget>
|
||||||
|
<widget class="QListWidget" name="JobList">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>50</y>
|
||||||
|
<width>401</width>
|
||||||
|
<height>101</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="showDropIndicator" stdset="0">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="selectionMode">
|
||||||
|
<enum>QAbstractItemView::NoSelection</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="BasicModeButton">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>195</width>
|
||||||
|
<height>32</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Basic</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="AdvModeButton">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>217</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>195</width>
|
||||||
|
<height>32</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Advanced</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QFrame" name="OptionsAdvancedGamma">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>305</y>
|
||||||
|
<width>401</width>
|
||||||
|
<height>41</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<widget class="QLabel" name="GammaLabel">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>15</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>100</width>
|
||||||
|
<height>40</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>When converting color images setting this option to 1.0 MIGHT improve readability.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Gamma: Auto</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QSlider" name="GammaSlider">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>110</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>270</width>
|
||||||
|
<height>22</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::ClickFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><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></string>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>500</number>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<widget class="QProgressBar" name="ProgressBar">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>401</width>
|
||||||
|
<height>31</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignJustify|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="format">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QFrame" name="OptionsExpert">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>337</y>
|
||||||
|
<width>421</width>
|
||||||
|
<height>41</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<widget class="QCheckBox" name="ColorBox">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>9</x>
|
||||||
|
<y>11</y>
|
||||||
|
<width>130</width>
|
||||||
|
<height>18</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Do not convert images to grayscale.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Color mode</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QFrame" name="OptionsExpertInternal">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>100</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>295</width>
|
||||||
|
<height>40</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="wLabel">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Resolution of target device.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Custom width: </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="customWidth">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::ClickFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="acceptDrops">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Resolution of target device.</string>
|
||||||
|
</property>
|
||||||
|
<property name="inputMask">
|
||||||
|
<string>0000; </string>
|
||||||
|
</property>
|
||||||
|
<property name="maxLength">
|
||||||
|
<number>4</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="2">
|
||||||
|
<widget class="QLabel" name="hLabel">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Resolution of target device.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Custom height: </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="3">
|
||||||
|
<widget class="QLineEdit" name="customHeight">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::ClickFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="acceptDrops">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Resolution of target device.</string>
|
||||||
|
</property>
|
||||||
|
<property name="inputMask">
|
||||||
|
<string>0000; </string>
|
||||||
|
</property>
|
||||||
|
<property name="maxLength">
|
||||||
|
<number>4</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<zorder>OptionsAdvanced</zorder>
|
||||||
|
<zorder>DeviceBox</zorder>
|
||||||
|
<zorder>FormatBox</zorder>
|
||||||
|
<zorder>ConvertButton</zorder>
|
||||||
|
<zorder>DirectoryButton</zorder>
|
||||||
|
<zorder>FileButton</zorder>
|
||||||
|
<zorder>ClearButton</zorder>
|
||||||
|
<zorder>OptionsBasic</zorder>
|
||||||
|
<zorder>JobList</zorder>
|
||||||
|
<zorder>BasicModeButton</zorder>
|
||||||
|
<zorder>AdvModeButton</zorder>
|
||||||
|
<zorder>OptionsAdvancedGamma</zorder>
|
||||||
|
<zorder>OptionsExpert</zorder>
|
||||||
|
<zorder>ProgressBar</zorder>
|
||||||
|
</widget>
|
||||||
|
<action name="ActionBasic">
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Basic</string>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="ActionAdvanced">
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Advanced</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
</widget>
|
||||||
|
<tabstops>
|
||||||
|
<tabstop>DirectoryButton</tabstop>
|
||||||
|
<tabstop>FileButton</tabstop>
|
||||||
|
<tabstop>ConvertButton</tabstop>
|
||||||
|
<tabstop>ClearButton</tabstop>
|
||||||
|
</tabstops>
|
||||||
|
<resources>
|
||||||
|
<include location="KCC.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
ISC LICENSE
|
ISC LICENSE
|
||||||
|
|
||||||
Copyright (c) 2012 Ciro Mattia Gonano <ciromattia@gmail.com>
|
Copyright (c) 2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
|
Copyright (c) 2013 Paweł Jastrzębski <pawelj@vulturis.eu>
|
||||||
|
|
||||||
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
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
include README.md MANIFEST.in LICENSE.txt
|
|
||||||
102
README.md
@@ -1,31 +1,34 @@
|
|||||||
# KCC
|
# KCC
|
||||||
|
|
||||||
`KCC` (a.k.a. `KindleComicConverter`) is a Python app to convert comic files or folders to ePub or Panel View MOBI.
|
**KindleComicConverter** is a Python app to convert comic files or folders to ePub or Panel View MOBI.
|
||||||
It was initally developed for Kindle but since v2.2 it outputs valid ePub 2.0 so _**despite its name, KCC is
|
It was initally developed for Kindle but since v2.2 it outputs valid ePub 2.0 so _**despite its name, KCC is
|
||||||
actually a comic 2 epub converter that every ereader owner can happily use**_.
|
actually a comic 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 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.
|
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 ;)
|
||||||
|
|
||||||
|
### Donations
|
||||||
|
If you find **KCC** valuable you can consider donating to the authors:
|
||||||
|
|
||||||
|
* Ciro Mattia Gonano [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=D8WNYNPBGDAS2)
|
||||||
|
* Paweł Jastrzębski [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YTTJ4LK2JDHPS)
|
||||||
|
|
||||||
## 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:
|
||||||
- OS X: [https://dl.dropbox.com/u/16806101/KindleComicConverter_osx_2.10.zip](https://dl.dropbox.com/u/16806101/KindleComicConverter_osx_2.10.zip)
|
- **Win64:** [http://kcc.vulturis.eu/Win64/](http://kcc.vulturis.eu/Win64/)
|
||||||
- Win64: [https://dl.dropbox.com/u/16806101/KindleComicConverter_win-amd64_2.10.zip](https://dl.dropbox.com/u/16806101/KindleComicConverter_win-amd64_2.10.zip)
|
- **Win32:** [http://kcc.vulturis.eu/Win32/](http://kcc.vulturis.eu/Win32/)
|
||||||
- Win32: [http://pawelj.vulturis.eu/Shared/KindleComicConverter_win-x86_2.10.zip](http://pawelj.vulturis.eu/Shared/KindleComicConverter_win-x86_2.10.zip)
|
- **OS X:** [http://kcc.vulturis.eu/OSX/](http://kcc.vulturis.eu/OSX/)
|
||||||
- Linux: Just download sourcecode and launch `python kcc.py` *(Provided you have Python and Pillow installed)*
|
- **Linux:** Just download sourcecode and launch: `python kcc.py`
|
||||||
|
|
||||||
## AWKCC .NET GUI
|
_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.
|
||||||

|
If it happens to you please append your message to [Issue #52](https://github.com/ciromattia/kcc/issues/52)._
|
||||||
|
|
||||||
[All-in-one package for Windows users](http://www.mobileread.com/forums/showpost.php?p=2444957&postcount=3)
|
|
||||||
|
|
||||||
## 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 file types:
|
||||||
- PNG, JPG, GIF, TIFF, BMP
|
- PNG, JPG, GIF, TIFF, BMP
|
||||||
- Folders
|
- Folders
|
||||||
- CBZ, ZIP
|
- CBZ, ZIP
|
||||||
@@ -33,21 +36,30 @@ You can find the latest released binary at the following links:
|
|||||||
- PDF *(Extracting only contained JPG images)*
|
- PDF *(Extracting only contained JPG images)*
|
||||||
|
|
||||||
## OPTIONAL REQUIREMENTS
|
## OPTIONAL REQUIREMENTS
|
||||||
- `kindlegen` v2.7+ in a directory reachable by your PATH or in KCC directory *(For .mobi generation)*
|
- [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 support)*
|
- [UnRAR](http://www.rarlab.com/download.htm) *(For CBR/RAR support)*
|
||||||
|
|
||||||
### For compiling/running from source:
|
### 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)
|
- Python 2.7 - Included in MacOS and Linux, follow the [official documentation](http://www.python.org/getit/windows/) to install on Windows.
|
||||||
- [Pillow](http://pypi.python.org/pypi/Pillow/) for comic optimizations like split double pages, resize to optimal resolution, improve contrast and palette, etc.
|
- PyQt4 - Please refer to official documentation for installing into your system.
|
||||||
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
|
||||||
|
|
||||||
### GUI
|
### Important tips:
|
||||||
|
* Use high quality source files. **This little detail have a major impact on the final result.**
|
||||||
|
* Read tooltip of _High/Ultra quality_ option. There are many important informations there.
|
||||||
|
* When converting images smaller than device resolution remember to enable upscaling.
|
||||||
|
* 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).
|
||||||
|
|
||||||
Should be pretty self-explanatory, just keep in mind that it's still in development ;)
|
### GUI
|
||||||
While working it seems frozen, I'll try to fix the aesthetics later.
|
|
||||||
Conversion being done, you should find an .epub and a .mobi files alongside the original input file (same directory)
|
Should be pretty self-explanatory.
|
||||||
|
After completed conversion you should find ready file alongside the original input file (same directory).
|
||||||
|
|
||||||
### Standalone `comic2ebook.py` usage:
|
### Standalone `comic2ebook.py` usage:
|
||||||
|
|
||||||
@@ -62,8 +74,8 @@ Options:
|
|||||||
-t TITLE, --title=TITLE
|
-t TITLE, --title=TITLE
|
||||||
Comic title [Default=filename]
|
Comic title [Default=filename]
|
||||||
-m, --manga-style Manga style (Right-to-left reading and splitting) [Default=False]
|
-m, --manga-style Manga style (Right-to-left reading and splitting) [Default=False]
|
||||||
|
--quality=QUALITY Output quality. 0 - Normal 1 - High 2 - Ultra [Default=0]
|
||||||
-c, --cbz-output Outputs a CBZ archive and does not generate EPUB
|
-c, --cbz-output Outputs a CBZ archive and does not generate EPUB
|
||||||
--nopanelviewhq Disable high quality Panel View [Default=False]
|
|
||||||
--noprocessing Do not apply image preprocessing (Page splitting and optimizations) [Default=True]
|
--noprocessing Do not apply image preprocessing (Page splitting and optimizations) [Default=True]
|
||||||
--forcepng Create PNG files instead JPEG (For non-Kindle devices) [Default=False]
|
--forcepng Create PNG files instead JPEG (For non-Kindle devices) [Default=False]
|
||||||
--gamma=GAMMA Apply gamma correction to linearize the image [Default=Auto]
|
--gamma=GAMMA Apply gamma correction to linearize the image [Default=Auto]
|
||||||
@@ -75,22 +87,35 @@ Options:
|
|||||||
--nocutpagenumbers Do not try to cut page numbering on images [Default=True]
|
--nocutpagenumbers Do not try to cut page numbering on images [Default=True]
|
||||||
-o OUTPUT, --output=OUTPUT
|
-o OUTPUT, --output=OUTPUT
|
||||||
Output generated file (EPUB or CBZ) to specified directory or file
|
Output generated file (EPUB or CBZ) to specified directory or file
|
||||||
|
--forcecolor Do not convert images to grayscale [Default=False]
|
||||||
|
--customwidth=WIDTH Replace screen width provided by device profile [Default=0]
|
||||||
|
--customheight=HEIGHT Replace screen height provided by device profile [Default=0]
|
||||||
-v, --verbose Verbose output [Default=False]
|
-v, --verbose Verbose output [Default=False]
|
||||||
```
|
```
|
||||||
|
|
||||||
## 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 in [this mobileread forum thread](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/binaries:
|
||||||
|
|
||||||
- `KindleStrip` script © 2010-2012 by **Paul Durrant** and released in public domain
|
- `KindleStrip` script © 2010-2012 by **Paul Durrant** and released in public domain
|
||||||
([mobileread forum thread](http://www.mobileread.com/forums/showthread.php?t=96903))
|
([forum thread](http://www.mobileread.com/forums/showthread.php?t=96903))
|
||||||
- `rarfile.py` script © 2005-2011 **Marko Kreen** <markokr@gmail.com>, released with ISC License
|
- `rarfile.py` script © 2005-2011 **Marko Kreen** <markokr@gmail.com>, released with ISC License
|
||||||
- the icon is by **Nikolay Verin** ([http://ncrow.deviantart.com/](http://ncrow.deviantart.com/)) and released under [CC Attribution-NonCommercial-ShareAlike 3.0 Unported](http://creativecommons.org/licenses/by-nc-sa/3.0/) License
|
|
||||||
- `image.py` class from **Alex Yatskov**'s [Mangle](http://foosoft.net/mangle/) with subsequent [proDOOMman](https://github.com/proDOOMman/Mangle)'s and [Birua](https://github.com/Birua/Mangle)'s patches
|
- `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
|
||||||
- `magic.py` from [python-magic](https://github.com/ahupp/python-magic) library
|
- Icon is by **Nikolay Verin** ([http://ncrow.deviantart.com/](http://ncrow.deviantart.com/)) and released under [CC BY-NC-SA 3.0](http://creativecommons.org/licenses/by-nc-sa/3.0/) License
|
||||||
|
|
||||||
|
## SAMPLE FILES CREATED BY KCC
|
||||||
|
* [Kindle Keyboard](http://kcc.vulturis.eu/Samples/Ubunchu!-K3.mobi)
|
||||||
|
* [Kindle DX](http://kcc.vulturis.eu/Samples/Ubunchu!-KDX.mobi)
|
||||||
|
* [Kindle DXG](http://kcc.vulturis.eu/Samples/Ubunchu!-KDXG.mobi)
|
||||||
|
* [Kindle Non-Touch](http://kcc.vulturis.eu/Samples/Ubunchu!-K4NT.mobi)
|
||||||
|
* [Kindle Touch](http://kcc.vulturis.eu/Samples/Ubunchu!-K4T.mobi)
|
||||||
|
* [Kindle Paperwhite](http://kcc.vulturis.eu/Samples/Ubunchu!-KPW.mobi)
|
||||||
|
* [Kindle Fire](http://kcc.vulturis.eu/Samples/Ubunchu!-KF.mobi)
|
||||||
|
* [Kindle Fire HD](http://kcc.vulturis.eu/Samples/Ubunchu!-KFHD.mobi)
|
||||||
|
* [Kindle Fire HD 8.9"](http://kcc.vulturis.eu/Samples/Ubunchu!-KFHD8.mobi)
|
||||||
|
|
||||||
## CHANGELOG
|
## CHANGELOG
|
||||||
####1.00
|
####1.00
|
||||||
@@ -179,9 +204,20 @@ The app relies and includes the following scripts/binaries:
|
|||||||
* Panel View support for horizontal content
|
* Panel View support for horizontal content
|
||||||
* Fixed panel order for horizontal pages when --rotate is enabled
|
* Fixed panel order for horizontal pages when --rotate is enabled
|
||||||
* Disabled cropping and page number cutting for blank pages
|
* Disabled cropping and page number cutting for blank pages
|
||||||
* Fixed some slugify issues with specific file naming conventions (#50, #51)
|
* Fixed some slugify issues with specific file naming conventions (#50, #51)
|
||||||
|
|
||||||
|
####3.0:
|
||||||
|
* New QT GUI
|
||||||
|
* Merge with AWKCC
|
||||||
|
* Added ultra quality mode
|
||||||
|
* Added support for custom width/height
|
||||||
|
* Added option to disable color conversion
|
||||||
|
|
||||||
|
## 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)
|
||||||
|
* Removing SRCS headers sometimes fail in 32bit enviroments. Due to memory limitations.
|
||||||
|
|
||||||
## COPYRIGHT
|
## COPYRIGHT
|
||||||
|
|
||||||
Copyright (c) 2012-2013 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.
|
||||||
|
|||||||
284
ez_setup.py
@@ -1,284 +0,0 @@
|
|||||||
#!python
|
|
||||||
"""Bootstrap setuptools installation
|
|
||||||
|
|
||||||
If you want to use setuptools in your package's setup.py, just include this
|
|
||||||
file in the same directory with it, and add this to the top of your setup.py::
|
|
||||||
|
|
||||||
from ez_setup import use_setuptools
|
|
||||||
use_setuptools()
|
|
||||||
|
|
||||||
If you want to require a specific version of setuptools, set a download
|
|
||||||
mirror, or use an alternate download directory, you can do so by supplying
|
|
||||||
the appropriate options to ``use_setuptools()``.
|
|
||||||
|
|
||||||
This file can also be run as a script to install or upgrade setuptools.
|
|
||||||
"""
|
|
||||||
import sys
|
|
||||||
DEFAULT_VERSION = "0.6c11"
|
|
||||||
DEFAULT_URL = "http://pypi.python.org/packages/%s/s/setuptools/" % sys.version[:3]
|
|
||||||
|
|
||||||
md5_data = {
|
|
||||||
'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca',
|
|
||||||
'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb',
|
|
||||||
'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b',
|
|
||||||
'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a',
|
|
||||||
'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618',
|
|
||||||
'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac',
|
|
||||||
'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5',
|
|
||||||
'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4',
|
|
||||||
'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c',
|
|
||||||
'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b',
|
|
||||||
'setuptools-0.6c10-py2.3.egg': 'ce1e2ab5d3a0256456d9fc13800a7090',
|
|
||||||
'setuptools-0.6c10-py2.4.egg': '57d6d9d6e9b80772c59a53a8433a5dd4',
|
|
||||||
'setuptools-0.6c10-py2.5.egg': 'de46ac8b1c97c895572e5e8596aeb8c7',
|
|
||||||
'setuptools-0.6c10-py2.6.egg': '58ea40aef06da02ce641495523a0b7f5',
|
|
||||||
'setuptools-0.6c11-py2.3.egg': '2baeac6e13d414a9d28e7ba5b5a596de',
|
|
||||||
'setuptools-0.6c11-py2.4.egg': 'bd639f9b0eac4c42497034dec2ec0c2b',
|
|
||||||
'setuptools-0.6c11-py2.5.egg': '64c94f3bf7a72a13ec83e0b24f2749b2',
|
|
||||||
'setuptools-0.6c11-py2.6.egg': 'bfa92100bd772d5a213eedd356d64086',
|
|
||||||
'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27',
|
|
||||||
'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277',
|
|
||||||
'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa',
|
|
||||||
'setuptools-0.6c3-py2.4.egg': 'e0ed74682c998bfb73bf803a50e7b71e',
|
|
||||||
'setuptools-0.6c3-py2.5.egg': 'abef16fdd61955514841c7c6bd98965e',
|
|
||||||
'setuptools-0.6c4-py2.3.egg': 'b0b9131acab32022bfac7f44c5d7971f',
|
|
||||||
'setuptools-0.6c4-py2.4.egg': '2a1f9656d4fbf3c97bf946c0a124e6e2',
|
|
||||||
'setuptools-0.6c4-py2.5.egg': '8f5a052e32cdb9c72bcf4b5526f28afc',
|
|
||||||
'setuptools-0.6c5-py2.3.egg': 'ee9fd80965da04f2f3e6b3576e9d8167',
|
|
||||||
'setuptools-0.6c5-py2.4.egg': 'afe2adf1c01701ee841761f5bcd8aa64',
|
|
||||||
'setuptools-0.6c5-py2.5.egg': 'a8d3f61494ccaa8714dfed37bccd3d5d',
|
|
||||||
'setuptools-0.6c6-py2.3.egg': '35686b78116a668847237b69d549ec20',
|
|
||||||
'setuptools-0.6c6-py2.4.egg': '3c56af57be3225019260a644430065ab',
|
|
||||||
'setuptools-0.6c6-py2.5.egg': 'b2f8a7520709a5b34f80946de5f02f53',
|
|
||||||
'setuptools-0.6c7-py2.3.egg': '209fdf9adc3a615e5115b725658e13e2',
|
|
||||||
'setuptools-0.6c7-py2.4.egg': '5a8f954807d46a0fb67cf1f26c55a82e',
|
|
||||||
'setuptools-0.6c7-py2.5.egg': '45d2ad28f9750e7434111fde831e8372',
|
|
||||||
'setuptools-0.6c8-py2.3.egg': '50759d29b349db8cfd807ba8303f1902',
|
|
||||||
'setuptools-0.6c8-py2.4.egg': 'cba38d74f7d483c06e9daa6070cce6de',
|
|
||||||
'setuptools-0.6c8-py2.5.egg': '1721747ee329dc150590a58b3e1ac95b',
|
|
||||||
'setuptools-0.6c9-py2.3.egg': 'a83c4020414807b496e4cfbe08507c03',
|
|
||||||
'setuptools-0.6c9-py2.4.egg': '260a2be2e5388d66bdaee06abec6342a',
|
|
||||||
'setuptools-0.6c9-py2.5.egg': 'fe67c3e5a17b12c0e7c541b7ea43a8e6',
|
|
||||||
'setuptools-0.6c9-py2.6.egg': 'ca37b1ff16fa2ede6e19383e7b59245a',
|
|
||||||
}
|
|
||||||
|
|
||||||
import sys, os
|
|
||||||
try: from hashlib import md5
|
|
||||||
except ImportError: from md5 import md5
|
|
||||||
|
|
||||||
def _validate_md5(egg_name, data):
|
|
||||||
if egg_name in md5_data:
|
|
||||||
digest = md5(data).hexdigest()
|
|
||||||
if digest != md5_data[egg_name]:
|
|
||||||
print >>sys.stderr, (
|
|
||||||
"md5 validation of %s failed! (Possible download problem?)"
|
|
||||||
% egg_name
|
|
||||||
)
|
|
||||||
sys.exit(2)
|
|
||||||
return data
|
|
||||||
|
|
||||||
def use_setuptools(
|
|
||||||
version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
|
|
||||||
download_delay=15
|
|
||||||
):
|
|
||||||
"""Automatically find/download setuptools and make it available on sys.path
|
|
||||||
|
|
||||||
`version` should be a valid setuptools version number that is available
|
|
||||||
as an egg for download under the `download_base` URL (which should end with
|
|
||||||
a '/'). `to_dir` is the directory where setuptools will be downloaded, if
|
|
||||||
it is not already available. If `download_delay` is specified, it should
|
|
||||||
be the number of seconds that will be paused before initiating a download,
|
|
||||||
should one be required. If an older version of setuptools is installed,
|
|
||||||
this routine will print a message to ``sys.stderr`` and raise SystemExit in
|
|
||||||
an attempt to abort the calling script.
|
|
||||||
"""
|
|
||||||
was_imported = 'pkg_resources' in sys.modules or 'setuptools' in sys.modules
|
|
||||||
def do_download():
|
|
||||||
egg = download_setuptools(version, download_base, to_dir, download_delay)
|
|
||||||
sys.path.insert(0, egg)
|
|
||||||
import setuptools; setuptools.bootstrap_install_from = egg
|
|
||||||
try:
|
|
||||||
import pkg_resources
|
|
||||||
except ImportError:
|
|
||||||
return do_download()
|
|
||||||
try:
|
|
||||||
pkg_resources.require("setuptools>="+version); return
|
|
||||||
except pkg_resources.VersionConflict, e:
|
|
||||||
if was_imported:
|
|
||||||
print >>sys.stderr, (
|
|
||||||
"The required version of setuptools (>=%s) is not available, and\n"
|
|
||||||
"can't be installed while this script is running. Please install\n"
|
|
||||||
" a more recent version first, using 'easy_install -U setuptools'."
|
|
||||||
"\n\n(Currently using %r)"
|
|
||||||
) % (version, e.args[0])
|
|
||||||
sys.exit(2)
|
|
||||||
except pkg_resources.DistributionNotFound:
|
|
||||||
pass
|
|
||||||
|
|
||||||
del pkg_resources, sys.modules['pkg_resources'] # reload ok
|
|
||||||
return do_download()
|
|
||||||
|
|
||||||
def download_setuptools(
|
|
||||||
version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
|
|
||||||
delay = 15
|
|
||||||
):
|
|
||||||
"""Download setuptools from a specified location and return its filename
|
|
||||||
|
|
||||||
`version` should be a valid setuptools version number that is available
|
|
||||||
as an egg for download under the `download_base` URL (which should end
|
|
||||||
with a '/'). `to_dir` is the directory where the egg will be downloaded.
|
|
||||||
`delay` is the number of seconds to pause before an actual download attempt.
|
|
||||||
"""
|
|
||||||
import urllib2, shutil
|
|
||||||
egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3])
|
|
||||||
url = download_base + egg_name
|
|
||||||
saveto = os.path.join(to_dir, egg_name)
|
|
||||||
src = dst = None
|
|
||||||
if not os.path.exists(saveto): # Avoid repeated downloads
|
|
||||||
try:
|
|
||||||
from distutils import log
|
|
||||||
if delay:
|
|
||||||
log.warn("""
|
|
||||||
---------------------------------------------------------------------------
|
|
||||||
This script requires setuptools version %s to run (even to display
|
|
||||||
help). I will attempt to download it for you (from
|
|
||||||
%s), but
|
|
||||||
you may need to enable firewall access for this script first.
|
|
||||||
I will start the download in %d seconds.
|
|
||||||
|
|
||||||
(Note: if this machine does not have network access, please obtain the file
|
|
||||||
|
|
||||||
%s
|
|
||||||
|
|
||||||
and place it in this directory before rerunning this script.)
|
|
||||||
---------------------------------------------------------------------------""",
|
|
||||||
version, download_base, delay, url
|
|
||||||
); from time import sleep; sleep(delay)
|
|
||||||
log.warn("Downloading %s", url)
|
|
||||||
src = urllib2.urlopen(url)
|
|
||||||
# Read/write all in one block, so we don't create a corrupt file
|
|
||||||
# if the download is interrupted.
|
|
||||||
data = _validate_md5(egg_name, src.read())
|
|
||||||
dst = open(saveto,"wb"); dst.write(data)
|
|
||||||
finally:
|
|
||||||
if src: src.close()
|
|
||||||
if dst: dst.close()
|
|
||||||
return os.path.realpath(saveto)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def main(argv, version=DEFAULT_VERSION):
|
|
||||||
"""Install or upgrade setuptools and EasyInstall"""
|
|
||||||
try:
|
|
||||||
import setuptools
|
|
||||||
except ImportError:
|
|
||||||
egg = None
|
|
||||||
try:
|
|
||||||
egg = download_setuptools(version, delay=0)
|
|
||||||
sys.path.insert(0,egg)
|
|
||||||
from setuptools.command.easy_install import main
|
|
||||||
return main(list(argv)+[egg]) # we're done here
|
|
||||||
finally:
|
|
||||||
if egg and os.path.exists(egg):
|
|
||||||
os.unlink(egg)
|
|
||||||
else:
|
|
||||||
if setuptools.__version__ == '0.0.1':
|
|
||||||
print >>sys.stderr, (
|
|
||||||
"You have an obsolete version of setuptools installed. Please\n"
|
|
||||||
"remove it from your system entirely before rerunning this script."
|
|
||||||
)
|
|
||||||
sys.exit(2)
|
|
||||||
|
|
||||||
req = "setuptools>="+version
|
|
||||||
import pkg_resources
|
|
||||||
try:
|
|
||||||
pkg_resources.require(req)
|
|
||||||
except pkg_resources.VersionConflict:
|
|
||||||
try:
|
|
||||||
from setuptools.command.easy_install import main
|
|
||||||
except ImportError:
|
|
||||||
from easy_install import main
|
|
||||||
main(list(argv)+[download_setuptools(delay=0)])
|
|
||||||
sys.exit(0) # try to force an exit
|
|
||||||
else:
|
|
||||||
if argv:
|
|
||||||
from setuptools.command.easy_install import main
|
|
||||||
main(argv)
|
|
||||||
else:
|
|
||||||
print "Setuptools version",version,"or greater has been installed."
|
|
||||||
print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)'
|
|
||||||
|
|
||||||
def update_md5(filenames):
|
|
||||||
"""Update our built-in md5 registry"""
|
|
||||||
|
|
||||||
import re
|
|
||||||
|
|
||||||
for name in filenames:
|
|
||||||
base = os.path.basename(name)
|
|
||||||
f = open(name,'rb')
|
|
||||||
md5_data[base] = md5(f.read()).hexdigest()
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
data = [" %r: %r,\n" % it for it in md5_data.items()]
|
|
||||||
data.sort()
|
|
||||||
repl = "".join(data)
|
|
||||||
|
|
||||||
import inspect
|
|
||||||
srcfile = inspect.getsourcefile(sys.modules[__name__])
|
|
||||||
f = open(srcfile, 'rb'); src = f.read(); f.close()
|
|
||||||
|
|
||||||
match = re.search("\nmd5_data = {\n([^}]+)}", src)
|
|
||||||
if not match:
|
|
||||||
print >>sys.stderr, "Internal error!"
|
|
||||||
sys.exit(2)
|
|
||||||
|
|
||||||
src = src[:match.start(1)] + repl + src[match.end(1):]
|
|
||||||
f = open(srcfile,'w')
|
|
||||||
f.write(src)
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__=='__main__':
|
|
||||||
if len(sys.argv)>2 and sys.argv[1]=='--md5update':
|
|
||||||
update_md5(sys.argv[2:])
|
|
||||||
else:
|
|
||||||
main(sys.argv[1:])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BIN
icons/CBZ.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
icons/EPUB.png
Normal file
|
After Width: | Height: | Size: 7.1 KiB |
BIN
icons/Kindle.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
icons/MOBI.png
Normal file
|
After Width: | Height: | Size: 7.8 KiB |
BIN
icons/Other.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
icons/clear.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 345 KiB After Width: | Height: | Size: 345 KiB |
BIN
icons/comic2ebook.png
Normal file
|
After Width: | Height: | Size: 71 KiB |
BIN
icons/convert.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
icons/document_new.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
icons/error.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
icons/folder_new.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
icons/info.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
icons/warning.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
44
kcc.py
@@ -1,4 +1,5 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
#
|
#
|
||||||
@@ -16,26 +17,35 @@
|
|||||||
# 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__ = '2.10'
|
__version__ = '3.0'
|
||||||
__license__ = 'ISC'
|
__license__ = 'ISC'
|
||||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>'
|
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
from Tkinter import *
|
import sys
|
||||||
from kcc import gui
|
|
||||||
from sys import platform
|
|
||||||
from multiprocessing import freeze_support
|
|
||||||
import os
|
import os
|
||||||
|
try:
|
||||||
|
# noinspection PyUnresolvedReferences
|
||||||
|
from PyQt4 import QtGui
|
||||||
|
except ImportError:
|
||||||
|
print "ERROR: PyQT4 is not installed!"
|
||||||
|
exit(1)
|
||||||
|
from kcc import KCC_gui
|
||||||
|
from multiprocessing import freeze_support
|
||||||
|
|
||||||
|
if sys.platform == 'darwin':
|
||||||
|
os.environ['PATH'] = '/usr/local/bin:' + os.environ['PATH']
|
||||||
|
from kcc import KCC_ui_osx as KCC_ui
|
||||||
|
else:
|
||||||
|
from kcc import KCC_ui
|
||||||
|
|
||||||
freeze_support()
|
freeze_support()
|
||||||
root = Tk()
|
APP = QtGui.QApplication(sys.argv)
|
||||||
root.resizable(width=False, height=False)
|
KCC = QtGui.QMainWindow()
|
||||||
root.config(padx=5, pady=5, takefocus=True)
|
UI = KCC_ui.Ui_KCC()
|
||||||
root.title("Kindle Comic Converter v" + __version__)
|
UI.setupUi(KCC)
|
||||||
#root.wm_attributes("-topmost", 1)
|
GUI = KCC_gui.Ui_KCC(UI, KCC)
|
||||||
if platform == 'darwin':
|
KCC.setWindowTitle("Kindle Comic Converter " + __version__)
|
||||||
os.environ['PATH'] = '/usr/local/bin:' + os.environ['PATH']
|
KCC.show()
|
||||||
elif platform == 'win32':
|
KCC.raise_()
|
||||||
root.iconbitmap(default='comic2ebook.ico')
|
sys.exit(APP.exec_())
|
||||||
gui.MainWindow(master=root)
|
|
||||||
root.mainloop()
|
|
||||||
|
|||||||
480
kcc/KCC_gui.py
Normal file
@@ -0,0 +1,480 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (c) 2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
|
#
|
||||||
|
# Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
# any purpose with or without fee is hereby granted, provided that the
|
||||||
|
# above copyright notice and this permission notice appear in all
|
||||||
|
# copies.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
# AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
|
||||||
|
# OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
# PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
__version__ = '3.0'
|
||||||
|
__license__ = 'ISC'
|
||||||
|
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import shutil
|
||||||
|
import traceback
|
||||||
|
import urllib2
|
||||||
|
import comic2ebook
|
||||||
|
import kindlestrip
|
||||||
|
from image import ProfileData
|
||||||
|
from subprocess import call, Popen, STDOUT, PIPE
|
||||||
|
from PyQt4 import QtGui, QtCore
|
||||||
|
from xml.dom.minidom import parse
|
||||||
|
|
||||||
|
|
||||||
|
class Icons:
|
||||||
|
def __init__(self):
|
||||||
|
self.deviceKindle = QtGui.QIcon()
|
||||||
|
self.deviceKindle.addPixmap(QtGui.QPixmap(":/Devices/icons/Kindle.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
self.deviceOther = QtGui.QIcon()
|
||||||
|
self.deviceOther.addPixmap(QtGui.QPixmap(":/Devices/icons/Other.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
|
||||||
|
self.MOBIFormat = QtGui.QIcon()
|
||||||
|
self.MOBIFormat.addPixmap(QtGui.QPixmap(":/Formats/icons/MOBI.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
self.CBZFormat = QtGui.QIcon()
|
||||||
|
self.CBZFormat.addPixmap(QtGui.QPixmap(":/Formats/icons/CBZ.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
self.EPUBFormat = QtGui.QIcon()
|
||||||
|
self.EPUBFormat.addPixmap(QtGui.QPixmap(":/Formats/icons/EPUB.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
|
||||||
|
self.info = QtGui.QIcon()
|
||||||
|
self.info.addPixmap(QtGui.QPixmap(":/Status/icons/info.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
self.warning = QtGui.QIcon()
|
||||||
|
self.warning.addPixmap(QtGui.QPixmap(":/Status/icons/warning.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
self.error = QtGui.QIcon()
|
||||||
|
self.error.addPixmap(QtGui.QPixmap(":/Status/icons/error.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
|
||||||
|
|
||||||
|
# noinspection PyBroadException
|
||||||
|
class VersionThread(QtCore.QThread):
|
||||||
|
def __init__(self, parent):
|
||||||
|
QtCore.QThread.__init__(self)
|
||||||
|
self.parent = parent
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
self.wait()
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
try:
|
||||||
|
XML = urllib2.urlopen('http://kcc.vulturis.eu/Version.php')
|
||||||
|
XML = parse(XML)
|
||||||
|
except Exception:
|
||||||
|
return
|
||||||
|
latestVersion = XML.childNodes[0].getElementsByTagName('latest')[0].childNodes[0].toxml()
|
||||||
|
if tuple(map(int, (latestVersion.split(".")))) > tuple(map(int, (__version__.split(".")))):
|
||||||
|
self.emit(QtCore.SIGNAL("addMessage"), 'New version is available!', 'warning')
|
||||||
|
|
||||||
|
|
||||||
|
# noinspection PyBroadException
|
||||||
|
class WorkerThread(QtCore.QThread):
|
||||||
|
def __init__(self, parent):
|
||||||
|
QtCore.QThread.__init__(self)
|
||||||
|
self.parent = parent
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
self.wait()
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self.emit(QtCore.SIGNAL("modeConvert"), False)
|
||||||
|
profile = ProfileData.ProfileLabels[str(GUI.DeviceBox.currentText())]
|
||||||
|
argv = ["--profile=" + profile]
|
||||||
|
currentJobs = []
|
||||||
|
if GUI.MangaBox.isChecked():
|
||||||
|
argv.append("--manga-style")
|
||||||
|
if GUI.RotateBox.isChecked():
|
||||||
|
argv.append("--rotate")
|
||||||
|
if GUI.QualityBox.checkState() == 1:
|
||||||
|
argv.append("--quality=1")
|
||||||
|
elif GUI.QualityBox.checkState() == 2:
|
||||||
|
argv.append("--quality=2")
|
||||||
|
if self.parent.currentMode > 1:
|
||||||
|
if GUI.ProcessingBox.isChecked():
|
||||||
|
argv.append("--noprocessing")
|
||||||
|
if GUI.UpscaleBox.isChecked() and not GUI.StretchBox.isChecked():
|
||||||
|
argv.append("--upscale")
|
||||||
|
if GUI.NoRotateBox.isChecked():
|
||||||
|
argv.append("--nosplitrotate")
|
||||||
|
if GUI.BorderBox.isChecked():
|
||||||
|
argv.append("--blackborders")
|
||||||
|
if GUI.StretchBox.isChecked():
|
||||||
|
argv.append("--stretch")
|
||||||
|
if GUI.NoDitheringBox.isChecked():
|
||||||
|
argv.append("--forcepng")
|
||||||
|
if float(self.parent.GammaValue) > 0.09:
|
||||||
|
argv.append("--gamma=" + self.parent.GammaValue)
|
||||||
|
if str(GUI.FormatBox.currentText()) == 'CBZ':
|
||||||
|
argv.append("--cbz-output")
|
||||||
|
if self.parent.currentMode > 2:
|
||||||
|
argv.append("--customwidth=" + str(GUI.customWidth.text()))
|
||||||
|
argv.append("--customheight=" + str(GUI.customHeight.text()))
|
||||||
|
if GUI.ColorBox.isChecked():
|
||||||
|
argv.append("--forcecolor")
|
||||||
|
for i in range(GUI.JobList.count()):
|
||||||
|
currentJobs.append(str(GUI.JobList.item(i).text()))
|
||||||
|
GUI.JobList.clear()
|
||||||
|
for job in currentJobs:
|
||||||
|
self.errors = False
|
||||||
|
self.emit(QtCore.SIGNAL("addMessage"), 'Source: ' + job, 'info')
|
||||||
|
if str(GUI.FormatBox.currentText()) == 'CBZ':
|
||||||
|
self.emit(QtCore.SIGNAL("addMessage"), 'Creating CBZ file...', 'info')
|
||||||
|
else:
|
||||||
|
self.emit(QtCore.SIGNAL("addMessage"), 'Creating EPUB file...', 'info')
|
||||||
|
jobargv = list(argv)
|
||||||
|
jobargv.append(job)
|
||||||
|
try:
|
||||||
|
outputPath = comic2ebook.main(jobargv, self)
|
||||||
|
self.emit(QtCore.SIGNAL("hideProgressBar"))
|
||||||
|
except Exception as err:
|
||||||
|
self.errors = True
|
||||||
|
type_, value_, traceback_ = sys.exc_info()
|
||||||
|
self.emit(QtCore.SIGNAL("showDialog"), "Error during conversion %s:\n\n%s\n\nTraceback:\n%s"
|
||||||
|
% (jobargv[-1], str(err), traceback.format_tb(traceback_)))
|
||||||
|
self.emit(QtCore.SIGNAL("addMessage"), 'KCC failed to create EPUB!', 'error')
|
||||||
|
if not self.errors:
|
||||||
|
if str(GUI.FormatBox.currentText()) == 'CBZ':
|
||||||
|
self.emit(QtCore.SIGNAL("addMessage"), 'Creating CBZ file... Done!', 'info', True)
|
||||||
|
else:
|
||||||
|
self.emit(QtCore.SIGNAL("addMessage"), 'Creating EPUB file... Done!', 'info', True)
|
||||||
|
if str(GUI.FormatBox.currentText()) == 'MOBI':
|
||||||
|
if not os.path.getsize(outputPath) > 314572800:
|
||||||
|
self.emit(QtCore.SIGNAL("addMessage"), 'Creating MOBI file...', 'info')
|
||||||
|
self.emit(QtCore.SIGNAL("progressBarTick"), 1)
|
||||||
|
try:
|
||||||
|
retcode = call('kindlegen -verbose "' + outputPath + '"', shell=True)
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
if retcode == 0:
|
||||||
|
self.emit(QtCore.SIGNAL("addMessage"), 'Creating MOBI file... Done!', 'info', True)
|
||||||
|
self.emit(QtCore.SIGNAL("addMessage"), 'Removing SRCS header...', 'info')
|
||||||
|
os.remove(outputPath)
|
||||||
|
mobiPath = outputPath.replace('.epub', '.mobi')
|
||||||
|
shutil.move(mobiPath, mobiPath + '_tostrip')
|
||||||
|
try:
|
||||||
|
kindlestrip.main((mobiPath + '_tostrip', mobiPath))
|
||||||
|
except Exception:
|
||||||
|
self.errors = True
|
||||||
|
if not self.errors:
|
||||||
|
os.remove(mobiPath + '_tostrip')
|
||||||
|
self.emit(QtCore.SIGNAL("addMessage"), 'Removing SRCS header... Done!', 'info', True)
|
||||||
|
else:
|
||||||
|
shutil.move(mobiPath + '_tostrip', mobiPath)
|
||||||
|
self.emit(QtCore.SIGNAL("addMessage"),
|
||||||
|
'KindleStrip failed to remove SRCS header!', 'warning')
|
||||||
|
self.emit(QtCore.SIGNAL("addMessage"),
|
||||||
|
'MOBI file will work correctly but it will be highly oversized.', 'warning')
|
||||||
|
else:
|
||||||
|
os.remove(outputPath)
|
||||||
|
if os.path.exists(outputPath.replace('.epub', '.mobi')):
|
||||||
|
os.remove(outputPath.replace('.epub', '.mobi'))
|
||||||
|
self.emit(QtCore.SIGNAL("addMessage"), 'KindleGen failed to create MOBI!', 'error')
|
||||||
|
self.emit(QtCore.SIGNAL("addMessage"), 'Try converting a smaller batch.', 'error')
|
||||||
|
else:
|
||||||
|
excess = (os.path.getsize(outputPath) - 314572800)/1024/1024
|
||||||
|
os.remove(outputPath)
|
||||||
|
self.emit(QtCore.SIGNAL("addMessage"), 'Created EPUB file is too big for KindleGen!', 'error')
|
||||||
|
self.emit(QtCore.SIGNAL("addMessage"), 'Limit exceeded by ' + str(excess) +
|
||||||
|
' MB. Try converting a smaller batch.', 'error')
|
||||||
|
self.emit(QtCore.SIGNAL("hideProgressBar"))
|
||||||
|
self.parent.needClean = True
|
||||||
|
self.emit(QtCore.SIGNAL("addMessage"), 'All jobs completed.', 'info')
|
||||||
|
self.emit(QtCore.SIGNAL("modeConvert"), True)
|
||||||
|
|
||||||
|
|
||||||
|
# noinspection PyBroadException
|
||||||
|
class Ui_KCC(object):
|
||||||
|
def selectDir(self):
|
||||||
|
# Dialog allow to select multiple directories but we can't parse that. QT Bug.
|
||||||
|
if self.needClean:
|
||||||
|
self.needClean = False
|
||||||
|
GUI.JobList.clear()
|
||||||
|
dname = QtGui.QFileDialog.getExistingDirectory(MainWindow, 'Select directory', self.lastPath)
|
||||||
|
# Lame UTF-8 security measure
|
||||||
|
try:
|
||||||
|
str(dname)
|
||||||
|
except Exception:
|
||||||
|
QtGui.QMessageBox.critical(MainWindow, 'KCC Error', "Path cannot contain non-ASCII characters.",
|
||||||
|
QtGui.QMessageBox.Ok)
|
||||||
|
return
|
||||||
|
if str(dname) != "":
|
||||||
|
self.lastPath = os.path.abspath(os.path.join(str(dname), os.pardir))
|
||||||
|
GUI.JobList.addItem(dname)
|
||||||
|
|
||||||
|
def selectFile(self):
|
||||||
|
if self.needClean:
|
||||||
|
self.needClean = False
|
||||||
|
GUI.JobList.clear()
|
||||||
|
if self.UnRAR:
|
||||||
|
fname = QtGui.QFileDialog.getOpenFileName(MainWindow, 'Select file', self.lastPath,
|
||||||
|
'*.cbz *.cbr *.zip *.rar *.pdf')
|
||||||
|
else:
|
||||||
|
fname = QtGui.QFileDialog.getOpenFileName(MainWindow, 'Select file', self.lastPath,
|
||||||
|
'*.cbz *.zip *.pdf')
|
||||||
|
# Lame UTF-8 security measure
|
||||||
|
try:
|
||||||
|
str(fname)
|
||||||
|
except Exception:
|
||||||
|
QtGui.QMessageBox.critical(MainWindow, 'KCC Error', "Path cannot contain non-ASCII characters.",
|
||||||
|
QtGui.QMessageBox.Ok)
|
||||||
|
return
|
||||||
|
if str(fname) != "":
|
||||||
|
self.lastPath = os.path.abspath(os.path.join(str(fname), os.pardir))
|
||||||
|
GUI.JobList.addItem(fname)
|
||||||
|
|
||||||
|
def clearJobs(self):
|
||||||
|
GUI.JobList.clear()
|
||||||
|
|
||||||
|
def modeBasic(self):
|
||||||
|
self.currentMode = 1
|
||||||
|
MainWindow.setMinimumSize(QtCore.QSize(420, 270))
|
||||||
|
MainWindow.setMaximumSize(QtCore.QSize(420, 270))
|
||||||
|
MainWindow.resize(420, 270)
|
||||||
|
GUI.BasicModeButton.setStyleSheet('font-weight:Bold;')
|
||||||
|
GUI.AdvModeButton.setStyleSheet('font-weight:Normal;')
|
||||||
|
GUI.FormatBox.setCurrentIndex(0)
|
||||||
|
GUI.FormatBox.setEnabled(False)
|
||||||
|
GUI.OptionsAdvanced.setEnabled(False)
|
||||||
|
GUI.OptionsAdvancedGamma.setEnabled(False)
|
||||||
|
GUI.OptionsExpert.setEnabled(False)
|
||||||
|
GUI.ProcessingBox.hide()
|
||||||
|
GUI.UpscaleBox.hide()
|
||||||
|
GUI.NoRotateBox.hide()
|
||||||
|
GUI.MangaBox.setEnabled(True)
|
||||||
|
|
||||||
|
def modeAdvanced(self):
|
||||||
|
self.currentMode = 2
|
||||||
|
MainWindow.setMinimumSize(QtCore.QSize(420, 345))
|
||||||
|
MainWindow.setMaximumSize(QtCore.QSize(420, 345))
|
||||||
|
MainWindow.resize(420, 345)
|
||||||
|
GUI.BasicModeButton.setStyleSheet('font-weight:Normal;')
|
||||||
|
GUI.AdvModeButton.setStyleSheet('font-weight:Bold;')
|
||||||
|
GUI.FormatBox.setEnabled(True)
|
||||||
|
GUI.ProcessingBox.show()
|
||||||
|
GUI.UpscaleBox.show()
|
||||||
|
GUI.NoRotateBox.show()
|
||||||
|
GUI.OptionsAdvancedGamma.setEnabled(True)
|
||||||
|
GUI.OptionsAdvanced.setEnabled(True)
|
||||||
|
GUI.OptionsExpert.setEnabled(False)
|
||||||
|
GUI.MangaBox.setEnabled(True)
|
||||||
|
|
||||||
|
def modeExpert(self):
|
||||||
|
self.modeAdvanced()
|
||||||
|
self.currentMode = 3
|
||||||
|
MainWindow.setMinimumSize(QtCore.QSize(420, 380))
|
||||||
|
MainWindow.setMaximumSize(QtCore.QSize(420, 380))
|
||||||
|
MainWindow.resize(420, 380)
|
||||||
|
GUI.OptionsExpert.setEnabled(True)
|
||||||
|
GUI.MangaBox.setCheckState(0)
|
||||||
|
GUI.MangaBox.setEnabled(False)
|
||||||
|
|
||||||
|
def modeConvert(self, enable):
|
||||||
|
if self.currentMode != 3:
|
||||||
|
GUI.BasicModeButton.setEnabled(enable)
|
||||||
|
GUI.AdvModeButton.setEnabled(enable)
|
||||||
|
GUI.DirectoryButton.setEnabled(enable)
|
||||||
|
GUI.ClearButton.setEnabled(enable)
|
||||||
|
GUI.FileButton.setEnabled(enable)
|
||||||
|
GUI.DeviceBox.setEnabled(enable)
|
||||||
|
GUI.ConvertButton.setEnabled(enable)
|
||||||
|
GUI.FormatBox.setEnabled(enable)
|
||||||
|
GUI.OptionsBasic.setEnabled(enable)
|
||||||
|
GUI.OptionsAdvanced.setEnabled(enable)
|
||||||
|
GUI.OptionsAdvancedGamma.setEnabled(enable)
|
||||||
|
GUI.OptionsExpert.setEnabled(enable)
|
||||||
|
if enable:
|
||||||
|
if self.currentMode == 1:
|
||||||
|
self.modeBasic()
|
||||||
|
elif self.currentMode == 2:
|
||||||
|
self.modeAdvanced()
|
||||||
|
elif self.currentMode == 3:
|
||||||
|
self.modeExpert()
|
||||||
|
|
||||||
|
def changeGamma(self, value):
|
||||||
|
value = float(value)
|
||||||
|
value = '%.2f' % (value/100)
|
||||||
|
if float(value) <= 0.09:
|
||||||
|
GUI.GammaLabel.setText('Gamma: Auto')
|
||||||
|
else:
|
||||||
|
GUI.GammaLabel.setText('Gamma: ' + str(value))
|
||||||
|
self.GammaValue = value
|
||||||
|
|
||||||
|
def changeDevice(self, value, start=False):
|
||||||
|
if value == 11 and (start or self.currentMode != 3):
|
||||||
|
GUI.BasicModeButton.setEnabled(False)
|
||||||
|
GUI.AdvModeButton.setEnabled(False)
|
||||||
|
self.modeExpert()
|
||||||
|
elif self.currentMode == 3:
|
||||||
|
GUI.BasicModeButton.setEnabled(True)
|
||||||
|
GUI.AdvModeButton.setEnabled(True)
|
||||||
|
self.modeBasic()
|
||||||
|
if value in [0, 1, 5, 6, 7, 8, 9, 11]:
|
||||||
|
GUI.QualityBox.setCheckState(0)
|
||||||
|
GUI.QualityBox.setEnabled(False)
|
||||||
|
else:
|
||||||
|
GUI.QualityBox.setEnabled(True)
|
||||||
|
|
||||||
|
def addMessage(self, message, icon=None, replace=False):
|
||||||
|
if icon:
|
||||||
|
icon = eval('self.icons.' + icon)
|
||||||
|
item = QtGui.QListWidgetItem(icon, message)
|
||||||
|
else:
|
||||||
|
item = QtGui.QListWidgetItem(message)
|
||||||
|
if replace:
|
||||||
|
GUI.JobList.takeItem(GUI.JobList.count()-1)
|
||||||
|
GUI.JobList.addItem(item)
|
||||||
|
GUI.JobList.scrollToBottom()
|
||||||
|
|
||||||
|
def showDialog(self, message):
|
||||||
|
QtGui.QMessageBox.critical(MainWindow, 'KCC Error', message, QtGui.QMessageBox.Ok)
|
||||||
|
|
||||||
|
def updateProgressbar(self, new=False, status=False):
|
||||||
|
if new == "status":
|
||||||
|
pass
|
||||||
|
GUI.ProgressBar.setFormat(status)
|
||||||
|
elif new:
|
||||||
|
GUI.ProgressBar.setMaximum(new - 1)
|
||||||
|
GUI.ProgressBar.reset()
|
||||||
|
GUI.ProgressBar.show()
|
||||||
|
else:
|
||||||
|
GUI.ProgressBar.setValue(GUI.ProgressBar.value() + 1)
|
||||||
|
|
||||||
|
def convertStart(self):
|
||||||
|
if self.needClean:
|
||||||
|
self.needClean = False
|
||||||
|
GUI.JobList.clear()
|
||||||
|
if GUI.JobList.count() == 0:
|
||||||
|
self.addMessage('No files selected! Please choose files to convert.', 'error')
|
||||||
|
self.needClean = True
|
||||||
|
return
|
||||||
|
if self.currentMode > 2 and (str(GUI.customWidth.text()) == '' or str(GUI.customHeight.text()) == ''):
|
||||||
|
GUI.JobList.clear()
|
||||||
|
self.addMessage('Target resolution is not set!', 'error')
|
||||||
|
self.needClean = True
|
||||||
|
return
|
||||||
|
self.worker.start()
|
||||||
|
|
||||||
|
def hideProgressBar(self):
|
||||||
|
GUI.ProgressBar.hide()
|
||||||
|
|
||||||
|
# noinspection PyUnusedLocal
|
||||||
|
def saveSettings(self, event):
|
||||||
|
self.settings.setValue('lastPath', self.lastPath)
|
||||||
|
self.settings.setValue('lastDevice', GUI.DeviceBox.currentIndex())
|
||||||
|
self.settings.setValue('currentFormat', GUI.FormatBox.currentIndex())
|
||||||
|
self.settings.setValue('currentMode', self.currentMode)
|
||||||
|
self.settings.setValue('options', QtCore.QVariant({'MangaBox': GUI.MangaBox.checkState(),
|
||||||
|
'RotateBox': GUI.RotateBox.checkState(),
|
||||||
|
'QualityBox': GUI.QualityBox.checkState(),
|
||||||
|
'ProcessingBox': GUI.ProcessingBox.checkState(),
|
||||||
|
'UpscaleBox': GUI.UpscaleBox.checkState(),
|
||||||
|
'NoRotateBox': GUI.NoRotateBox.checkState(),
|
||||||
|
'BorderBox': GUI.BorderBox.checkState(),
|
||||||
|
'StretchBox': GUI.StretchBox.checkState(),
|
||||||
|
'NoDitheringBox': GUI.NoDitheringBox.checkState(),
|
||||||
|
'ColorBox': GUI.ColorBox.checkState(),
|
||||||
|
'customWidth': GUI.customWidth.text(),
|
||||||
|
'customHeight': GUI.customHeight.text(),
|
||||||
|
'GammaSlider': float(self.GammaValue)*100}))
|
||||||
|
self.settings.sync()
|
||||||
|
|
||||||
|
def __init__(self, UI, KCC):
|
||||||
|
global GUI, MainWindow
|
||||||
|
GUI = UI
|
||||||
|
MainWindow = KCC
|
||||||
|
profiles = sorted(ProfileData.ProfileLabels.iterkeys())
|
||||||
|
self.icons = Icons()
|
||||||
|
self.settings = QtCore.QSettings('KindleComicConverter', 'KindleComicConverter')
|
||||||
|
self.lastPath = self.settings.value('lastPath', '', type=str)
|
||||||
|
self.lastDevice = self.settings.value('lastDevice', 10, type=int)
|
||||||
|
self.currentMode = self.settings.value('currentMode', 1, type=int)
|
||||||
|
self.currentFormat = self.settings.value('currentFormat', 0, type=int)
|
||||||
|
self.options = self.settings.value('options', QtCore.QVariant({'GammaSlider': 0}))
|
||||||
|
self.options = self.options.toPyObject()
|
||||||
|
self.worker = WorkerThread(self)
|
||||||
|
self.versionCheck = VersionThread(self)
|
||||||
|
self.needClean = True
|
||||||
|
|
||||||
|
self.addMessage('Welcome!', 'info')
|
||||||
|
self.addMessage('Remember: all options have additional informations in tooltips.', 'info')
|
||||||
|
if call('kindlegen', stdout=PIPE, stderr=STDOUT, shell=True) == 0:
|
||||||
|
self.KindleGen = True
|
||||||
|
formats = ['MOBI', 'EPUB', 'CBZ']
|
||||||
|
versionCheck = Popen('kindlegen', stdout=PIPE, stderr=STDOUT, shell=True)
|
||||||
|
for line in versionCheck.stdout:
|
||||||
|
if "Amazon kindlegen" in line:
|
||||||
|
versionCheck = line.split('V')[1].split(' ')[0]
|
||||||
|
if tuple(map(int, (versionCheck.split(".")))) < tuple(map(int, ('2.9'.split(".")))):
|
||||||
|
self.addMessage('Your kindlegen is outdated! Creating MOBI might fail.'
|
||||||
|
' Please update kindlegen from Amazon\'s website.', 'warning')
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
self.KindleGen = False
|
||||||
|
formats = ['EPUB', 'CBZ']
|
||||||
|
self.addMessage('Cannot find kindlegen in PATH! MOBI creation will be disabled.', 'warning')
|
||||||
|
if call('unrar', stdout=PIPE, stderr=STDOUT, shell=True) == 0:
|
||||||
|
self.UnRAR = True
|
||||||
|
else:
|
||||||
|
self.UnRAR = False
|
||||||
|
self.addMessage('Cannot find UnRAR! Processing of CBR/RAR files will be disabled.', 'warning')
|
||||||
|
|
||||||
|
GUI.BasicModeButton.clicked.connect(self.modeBasic)
|
||||||
|
GUI.AdvModeButton.clicked.connect(self.modeAdvanced)
|
||||||
|
GUI.DirectoryButton.clicked.connect(self.selectDir)
|
||||||
|
GUI.ClearButton.clicked.connect(self.clearJobs)
|
||||||
|
GUI.FileButton.clicked.connect(self.selectFile)
|
||||||
|
GUI.ConvertButton.clicked.connect(self.convertStart)
|
||||||
|
GUI.GammaSlider.valueChanged.connect(self.changeGamma)
|
||||||
|
GUI.DeviceBox.activated.connect(self.changeDevice)
|
||||||
|
KCC.connect(self.worker, QtCore.SIGNAL("progressBarTick"), self.updateProgressbar)
|
||||||
|
KCC.connect(self.worker, QtCore.SIGNAL("modeConvert"), self.modeConvert)
|
||||||
|
KCC.connect(self.worker, QtCore.SIGNAL("addMessage"), self.addMessage)
|
||||||
|
KCC.connect(self.worker, QtCore.SIGNAL("showDialog"), self.showDialog)
|
||||||
|
KCC.connect(self.worker, QtCore.SIGNAL("hideProgressBar"), self.hideProgressBar)
|
||||||
|
KCC.connect(self.versionCheck, QtCore.SIGNAL("addMessage"), self.addMessage)
|
||||||
|
KCC.closeEvent = self.saveSettings
|
||||||
|
|
||||||
|
for profile in profiles:
|
||||||
|
if profile != "Other":
|
||||||
|
GUI.DeviceBox.addItem(self.icons.deviceKindle, profile)
|
||||||
|
else:
|
||||||
|
GUI.DeviceBox.addItem(self.icons.deviceOther, profile)
|
||||||
|
GUI.DeviceBox.setCurrentIndex(self.lastDevice)
|
||||||
|
|
||||||
|
for f in formats:
|
||||||
|
GUI.FormatBox.addItem(eval('self.icons.' + f + 'Format'), f)
|
||||||
|
if self.currentFormat > GUI.FormatBox.count():
|
||||||
|
GUI.FormatBox.setCurrentIndex(0)
|
||||||
|
self.currentFormat = 0
|
||||||
|
else:
|
||||||
|
GUI.FormatBox.setCurrentIndex(self.currentFormat)
|
||||||
|
|
||||||
|
for option in self.options:
|
||||||
|
if str(option) == "customWidth":
|
||||||
|
GUI.customWidth.setText(str(self.options[option]))
|
||||||
|
elif str(option) == "customHeight":
|
||||||
|
GUI.customHeight.setText(str(self.options[option]))
|
||||||
|
elif str(option) == "GammaSlider":
|
||||||
|
GUI.GammaSlider.setValue(int(self.options[option]))
|
||||||
|
self.changeGamma(int(self.options[option]))
|
||||||
|
else:
|
||||||
|
eval('GUI.' + str(option)).setCheckState(self.options[option])
|
||||||
|
if self.currentMode == 1:
|
||||||
|
self.modeBasic()
|
||||||
|
elif self.currentMode == 2:
|
||||||
|
self.modeAdvanced()
|
||||||
|
elif self.currentMode == 3:
|
||||||
|
self.modeExpert()
|
||||||
|
self.versionCheck.start()
|
||||||
|
self.hideProgressBar()
|
||||||
|
self.changeDevice(self.lastDevice, True)
|
||||||
7893
kcc/KCC_rc.py
Normal file
311
kcc/KCC_ui.py
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Form implementation generated from reading ui file 'KCC.ui'
|
||||||
|
#
|
||||||
|
# Created: Fri Jun 21 18:23:19 2013
|
||||||
|
# by: PyQt4 UI code generator 4.10.1
|
||||||
|
#
|
||||||
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
|
||||||
|
from PyQt4 import QtCore, QtGui
|
||||||
|
|
||||||
|
try:
|
||||||
|
_fromUtf8 = QtCore.QString.fromUtf8
|
||||||
|
except AttributeError:
|
||||||
|
def _fromUtf8(s):
|
||||||
|
return s
|
||||||
|
|
||||||
|
try:
|
||||||
|
_encoding = QtGui.QApplication.UnicodeUTF8
|
||||||
|
def _translate(context, text, disambig):
|
||||||
|
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
||||||
|
except AttributeError:
|
||||||
|
def _translate(context, text, disambig):
|
||||||
|
return QtGui.QApplication.translate(context, text, disambig)
|
||||||
|
|
||||||
|
class Ui_KCC(object):
|
||||||
|
def setupUi(self, KCC):
|
||||||
|
KCC.setObjectName(_fromUtf8("KCC"))
|
||||||
|
KCC.resize(420, 380)
|
||||||
|
KCC.setMinimumSize(QtCore.QSize(420, 380))
|
||||||
|
KCC.setMaximumSize(QtCore.QSize(420, 380))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(9)
|
||||||
|
KCC.setFont(font)
|
||||||
|
KCC.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
icon = QtGui.QIcon()
|
||||||
|
icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/Icon/icons/comic2ebook.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
KCC.setWindowIcon(icon)
|
||||||
|
KCC.setLocale(QtCore.QLocale(QtCore.QLocale.C, QtCore.QLocale.AnyCountry))
|
||||||
|
self.Form = QtGui.QWidget(KCC)
|
||||||
|
self.Form.setObjectName(_fromUtf8("Form"))
|
||||||
|
self.OptionsAdvanced = QtGui.QFrame(self.Form)
|
||||||
|
self.OptionsAdvanced.setEnabled(True)
|
||||||
|
self.OptionsAdvanced.setGeometry(QtCore.QRect(10, 254, 421, 61))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(9)
|
||||||
|
self.OptionsAdvanced.setFont(font)
|
||||||
|
self.OptionsAdvanced.setObjectName(_fromUtf8("OptionsAdvanced"))
|
||||||
|
self.gridLayout = QtGui.QGridLayout(self.OptionsAdvanced)
|
||||||
|
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
|
||||||
|
self.ProcessingBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||||
|
self.ProcessingBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.ProcessingBox.setObjectName(_fromUtf8("ProcessingBox"))
|
||||||
|
self.gridLayout.addWidget(self.ProcessingBox, 1, 0, 1, 1)
|
||||||
|
self.UpscaleBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||||
|
self.UpscaleBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.UpscaleBox.setObjectName(_fromUtf8("UpscaleBox"))
|
||||||
|
self.gridLayout.addWidget(self.UpscaleBox, 1, 1, 1, 1)
|
||||||
|
self.StretchBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||||
|
self.StretchBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.StretchBox.setObjectName(_fromUtf8("StretchBox"))
|
||||||
|
self.gridLayout.addWidget(self.StretchBox, 3, 1, 1, 1)
|
||||||
|
self.NoDitheringBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||||
|
self.NoDitheringBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.NoDitheringBox.setObjectName(_fromUtf8("NoDitheringBox"))
|
||||||
|
self.gridLayout.addWidget(self.NoDitheringBox, 3, 2, 1, 1)
|
||||||
|
self.BorderBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||||
|
self.BorderBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.BorderBox.setObjectName(_fromUtf8("BorderBox"))
|
||||||
|
self.gridLayout.addWidget(self.BorderBox, 3, 0, 1, 1)
|
||||||
|
self.NoRotateBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||||
|
self.NoRotateBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.NoRotateBox.setObjectName(_fromUtf8("NoRotateBox"))
|
||||||
|
self.gridLayout.addWidget(self.NoRotateBox, 1, 2, 1, 1)
|
||||||
|
self.DeviceBox = QtGui.QComboBox(self.Form)
|
||||||
|
self.DeviceBox.setGeometry(QtCore.QRect(10, 200, 141, 31))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(8)
|
||||||
|
self.DeviceBox.setFont(font)
|
||||||
|
self.DeviceBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.DeviceBox.setObjectName(_fromUtf8("DeviceBox"))
|
||||||
|
self.FormatBox = QtGui.QComboBox(self.Form)
|
||||||
|
self.FormatBox.setGeometry(QtCore.QRect(260, 200, 151, 31))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(8)
|
||||||
|
self.FormatBox.setFont(font)
|
||||||
|
self.FormatBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.FormatBox.setObjectName(_fromUtf8("FormatBox"))
|
||||||
|
self.ConvertButton = QtGui.QPushButton(self.Form)
|
||||||
|
self.ConvertButton.setGeometry(QtCore.QRect(160, 200, 91, 32))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(9)
|
||||||
|
font.setBold(True)
|
||||||
|
font.setWeight(75)
|
||||||
|
self.ConvertButton.setFont(font)
|
||||||
|
self.ConvertButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
icon1 = QtGui.QIcon()
|
||||||
|
icon1.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/convert.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
self.ConvertButton.setIcon(icon1)
|
||||||
|
self.ConvertButton.setObjectName(_fromUtf8("ConvertButton"))
|
||||||
|
self.DirectoryButton = QtGui.QPushButton(self.Form)
|
||||||
|
self.DirectoryButton.setGeometry(QtCore.QRect(10, 160, 141, 32))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(8)
|
||||||
|
self.DirectoryButton.setFont(font)
|
||||||
|
self.DirectoryButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
icon2 = QtGui.QIcon()
|
||||||
|
icon2.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/folder_new.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
self.DirectoryButton.setIcon(icon2)
|
||||||
|
self.DirectoryButton.setObjectName(_fromUtf8("DirectoryButton"))
|
||||||
|
self.FileButton = QtGui.QPushButton(self.Form)
|
||||||
|
self.FileButton.setGeometry(QtCore.QRect(260, 160, 151, 32))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(8)
|
||||||
|
self.FileButton.setFont(font)
|
||||||
|
self.FileButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
icon3 = QtGui.QIcon()
|
||||||
|
icon3.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/document_new.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
self.FileButton.setIcon(icon3)
|
||||||
|
self.FileButton.setObjectName(_fromUtf8("FileButton"))
|
||||||
|
self.ClearButton = QtGui.QPushButton(self.Form)
|
||||||
|
self.ClearButton.setGeometry(QtCore.QRect(160, 160, 91, 32))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(8)
|
||||||
|
self.ClearButton.setFont(font)
|
||||||
|
self.ClearButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
icon4 = QtGui.QIcon()
|
||||||
|
icon4.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/clear.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
self.ClearButton.setIcon(icon4)
|
||||||
|
self.ClearButton.setObjectName(_fromUtf8("ClearButton"))
|
||||||
|
self.OptionsBasic = QtGui.QFrame(self.Form)
|
||||||
|
self.OptionsBasic.setGeometry(QtCore.QRect(10, 230, 421, 41))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(9)
|
||||||
|
self.OptionsBasic.setFont(font)
|
||||||
|
self.OptionsBasic.setObjectName(_fromUtf8("OptionsBasic"))
|
||||||
|
self.MangaBox = QtGui.QCheckBox(self.OptionsBasic)
|
||||||
|
self.MangaBox.setGeometry(QtCore.QRect(9, 10, 130, 18))
|
||||||
|
self.MangaBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.MangaBox.setObjectName(_fromUtf8("MangaBox"))
|
||||||
|
self.QualityBox = QtGui.QCheckBox(self.OptionsBasic)
|
||||||
|
self.QualityBox.setGeometry(QtCore.QRect(282, 10, 130, 18))
|
||||||
|
self.QualityBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.QualityBox.setTristate(True)
|
||||||
|
self.QualityBox.setObjectName(_fromUtf8("QualityBox"))
|
||||||
|
self.RotateBox = QtGui.QCheckBox(self.OptionsBasic)
|
||||||
|
self.RotateBox.setGeometry(QtCore.QRect(145, 10, 130, 18))
|
||||||
|
self.RotateBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.RotateBox.setObjectName(_fromUtf8("RotateBox"))
|
||||||
|
self.JobList = QtGui.QListWidget(self.Form)
|
||||||
|
self.JobList.setGeometry(QtCore.QRect(10, 50, 401, 101))
|
||||||
|
self.JobList.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.JobList.setProperty("showDropIndicator", False)
|
||||||
|
self.JobList.setSelectionMode(QtGui.QAbstractItemView.NoSelection)
|
||||||
|
self.JobList.setObjectName(_fromUtf8("JobList"))
|
||||||
|
self.BasicModeButton = QtGui.QPushButton(self.Form)
|
||||||
|
self.BasicModeButton.setGeometry(QtCore.QRect(10, 10, 195, 32))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(9)
|
||||||
|
self.BasicModeButton.setFont(font)
|
||||||
|
self.BasicModeButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.BasicModeButton.setObjectName(_fromUtf8("BasicModeButton"))
|
||||||
|
self.AdvModeButton = QtGui.QPushButton(self.Form)
|
||||||
|
self.AdvModeButton.setGeometry(QtCore.QRect(217, 10, 195, 32))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(9)
|
||||||
|
self.AdvModeButton.setFont(font)
|
||||||
|
self.AdvModeButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.AdvModeButton.setObjectName(_fromUtf8("AdvModeButton"))
|
||||||
|
self.OptionsAdvancedGamma = QtGui.QFrame(self.Form)
|
||||||
|
self.OptionsAdvancedGamma.setEnabled(True)
|
||||||
|
self.OptionsAdvancedGamma.setGeometry(QtCore.QRect(10, 305, 401, 41))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(9)
|
||||||
|
self.OptionsAdvancedGamma.setFont(font)
|
||||||
|
self.OptionsAdvancedGamma.setObjectName(_fromUtf8("OptionsAdvancedGamma"))
|
||||||
|
self.GammaLabel = QtGui.QLabel(self.OptionsAdvancedGamma)
|
||||||
|
self.GammaLabel.setGeometry(QtCore.QRect(15, 0, 100, 40))
|
||||||
|
self.GammaLabel.setObjectName(_fromUtf8("GammaLabel"))
|
||||||
|
self.GammaSlider = QtGui.QSlider(self.OptionsAdvancedGamma)
|
||||||
|
self.GammaSlider.setGeometry(QtCore.QRect(110, 10, 270, 22))
|
||||||
|
self.GammaSlider.setFocusPolicy(QtCore.Qt.ClickFocus)
|
||||||
|
self.GammaSlider.setMaximum(500)
|
||||||
|
self.GammaSlider.setSingleStep(5)
|
||||||
|
self.GammaSlider.setOrientation(QtCore.Qt.Horizontal)
|
||||||
|
self.GammaSlider.setObjectName(_fromUtf8("GammaSlider"))
|
||||||
|
self.ProgressBar = QtGui.QProgressBar(self.Form)
|
||||||
|
self.ProgressBar.setGeometry(QtCore.QRect(10, 10, 401, 31))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(10)
|
||||||
|
font.setBold(True)
|
||||||
|
font.setWeight(75)
|
||||||
|
self.ProgressBar.setFont(font)
|
||||||
|
self.ProgressBar.setProperty("value", 0)
|
||||||
|
self.ProgressBar.setAlignment(QtCore.Qt.AlignJustify|QtCore.Qt.AlignVCenter)
|
||||||
|
self.ProgressBar.setFormat(_fromUtf8(""))
|
||||||
|
self.ProgressBar.setObjectName(_fromUtf8("ProgressBar"))
|
||||||
|
self.OptionsExpert = QtGui.QFrame(self.Form)
|
||||||
|
self.OptionsExpert.setGeometry(QtCore.QRect(10, 337, 421, 41))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(9)
|
||||||
|
self.OptionsExpert.setFont(font)
|
||||||
|
self.OptionsExpert.setObjectName(_fromUtf8("OptionsExpert"))
|
||||||
|
self.ColorBox = QtGui.QCheckBox(self.OptionsExpert)
|
||||||
|
self.ColorBox.setGeometry(QtCore.QRect(9, 11, 130, 18))
|
||||||
|
self.ColorBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.ColorBox.setObjectName(_fromUtf8("ColorBox"))
|
||||||
|
self.OptionsExpertInternal = QtGui.QFrame(self.OptionsExpert)
|
||||||
|
self.OptionsExpertInternal.setGeometry(QtCore.QRect(100, 0, 295, 40))
|
||||||
|
self.OptionsExpertInternal.setObjectName(_fromUtf8("OptionsExpertInternal"))
|
||||||
|
self.gridLayout_2 = QtGui.QGridLayout(self.OptionsExpertInternal)
|
||||||
|
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
|
||||||
|
self.wLabel = QtGui.QLabel(self.OptionsExpertInternal)
|
||||||
|
self.wLabel.setObjectName(_fromUtf8("wLabel"))
|
||||||
|
self.gridLayout_2.addWidget(self.wLabel, 0, 0, 1, 1)
|
||||||
|
self.customWidth = QtGui.QLineEdit(self.OptionsExpertInternal)
|
||||||
|
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.customWidth.sizePolicy().hasHeightForWidth())
|
||||||
|
self.customWidth.setSizePolicy(sizePolicy)
|
||||||
|
self.customWidth.setMaximumSize(QtCore.QSize(40, 16777215))
|
||||||
|
self.customWidth.setFocusPolicy(QtCore.Qt.ClickFocus)
|
||||||
|
self.customWidth.setAcceptDrops(False)
|
||||||
|
self.customWidth.setMaxLength(4)
|
||||||
|
self.customWidth.setObjectName(_fromUtf8("customWidth"))
|
||||||
|
self.gridLayout_2.addWidget(self.customWidth, 0, 1, 1, 1)
|
||||||
|
self.hLabel = QtGui.QLabel(self.OptionsExpertInternal)
|
||||||
|
self.hLabel.setObjectName(_fromUtf8("hLabel"))
|
||||||
|
self.gridLayout_2.addWidget(self.hLabel, 0, 2, 1, 1)
|
||||||
|
self.customHeight = QtGui.QLineEdit(self.OptionsExpertInternal)
|
||||||
|
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.customHeight.sizePolicy().hasHeightForWidth())
|
||||||
|
self.customHeight.setSizePolicy(sizePolicy)
|
||||||
|
self.customHeight.setMaximumSize(QtCore.QSize(40, 16777215))
|
||||||
|
self.customHeight.setFocusPolicy(QtCore.Qt.ClickFocus)
|
||||||
|
self.customHeight.setAcceptDrops(False)
|
||||||
|
self.customHeight.setMaxLength(4)
|
||||||
|
self.customHeight.setObjectName(_fromUtf8("customHeight"))
|
||||||
|
self.gridLayout_2.addWidget(self.customHeight, 0, 3, 1, 1)
|
||||||
|
KCC.setCentralWidget(self.Form)
|
||||||
|
self.ActionBasic = QtGui.QAction(KCC)
|
||||||
|
self.ActionBasic.setCheckable(True)
|
||||||
|
self.ActionBasic.setChecked(False)
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(9)
|
||||||
|
self.ActionBasic.setFont(font)
|
||||||
|
self.ActionBasic.setObjectName(_fromUtf8("ActionBasic"))
|
||||||
|
self.ActionAdvanced = QtGui.QAction(KCC)
|
||||||
|
self.ActionAdvanced.setCheckable(True)
|
||||||
|
self.ActionAdvanced.setObjectName(_fromUtf8("ActionAdvanced"))
|
||||||
|
|
||||||
|
self.retranslateUi(KCC)
|
||||||
|
QtCore.QMetaObject.connectSlotsByName(KCC)
|
||||||
|
KCC.setTabOrder(self.DirectoryButton, self.FileButton)
|
||||||
|
KCC.setTabOrder(self.FileButton, self.ConvertButton)
|
||||||
|
KCC.setTabOrder(self.ConvertButton, self.ClearButton)
|
||||||
|
|
||||||
|
def retranslateUi(self, KCC):
|
||||||
|
KCC.setWindowTitle(_translate("KCC", "Kindle Comic Converter", None))
|
||||||
|
self.ProcessingBox.setToolTip(_translate("KCC", "Disable image optimizations.", None))
|
||||||
|
self.ProcessingBox.setText(_translate("KCC", "No optimisation", None))
|
||||||
|
self.UpscaleBox.setToolTip(_translate("KCC", "<html><head/><body><p>Enable image upscaling.<br/>Aspect ratio will be preserved.</p></body></html>", None))
|
||||||
|
self.UpscaleBox.setText(_translate("KCC", "Upscale images", None))
|
||||||
|
self.StretchBox.setToolTip(_translate("KCC", "<html><head/><body><p>Enable image stretching.<br/>Aspect ratio will be not preserved.</p></body></html>", None))
|
||||||
|
self.StretchBox.setText(_translate("KCC", "Stretch images", None))
|
||||||
|
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.NoDitheringBox.setText(_translate("KCC", "PNG output", None))
|
||||||
|
self.BorderBox.setToolTip(_translate("KCC", "Fill space around images with black color.", None))
|
||||||
|
self.BorderBox.setText(_translate("KCC", "Black borders", None))
|
||||||
|
self.NoRotateBox.setToolTip(_translate("KCC", "<html><head/><body><p>Disable splitting and rotation.</p></body></html>", None))
|
||||||
|
self.NoRotateBox.setText(_translate("KCC", "No split/rotate", None))
|
||||||
|
self.DeviceBox.setToolTip(_translate("KCC", "Target device.", None))
|
||||||
|
self.FormatBox.setToolTip(_translate("KCC", "Output format.", None))
|
||||||
|
self.ConvertButton.setText(_translate("KCC", "Convert", None))
|
||||||
|
self.DirectoryButton.setText(_translate("KCC", "Add directory", None))
|
||||||
|
self.FileButton.setText(_translate("KCC", "Add file", None))
|
||||||
|
self.ClearButton.setText(_translate("KCC", "Clear list", None))
|
||||||
|
self.MangaBox.setToolTip(_translate("KCC", "Enable right-to-left reading.", None))
|
||||||
|
self.MangaBox.setText(_translate("KCC", "Manga mode", None))
|
||||||
|
self.QualityBox.setToolTip(_translate("KCC", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
|
||||||
|
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
|
||||||
|
"p, li { white-space: pre-wrap; }\n"
|
||||||
|
"</style></head><body style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt; font-weight:400; font-style:normal;\">\n"
|
||||||
|
"<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Normal quality mode<br /></span><span style=\" font-style:italic;\">Use it when Panel View support is not needed.</span><span style=\" font-weight:600; text-decoration: underline;\"><br /></span>- Maximum quality when zoom is not enabled.<br />- Poor quality when zoom is enabled.<br />- Lowest file size.</p>\n"
|
||||||
|
"<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - High quality mode<br /></span><span style=\" font-style:italic;\">Not zoomed image </span><span style=\" font-weight:600; font-style:italic;\">might </span><span style=\" font-style:italic;\">be </span><span style=\" font-style:italic;\">a little blurry.</span><span style=\" font-weight:600; text-decoration: underline;\"><br /></span>- Medium/High quality when zoom is not enabled.<br />- Maximum quality when zoom is enabled.</p>\n"
|
||||||
|
"<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-weight:600; text-decoration: underline;\">Checked - Ultra quality mode<br /></span><span style=\" font-style:italic;\">Maximum possible quality.</span><span style=\" font-weight:600; text-decoration: underline;\"><br /></span>- Maximum quality when zoom is not enabled.<br />- Maximum quality when zoom is enabled.<br />- Very high file size.</p></body></html>", None))
|
||||||
|
self.QualityBox.setText(_translate("KCC", "High/Ultra quality", None))
|
||||||
|
self.RotateBox.setToolTip(_translate("KCC", "<html><head/><body><p>Disable page spliting.<br/>They will be rotated instead.</p></body></html>", None))
|
||||||
|
self.RotateBox.setText(_translate("KCC", "Horizontal mode", None))
|
||||||
|
self.BasicModeButton.setText(_translate("KCC", "Basic", None))
|
||||||
|
self.AdvModeButton.setText(_translate("KCC", "Advanced", None))
|
||||||
|
self.GammaLabel.setToolTip(_translate("KCC", "When converting color images setting this option to 1.0 MIGHT improve readability.", None))
|
||||||
|
self.GammaLabel.setText(_translate("KCC", "Gamma: Auto", None))
|
||||||
|
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.ColorBox.setToolTip(_translate("KCC", "Do not convert images to grayscale.", None))
|
||||||
|
self.ColorBox.setText(_translate("KCC", "Color mode", None))
|
||||||
|
self.wLabel.setToolTip(_translate("KCC", "Resolution of target device.", None))
|
||||||
|
self.wLabel.setText(_translate("KCC", "Custom width: ", None))
|
||||||
|
self.customWidth.setToolTip(_translate("KCC", "Resolution of target device.", None))
|
||||||
|
self.customWidth.setInputMask(_translate("KCC", "0000; ", None))
|
||||||
|
self.hLabel.setToolTip(_translate("KCC", "Resolution of target device.", None))
|
||||||
|
self.hLabel.setText(_translate("KCC", "Custom height: ", None))
|
||||||
|
self.customHeight.setToolTip(_translate("KCC", "Resolution of target device.", None))
|
||||||
|
self.customHeight.setInputMask(_translate("KCC", "0000; ", None))
|
||||||
|
self.ActionBasic.setText(_translate("KCC", "Basic", None))
|
||||||
|
self.ActionAdvanced.setText(_translate("KCC", "Advanced", None))
|
||||||
|
|
||||||
|
import KCC_rc
|
||||||
364
kcc/KCC_ui_osx.py
Normal file
@@ -0,0 +1,364 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Form implementation generated from reading ui file 'KCC-OSX.ui'
|
||||||
|
#
|
||||||
|
# Created: Fri Jun 21 18:23:35 2013
|
||||||
|
# by: PyQt4 UI code generator 4.10.1
|
||||||
|
#
|
||||||
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
|
||||||
|
from PyQt4 import QtCore, QtGui
|
||||||
|
|
||||||
|
try:
|
||||||
|
_fromUtf8 = QtCore.QString.fromUtf8
|
||||||
|
except AttributeError:
|
||||||
|
def _fromUtf8(s):
|
||||||
|
return s
|
||||||
|
|
||||||
|
try:
|
||||||
|
_encoding = QtGui.QApplication.UnicodeUTF8
|
||||||
|
def _translate(context, text, disambig):
|
||||||
|
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
||||||
|
except AttributeError:
|
||||||
|
def _translate(context, text, disambig):
|
||||||
|
return QtGui.QApplication.translate(context, text, disambig)
|
||||||
|
|
||||||
|
class Ui_KCC(object):
|
||||||
|
def setupUi(self, KCC):
|
||||||
|
KCC.setObjectName(_fromUtf8("KCC"))
|
||||||
|
KCC.resize(420, 380)
|
||||||
|
KCC.setMinimumSize(QtCore.QSize(420, 380))
|
||||||
|
KCC.setMaximumSize(QtCore.QSize(420, 380))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(9)
|
||||||
|
KCC.setFont(font)
|
||||||
|
KCC.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
icon = QtGui.QIcon()
|
||||||
|
icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/Icon/icons/comic2ebook.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
KCC.setWindowIcon(icon)
|
||||||
|
KCC.setLocale(QtCore.QLocale(QtCore.QLocale.C, QtCore.QLocale.AnyCountry))
|
||||||
|
self.Form = QtGui.QWidget(KCC)
|
||||||
|
self.Form.setObjectName(_fromUtf8("Form"))
|
||||||
|
self.OptionsAdvanced = QtGui.QFrame(self.Form)
|
||||||
|
self.OptionsAdvanced.setEnabled(True)
|
||||||
|
self.OptionsAdvanced.setGeometry(QtCore.QRect(9, 253, 421, 61))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(9)
|
||||||
|
self.OptionsAdvanced.setFont(font)
|
||||||
|
self.OptionsAdvanced.setObjectName(_fromUtf8("OptionsAdvanced"))
|
||||||
|
self.gridLayout = QtGui.QGridLayout(self.OptionsAdvanced)
|
||||||
|
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
|
||||||
|
self.ProcessingBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(11)
|
||||||
|
self.ProcessingBox.setFont(font)
|
||||||
|
self.ProcessingBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.ProcessingBox.setObjectName(_fromUtf8("ProcessingBox"))
|
||||||
|
self.gridLayout.addWidget(self.ProcessingBox, 1, 0, 1, 1)
|
||||||
|
self.UpscaleBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(11)
|
||||||
|
self.UpscaleBox.setFont(font)
|
||||||
|
self.UpscaleBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.UpscaleBox.setObjectName(_fromUtf8("UpscaleBox"))
|
||||||
|
self.gridLayout.addWidget(self.UpscaleBox, 1, 1, 1, 1)
|
||||||
|
self.StretchBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(11)
|
||||||
|
self.StretchBox.setFont(font)
|
||||||
|
self.StretchBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.StretchBox.setObjectName(_fromUtf8("StretchBox"))
|
||||||
|
self.gridLayout.addWidget(self.StretchBox, 3, 1, 1, 1)
|
||||||
|
self.NoDitheringBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(11)
|
||||||
|
self.NoDitheringBox.setFont(font)
|
||||||
|
self.NoDitheringBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.NoDitheringBox.setObjectName(_fromUtf8("NoDitheringBox"))
|
||||||
|
self.gridLayout.addWidget(self.NoDitheringBox, 3, 2, 1, 1)
|
||||||
|
self.BorderBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(11)
|
||||||
|
self.BorderBox.setFont(font)
|
||||||
|
self.BorderBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.BorderBox.setObjectName(_fromUtf8("BorderBox"))
|
||||||
|
self.gridLayout.addWidget(self.BorderBox, 3, 0, 1, 1)
|
||||||
|
self.NoRotateBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(11)
|
||||||
|
self.NoRotateBox.setFont(font)
|
||||||
|
self.NoRotateBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.NoRotateBox.setObjectName(_fromUtf8("NoRotateBox"))
|
||||||
|
self.gridLayout.addWidget(self.NoRotateBox, 1, 2, 1, 1)
|
||||||
|
self.DeviceBox = QtGui.QComboBox(self.Form)
|
||||||
|
self.DeviceBox.setGeometry(QtCore.QRect(8, 200, 151, 34))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(11)
|
||||||
|
self.DeviceBox.setFont(font)
|
||||||
|
self.DeviceBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.DeviceBox.setObjectName(_fromUtf8("DeviceBox"))
|
||||||
|
self.FormatBox = QtGui.QComboBox(self.Form)
|
||||||
|
self.FormatBox.setGeometry(QtCore.QRect(262, 200, 152, 34))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(11)
|
||||||
|
self.FormatBox.setFont(font)
|
||||||
|
self.FormatBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.FormatBox.setObjectName(_fromUtf8("FormatBox"))
|
||||||
|
self.ConvertButton = QtGui.QPushButton(self.Form)
|
||||||
|
self.ConvertButton.setGeometry(QtCore.QRect(160, 200, 101, 41))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(11)
|
||||||
|
font.setBold(True)
|
||||||
|
font.setWeight(75)
|
||||||
|
self.ConvertButton.setFont(font)
|
||||||
|
self.ConvertButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
icon1 = QtGui.QIcon()
|
||||||
|
icon1.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/convert.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
self.ConvertButton.setIcon(icon1)
|
||||||
|
self.ConvertButton.setObjectName(_fromUtf8("ConvertButton"))
|
||||||
|
self.DirectoryButton = QtGui.QPushButton(self.Form)
|
||||||
|
self.DirectoryButton.setGeometry(QtCore.QRect(5, 160, 156, 41))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(11)
|
||||||
|
self.DirectoryButton.setFont(font)
|
||||||
|
self.DirectoryButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
icon2 = QtGui.QIcon()
|
||||||
|
icon2.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/folder_new.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
self.DirectoryButton.setIcon(icon2)
|
||||||
|
self.DirectoryButton.setObjectName(_fromUtf8("DirectoryButton"))
|
||||||
|
self.FileButton = QtGui.QPushButton(self.Form)
|
||||||
|
self.FileButton.setGeometry(QtCore.QRect(260, 160, 157, 41))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(11)
|
||||||
|
self.FileButton.setFont(font)
|
||||||
|
self.FileButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
icon3 = QtGui.QIcon()
|
||||||
|
icon3.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/document_new.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
self.FileButton.setIcon(icon3)
|
||||||
|
self.FileButton.setObjectName(_fromUtf8("FileButton"))
|
||||||
|
self.ClearButton = QtGui.QPushButton(self.Form)
|
||||||
|
self.ClearButton.setGeometry(QtCore.QRect(160, 160, 101, 41))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(11)
|
||||||
|
self.ClearButton.setFont(font)
|
||||||
|
self.ClearButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
icon4 = QtGui.QIcon()
|
||||||
|
icon4.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/clear.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
self.ClearButton.setIcon(icon4)
|
||||||
|
self.ClearButton.setObjectName(_fromUtf8("ClearButton"))
|
||||||
|
self.OptionsBasic = QtGui.QFrame(self.Form)
|
||||||
|
self.OptionsBasic.setGeometry(QtCore.QRect(10, 233, 421, 41))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(9)
|
||||||
|
self.OptionsBasic.setFont(font)
|
||||||
|
self.OptionsBasic.setObjectName(_fromUtf8("OptionsBasic"))
|
||||||
|
self.MangaBox = QtGui.QCheckBox(self.OptionsBasic)
|
||||||
|
self.MangaBox.setGeometry(QtCore.QRect(9, 10, 130, 18))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(11)
|
||||||
|
self.MangaBox.setFont(font)
|
||||||
|
self.MangaBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.MangaBox.setObjectName(_fromUtf8("MangaBox"))
|
||||||
|
self.QualityBox = QtGui.QCheckBox(self.OptionsBasic)
|
||||||
|
self.QualityBox.setGeometry(QtCore.QRect(282, 10, 130, 18))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(11)
|
||||||
|
self.QualityBox.setFont(font)
|
||||||
|
self.QualityBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.QualityBox.setTristate(True)
|
||||||
|
self.QualityBox.setObjectName(_fromUtf8("QualityBox"))
|
||||||
|
self.RotateBox = QtGui.QCheckBox(self.OptionsBasic)
|
||||||
|
self.RotateBox.setGeometry(QtCore.QRect(145, 10, 130, 18))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(11)
|
||||||
|
self.RotateBox.setFont(font)
|
||||||
|
self.RotateBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.RotateBox.setObjectName(_fromUtf8("RotateBox"))
|
||||||
|
self.JobList = QtGui.QListWidget(self.Form)
|
||||||
|
self.JobList.setGeometry(QtCore.QRect(10, 50, 401, 101))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(11)
|
||||||
|
self.JobList.setFont(font)
|
||||||
|
self.JobList.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.JobList.setProperty("showDropIndicator", False)
|
||||||
|
self.JobList.setSelectionMode(QtGui.QAbstractItemView.NoSelection)
|
||||||
|
self.JobList.setObjectName(_fromUtf8("JobList"))
|
||||||
|
self.BasicModeButton = QtGui.QPushButton(self.Form)
|
||||||
|
self.BasicModeButton.setGeometry(QtCore.QRect(5, 10, 210, 41))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(12)
|
||||||
|
font.setBold(False)
|
||||||
|
font.setWeight(50)
|
||||||
|
self.BasicModeButton.setFont(font)
|
||||||
|
self.BasicModeButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.BasicModeButton.setObjectName(_fromUtf8("BasicModeButton"))
|
||||||
|
self.AdvModeButton = QtGui.QPushButton(self.Form)
|
||||||
|
self.AdvModeButton.setGeometry(QtCore.QRect(207, 10, 210, 41))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(12)
|
||||||
|
font.setBold(False)
|
||||||
|
font.setWeight(50)
|
||||||
|
self.AdvModeButton.setFont(font)
|
||||||
|
self.AdvModeButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.AdvModeButton.setObjectName(_fromUtf8("AdvModeButton"))
|
||||||
|
self.OptionsAdvancedGamma = QtGui.QFrame(self.Form)
|
||||||
|
self.OptionsAdvancedGamma.setEnabled(True)
|
||||||
|
self.OptionsAdvancedGamma.setGeometry(QtCore.QRect(10, 303, 401, 41))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(9)
|
||||||
|
self.OptionsAdvancedGamma.setFont(font)
|
||||||
|
self.OptionsAdvancedGamma.setObjectName(_fromUtf8("OptionsAdvancedGamma"))
|
||||||
|
self.GammaLabel = QtGui.QLabel(self.OptionsAdvancedGamma)
|
||||||
|
self.GammaLabel.setGeometry(QtCore.QRect(20, 0, 100, 40))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(12)
|
||||||
|
font.setBold(False)
|
||||||
|
font.setWeight(50)
|
||||||
|
self.GammaLabel.setFont(font)
|
||||||
|
self.GammaLabel.setObjectName(_fromUtf8("GammaLabel"))
|
||||||
|
self.GammaSlider = QtGui.QSlider(self.OptionsAdvancedGamma)
|
||||||
|
self.GammaSlider.setGeometry(QtCore.QRect(110, 10, 280, 22))
|
||||||
|
self.GammaSlider.setFocusPolicy(QtCore.Qt.ClickFocus)
|
||||||
|
self.GammaSlider.setMaximum(500)
|
||||||
|
self.GammaSlider.setSingleStep(5)
|
||||||
|
self.GammaSlider.setOrientation(QtCore.Qt.Horizontal)
|
||||||
|
self.GammaSlider.setObjectName(_fromUtf8("GammaSlider"))
|
||||||
|
self.ProgressBar = QtGui.QProgressBar(self.Form)
|
||||||
|
self.ProgressBar.setGeometry(QtCore.QRect(10, 10, 401, 35))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(10)
|
||||||
|
font.setBold(True)
|
||||||
|
font.setWeight(75)
|
||||||
|
self.ProgressBar.setFont(font)
|
||||||
|
self.ProgressBar.setAutoFillBackground(True)
|
||||||
|
self.ProgressBar.setProperty("value", 0)
|
||||||
|
self.ProgressBar.setAlignment(QtCore.Qt.AlignJustify|QtCore.Qt.AlignVCenter)
|
||||||
|
self.ProgressBar.setFormat(_fromUtf8(""))
|
||||||
|
self.ProgressBar.setObjectName(_fromUtf8("ProgressBar"))
|
||||||
|
self.OptionsExpert = QtGui.QFrame(self.Form)
|
||||||
|
self.OptionsExpert.setGeometry(QtCore.QRect(10, 335, 421, 41))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(9)
|
||||||
|
self.OptionsExpert.setFont(font)
|
||||||
|
self.OptionsExpert.setObjectName(_fromUtf8("OptionsExpert"))
|
||||||
|
self.ColorBox = QtGui.QCheckBox(self.OptionsExpert)
|
||||||
|
self.ColorBox.setGeometry(QtCore.QRect(9, 11, 130, 18))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(11)
|
||||||
|
self.ColorBox.setFont(font)
|
||||||
|
self.ColorBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.ColorBox.setObjectName(_fromUtf8("ColorBox"))
|
||||||
|
self.OptionsExpertInternal = QtGui.QFrame(self.OptionsExpert)
|
||||||
|
self.OptionsExpertInternal.setGeometry(QtCore.QRect(90, 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.setPointSize(12)
|
||||||
|
font.setBold(False)
|
||||||
|
font.setWeight(50)
|
||||||
|
self.wLabel.setFont(font)
|
||||||
|
self.wLabel.setObjectName(_fromUtf8("wLabel"))
|
||||||
|
self.gridLayout_2.addWidget(self.wLabel, 0, 0, 1, 1)
|
||||||
|
self.customWidth = QtGui.QLineEdit(self.OptionsExpertInternal)
|
||||||
|
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.customWidth.sizePolicy().hasHeightForWidth())
|
||||||
|
self.customWidth.setSizePolicy(sizePolicy)
|
||||||
|
self.customWidth.setMaximumSize(QtCore.QSize(45, 16777215))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(12)
|
||||||
|
self.customWidth.setFont(font)
|
||||||
|
self.customWidth.setFocusPolicy(QtCore.Qt.ClickFocus)
|
||||||
|
self.customWidth.setAcceptDrops(False)
|
||||||
|
self.customWidth.setMaxLength(4)
|
||||||
|
self.customWidth.setObjectName(_fromUtf8("customWidth"))
|
||||||
|
self.gridLayout_2.addWidget(self.customWidth, 0, 1, 1, 1)
|
||||||
|
self.hLabel = QtGui.QLabel(self.OptionsExpertInternal)
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(12)
|
||||||
|
font.setBold(False)
|
||||||
|
font.setWeight(50)
|
||||||
|
self.hLabel.setFont(font)
|
||||||
|
self.hLabel.setObjectName(_fromUtf8("hLabel"))
|
||||||
|
self.gridLayout_2.addWidget(self.hLabel, 0, 2, 1, 1)
|
||||||
|
self.customHeight = QtGui.QLineEdit(self.OptionsExpertInternal)
|
||||||
|
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.customHeight.sizePolicy().hasHeightForWidth())
|
||||||
|
self.customHeight.setSizePolicy(sizePolicy)
|
||||||
|
self.customHeight.setMaximumSize(QtCore.QSize(45, 16777215))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(12)
|
||||||
|
self.customHeight.setFont(font)
|
||||||
|
self.customHeight.setFocusPolicy(QtCore.Qt.ClickFocus)
|
||||||
|
self.customHeight.setAcceptDrops(False)
|
||||||
|
self.customHeight.setMaxLength(4)
|
||||||
|
self.customHeight.setObjectName(_fromUtf8("customHeight"))
|
||||||
|
self.gridLayout_2.addWidget(self.customHeight, 0, 3, 1, 1)
|
||||||
|
KCC.setCentralWidget(self.Form)
|
||||||
|
self.ActionBasic = QtGui.QAction(KCC)
|
||||||
|
self.ActionBasic.setCheckable(True)
|
||||||
|
self.ActionBasic.setChecked(False)
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(9)
|
||||||
|
self.ActionBasic.setFont(font)
|
||||||
|
self.ActionBasic.setObjectName(_fromUtf8("ActionBasic"))
|
||||||
|
self.ActionAdvanced = QtGui.QAction(KCC)
|
||||||
|
self.ActionAdvanced.setCheckable(True)
|
||||||
|
self.ActionAdvanced.setObjectName(_fromUtf8("ActionAdvanced"))
|
||||||
|
|
||||||
|
self.retranslateUi(KCC)
|
||||||
|
QtCore.QMetaObject.connectSlotsByName(KCC)
|
||||||
|
KCC.setTabOrder(self.DirectoryButton, self.FileButton)
|
||||||
|
KCC.setTabOrder(self.FileButton, self.ConvertButton)
|
||||||
|
KCC.setTabOrder(self.ConvertButton, self.ClearButton)
|
||||||
|
|
||||||
|
def retranslateUi(self, KCC):
|
||||||
|
KCC.setWindowTitle(_translate("KCC", "Kindle Comic Converter", None))
|
||||||
|
self.ProcessingBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Disable image optimizations.</span></p></body></html>", None))
|
||||||
|
self.ProcessingBox.setText(_translate("KCC", "No optimisation", None))
|
||||||
|
self.UpscaleBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Enable image upscaling.<br/>Aspect ratio will be preserved.</span></p></body></html>", None))
|
||||||
|
self.UpscaleBox.setText(_translate("KCC", "Upscale images", None))
|
||||||
|
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.StretchBox.setText(_translate("KCC", "Stretch images", None))
|
||||||
|
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.NoDitheringBox.setText(_translate("KCC", "PNG output", None))
|
||||||
|
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.BorderBox.setText(_translate("KCC", "Black borders", None))
|
||||||
|
self.NoRotateBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Disable splitting and rotation.</span></p></body></html>", None))
|
||||||
|
self.NoRotateBox.setText(_translate("KCC", "No split/rotate", None))
|
||||||
|
self.DeviceBox.setToolTip(_translate("KCC", "Target device.", None))
|
||||||
|
self.FormatBox.setToolTip(_translate("KCC", "Output format.", None))
|
||||||
|
self.ConvertButton.setText(_translate("KCC", "Convert", None))
|
||||||
|
self.DirectoryButton.setText(_translate("KCC", "Add directory", None))
|
||||||
|
self.FileButton.setText(_translate("KCC", "Add file", None))
|
||||||
|
self.ClearButton.setText(_translate("KCC", "Clear list", None))
|
||||||
|
self.MangaBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Enable right-to-left reading.</span></p></body></html>", None))
|
||||||
|
self.MangaBox.setText(_translate("KCC", "Manga mode", None))
|
||||||
|
self.QualityBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-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.QualityBox.setText(_translate("KCC", "High/Ultra quality", None))
|
||||||
|
self.RotateBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Disable page spliting.<br/>They will be rotated instead.</span></p></body></html>", None))
|
||||||
|
self.RotateBox.setText(_translate("KCC", "Horizontal mode", None))
|
||||||
|
self.BasicModeButton.setText(_translate("KCC", "Basic", None))
|
||||||
|
self.AdvModeButton.setText(_translate("KCC", "Advanced", None))
|
||||||
|
self.GammaLabel.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.GammaLabel.setText(_translate("KCC", "Gamma: Auto", None))
|
||||||
|
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.ColorBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Do not convert images to grayscale.</span></p></body></html>", None))
|
||||||
|
self.ColorBox.setText(_translate("KCC", "Color mode", None))
|
||||||
|
self.wLabel.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Resolution of target device.</span></p></body></html>", None))
|
||||||
|
self.wLabel.setText(_translate("KCC", "Custom width: ", None))
|
||||||
|
self.customWidth.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Resolution of target device.</span></p></body></html>", None))
|
||||||
|
self.customWidth.setInputMask(_translate("KCC", "0000; ", None))
|
||||||
|
self.hLabel.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Resolution of target device.</span></p></body></html>", None))
|
||||||
|
self.hLabel.setText(_translate("KCC", "Custom height: ", None))
|
||||||
|
self.customHeight.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Resolution of target device.</span></p></body></html>", None))
|
||||||
|
self.customHeight.setInputMask(_translate("KCC", "0000; ", None))
|
||||||
|
self.ActionBasic.setText(_translate("KCC", "Basic", None))
|
||||||
|
self.ActionAdvanced.setText(_translate("KCC", "Advanced", None))
|
||||||
|
|
||||||
|
import KCC_rc
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
__version__ = '2.10'
|
__version__ = '3.0'
|
||||||
__license__ = 'ISC'
|
__license__ = 'ISC'
|
||||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>'
|
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
# PERFORMANCE OF THIS SOFTWARE.
|
# PERFORMANCE OF THIS SOFTWARE.
|
||||||
#
|
#
|
||||||
__license__ = 'ISC'
|
__license__ = 'ISC'
|
||||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>'
|
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import os
|
import os
|
||||||
@@ -23,6 +23,7 @@ import zipfile
|
|||||||
import rarfile
|
import rarfile
|
||||||
|
|
||||||
|
|
||||||
|
# noinspection PyBroadException
|
||||||
class CBxArchive:
|
class CBxArchive:
|
||||||
def __init__(self, origFileName):
|
def __init__(self, origFileName):
|
||||||
self.origFileName = origFileName
|
self.origFileName = origFileName
|
||||||
@@ -40,7 +41,7 @@ class CBxArchive:
|
|||||||
cbzFile = zipfile.ZipFile(self.origFileName)
|
cbzFile = zipfile.ZipFile(self.origFileName)
|
||||||
filelist = []
|
filelist = []
|
||||||
for f in cbzFile.namelist():
|
for f in cbzFile.namelist():
|
||||||
if f.startswith('__MACOSX') or f.endswith('.DS_Store'):
|
if f.startswith('__MACOSX') or f.endswith('.DS_Store') or f.endswith('thumbs.db'):
|
||||||
pass # skip MacOS special files
|
pass # skip MacOS special files
|
||||||
elif f.endswith('/'):
|
elif f.endswith('/'):
|
||||||
try:
|
try:
|
||||||
@@ -55,7 +56,7 @@ class CBxArchive:
|
|||||||
cbrFile = rarfile.RarFile(self.origFileName)
|
cbrFile = rarfile.RarFile(self.origFileName)
|
||||||
filelist = []
|
filelist = []
|
||||||
for f in cbrFile.namelist():
|
for f in cbrFile.namelist():
|
||||||
if f.startswith('__MACOSX') or f.endswith('.DS_Store'):
|
if f.startswith('__MACOSX') or f.endswith('.DS_Store') or f.endswith('thumbs.db'):
|
||||||
pass # skip MacOS special files
|
pass # skip MacOS special files
|
||||||
elif f.endswith('/'):
|
elif f.endswith('/'):
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -17,22 +17,28 @@
|
|||||||
# 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__ = '2.10'
|
__version__ = '3.0'
|
||||||
__license__ = 'ISC'
|
__license__ = 'ISC'
|
||||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>'
|
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import re
|
import re
|
||||||
|
import stat
|
||||||
|
import string
|
||||||
from shutil import move
|
from shutil import move
|
||||||
from shutil import copyfile
|
from shutil import copyfile
|
||||||
from shutil import copytree
|
from shutil import copytree
|
||||||
from shutil import rmtree
|
from shutil import rmtree
|
||||||
from shutil import make_archive
|
from shutil import make_archive
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
from multiprocessing import Pool, freeze_support
|
from multiprocessing import Pool, Queue, freeze_support
|
||||||
|
try:
|
||||||
|
from PyQt4 import QtCore
|
||||||
|
except ImportError:
|
||||||
|
QtCore = None
|
||||||
import image
|
import image
|
||||||
import cbxarchive
|
import cbxarchive
|
||||||
import pdfjpgextract
|
import pdfjpgextract
|
||||||
@@ -42,7 +48,7 @@ def buildHTML(path, imgfile):
|
|||||||
filename = getImageFileName(imgfile)
|
filename = getImageFileName(imgfile)
|
||||||
if filename is not None:
|
if filename is not None:
|
||||||
# All files marked with this sufix need horizontal Panel View.
|
# All files marked with this sufix need horizontal Panel View.
|
||||||
if "_rotated" in str(filename):
|
if "_kccrotated" in str(filename):
|
||||||
rotate = True
|
rotate = True
|
||||||
else:
|
else:
|
||||||
rotate = False
|
rotate = False
|
||||||
@@ -118,19 +124,24 @@ def buildHTML(path, imgfile):
|
|||||||
"<div id=\"BoxBR\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify="
|
"<div id=\"BoxBR\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify="
|
||||||
"'{\"targetId\":\"BoxBR-Panel-Parent\", \"ordinal\":4}'></a></div>\n"
|
"'{\"targetId\":\"BoxBR-Panel-Parent\", \"ordinal\":4}'></a></div>\n"
|
||||||
])
|
])
|
||||||
|
if options.quality == 2:
|
||||||
|
imgfilepv = string.split(imgfile, ".")
|
||||||
|
imgfilepv[0] += "_kcchq"
|
||||||
|
imgfilepv = string.join(imgfilepv, ".")
|
||||||
|
else:
|
||||||
|
imgfilepv = imgfile
|
||||||
f.writelines(["<div id=\"BoxTL-Panel-Parent\" class=\"target-mag-parent\"><div id=\"BoxTL-Panel\" class=\"",
|
f.writelines(["<div id=\"BoxTL-Panel-Parent\" class=\"target-mag-parent\"><div id=\"BoxTL-Panel\" class=\"",
|
||||||
"target-mag\"><img src=\"", "../" * backref, "Images/", postfix, imgfile, "\" alt=\"",
|
"target-mag\"><img src=\"", "../" * backref, "Images/", postfix, imgfilepv, "\" alt=\"",
|
||||||
imgfile, "\"/></div></div>\n",
|
imgfilepv, "\"/></div></div>\n",
|
||||||
"<div id=\"BoxTR-Panel-Parent\" class=\"target-mag-parent\"><div id=\"BoxTR-Panel\" class=\"",
|
"<div id=\"BoxTR-Panel-Parent\" class=\"target-mag-parent\"><div id=\"BoxTR-Panel\" class=\"",
|
||||||
"target-mag\"><img src=\"", "../" * backref, "Images/", postfix, imgfile, "\" alt=\"",
|
"target-mag\"><img src=\"", "../" * backref, "Images/", postfix, imgfilepv, "\" alt=\"",
|
||||||
imgfile, "\"/></div></div>\n",
|
imgfilepv, "\"/></div></div>\n",
|
||||||
"<div id=\"BoxBL-Panel-Parent\" class=\"target-mag-parent\"><div id=\"BoxBL-Panel\" class=\"",
|
"<div id=\"BoxBL-Panel-Parent\" class=\"target-mag-parent\"><div id=\"BoxBL-Panel\" class=\"",
|
||||||
"target-mag\"><img src=\"", "../" * backref, "Images/", postfix, imgfile, "\" alt=\"",
|
"target-mag\"><img src=\"", "../" * backref, "Images/", postfix, imgfilepv, "\" alt=\"",
|
||||||
imgfile, "\"/></div></div>\n",
|
imgfilepv, "\"/></div></div>\n",
|
||||||
"<div id=\"BoxBR-Panel-Parent\" class=\"target-mag-parent\"><div id=\"BoxBR-Panel\" class=\"",
|
"<div id=\"BoxBR-Panel-Parent\" class=\"target-mag-parent\"><div id=\"BoxBR-Panel\" class=\"",
|
||||||
"target-mag\"><img src=\"", "../" * backref, "Images/", postfix, imgfile, "\" alt=\"",
|
"target-mag\"><img src=\"", "../" * backref, "Images/", postfix, imgfilepv, "\" alt=\"",
|
||||||
imgfile, "\"/></div></div>\n"
|
imgfilepv, "\"/></div></div>\n"
|
||||||
])
|
])
|
||||||
f.writelines(["</div>\n</body>\n</html>"])
|
f.writelines(["</div>\n</body>\n</html>"])
|
||||||
f.close()
|
f.close()
|
||||||
@@ -154,6 +165,9 @@ def buildBlankHTML(path):
|
|||||||
|
|
||||||
|
|
||||||
def buildNCX(dstdir, title, chapters):
|
def buildNCX(dstdir, title, chapters):
|
||||||
|
from uuid import uuid4
|
||||||
|
options.uuid = str(uuid4())
|
||||||
|
options.uuid = options.uuid.encode('utf-8')
|
||||||
ncxfile = os.path.join(dstdir, 'OEBPS', 'toc.ncx')
|
ncxfile = os.path.join(dstdir, 'OEBPS', 'toc.ncx')
|
||||||
f = open(ncxfile, "w")
|
f = open(ncxfile, "w")
|
||||||
f.writelines(["<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
|
f.writelines(["<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
|
||||||
@@ -161,7 +175,7 @@ def buildNCX(dstdir, title, chapters):
|
|||||||
"\"http://www.daisy.org/z3986/2005/ncx-2005-1.dtd\">\n",
|
"\"http://www.daisy.org/z3986/2005/ncx-2005-1.dtd\">\n",
|
||||||
"<ncx version=\"2005-1\" xml:lang=\"en-US\" xmlns=\"http://www.daisy.org/z3986/2005/ncx/\">\n",
|
"<ncx version=\"2005-1\" xml:lang=\"en-US\" xmlns=\"http://www.daisy.org/z3986/2005/ncx/\">\n",
|
||||||
"<head>\n",
|
"<head>\n",
|
||||||
"<meta name=\"dtb:uid\" content=\"015ffaec-9340-42f8-b163-a0c5ab7d0611\"/>\n",
|
"<meta name=\"dtb:uid\" content=\"", options.uuid, "\"/>\n",
|
||||||
"<meta name=\"dtb:depth\" content=\"2\"/>\n",
|
"<meta name=\"dtb:depth\" content=\"2\"/>\n",
|
||||||
"<meta name=\"dtb:totalPageCount\" content=\"0\"/>\n",
|
"<meta name=\"dtb:totalPageCount\" content=\"0\"/>\n",
|
||||||
"<meta name=\"dtb:maxPageNumber\" content=\"0\"/>\n",
|
"<meta name=\"dtb:maxPageNumber\" content=\"0\"/>\n",
|
||||||
@@ -174,16 +188,15 @@ def buildNCX(dstdir, title, chapters):
|
|||||||
title = os.path.basename(folder)
|
title = os.path.basename(folder)
|
||||||
filename = getImageFileName(os.path.join(folder, chapter[1]))
|
filename = getImageFileName(os.path.join(folder, chapter[1]))
|
||||||
f.write("<navPoint id=\"" + folder.replace('/', '_').replace('\\', '_') + "\"><navLabel><text>" + title
|
f.write("<navPoint id=\"" + folder.replace('/', '_').replace('\\', '_') + "\"><navLabel><text>" + title
|
||||||
+ "</text></navLabel><content src=\"" + filename[0] + ".html\"/></navPoint>\n")
|
+ "</text></navLabel><content src=\"" + filename[0].replace("\\", "/") + ".html\"/></navPoint>\n")
|
||||||
f.write("</navMap>\n</ncx>")
|
f.write("</navMap>\n</ncx>")
|
||||||
f.close()
|
f.close()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
def buildOPF(profile, dstdir, title, filelist, cover=None):
|
def buildOPF(dstdir, title, filelist, cover=None):
|
||||||
opffile = os.path.join(dstdir, 'OEBPS', 'content.opf')
|
opffile = os.path.join(dstdir, 'OEBPS', 'content.opf')
|
||||||
# read the first file resolution
|
profilelabel, deviceres, palette, gamma, panelviewsize = options.profileData
|
||||||
profilelabel, deviceres, palette, gamma, panelviewsize = image.ProfileData.Profiles[profile]
|
|
||||||
imgres = str(deviceres[0]) + "x" + str(deviceres[1])
|
imgres = str(deviceres[0]) + "x" + str(deviceres[1])
|
||||||
if options.righttoleft:
|
if options.righttoleft:
|
||||||
writingmode = "horizontal-rl"
|
writingmode = "horizontal-rl"
|
||||||
@@ -195,9 +208,6 @@ def buildOPF(profile, dstdir, title, filelist, cover=None):
|
|||||||
facing = "left"
|
facing = "left"
|
||||||
facing1 = "left"
|
facing1 = "left"
|
||||||
facing2 = "right"
|
facing2 = "right"
|
||||||
from uuid import uuid4
|
|
||||||
uuid = str(uuid4())
|
|
||||||
uuid = uuid.encode('utf-8')
|
|
||||||
f = open(opffile, "w")
|
f = open(opffile, "w")
|
||||||
f.writelines(["<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
|
f.writelines(["<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
|
||||||
"<package version=\"2.0\" unique-identifier=\"BookID\" xmlns=\"http://www.idpf.org/2007/opf\">\n",
|
"<package version=\"2.0\" unique-identifier=\"BookID\" xmlns=\"http://www.idpf.org/2007/opf\">\n",
|
||||||
@@ -205,7 +215,7 @@ def buildOPF(profile, dstdir, title, filelist, cover=None):
|
|||||||
"xmlns:opf=\"http://www.idpf.org/2007/opf\">\n",
|
"xmlns:opf=\"http://www.idpf.org/2007/opf\">\n",
|
||||||
"<dc:title>", title, "</dc:title>\n",
|
"<dc:title>", title, "</dc:title>\n",
|
||||||
"<dc:language>en-US</dc:language>\n",
|
"<dc:language>en-US</dc:language>\n",
|
||||||
"<dc:identifier id=\"BookID\" opf:scheme=\"UUID\">", uuid, "</dc:identifier>\n",
|
"<dc:identifier id=\"BookID\" opf:scheme=\"UUID\">", options.uuid, "</dc:identifier>\n",
|
||||||
"<meta name=\"RegionMagnification\" content=\"true\"/>\n",
|
"<meta name=\"RegionMagnification\" content=\"true\"/>\n",
|
||||||
"<meta name=\"cover\" content=\"cover\"/>\n",
|
"<meta name=\"cover\" content=\"cover\"/>\n",
|
||||||
"<meta name=\"book-type\" content=\"comic\"/>\n",
|
"<meta name=\"book-type\" content=\"comic\"/>\n",
|
||||||
@@ -230,10 +240,10 @@ def buildOPF(profile, dstdir, title, filelist, cover=None):
|
|||||||
mt = 'image/png'
|
mt = 'image/png'
|
||||||
else:
|
else:
|
||||||
mt = 'image/jpeg'
|
mt = 'image/jpeg'
|
||||||
f.write("<item id=\"cover\" href=\"" + filename[0] + filename[1] + "\" media-type=\"" + mt + "\"/>\n")
|
f.write("<item id=\"cover\" href=\"Images/cover" + filename[1] + "\" media-type=\"" + mt + "\"/>\n")
|
||||||
reflist = []
|
reflist = []
|
||||||
for path in filelist:
|
for path in filelist:
|
||||||
folder = path[0].replace(os.path.join(dstdir, 'OEBPS'), '').lstrip('/').lstrip('\\\\')
|
folder = path[0].replace(os.path.join(dstdir, 'OEBPS'), '').lstrip('/').lstrip('\\\\').replace("\\", "/")
|
||||||
filename = getImageFileName(path[1])
|
filename = getImageFileName(path[1])
|
||||||
uniqueid = os.path.join(folder, filename[0]).replace('/', '_').replace('\\', '_')
|
uniqueid = os.path.join(folder, filename[0]).replace('/', '_').replace('\\', '_')
|
||||||
reflist.append(uniqueid)
|
reflist.append(uniqueid)
|
||||||
@@ -256,7 +266,7 @@ def buildOPF(profile, dstdir, title, filelist, cover=None):
|
|||||||
f.write("</manifest>\n<spine toc=\"ncx\">\n")
|
f.write("</manifest>\n<spine toc=\"ncx\">\n")
|
||||||
splitCountUsed = 1
|
splitCountUsed = 1
|
||||||
for entry in reflist:
|
for entry in reflist:
|
||||||
if entry.endswith("-kcca"):
|
if "_kcca" in str(entry):
|
||||||
# noinspection PyRedundantParentheses
|
# noinspection PyRedundantParentheses
|
||||||
if ((options.righttoleft and facing == 'left') or (not options.righttoleft and facing == 'right')) and\
|
if ((options.righttoleft and facing == 'left') or (not options.righttoleft and facing == 'right')) and\
|
||||||
options.landscapemode:
|
options.landscapemode:
|
||||||
@@ -266,7 +276,7 @@ def buildOPF(profile, dstdir, title, filelist, cover=None):
|
|||||||
f.write("<itemref idref=\"page_" + entry + "\" properties=\"page-spread-" + facing1 + "\"/>\n")
|
f.write("<itemref idref=\"page_" + entry + "\" properties=\"page-spread-" + facing1 + "\"/>\n")
|
||||||
else:
|
else:
|
||||||
f.write("<itemref idref=\"page_" + entry + "\"/>\n")
|
f.write("<itemref idref=\"page_" + entry + "\"/>\n")
|
||||||
elif entry.endswith("-kccb"):
|
elif "_kccb" in str(entry):
|
||||||
if options.landscapemode:
|
if options.landscapemode:
|
||||||
f.write("<itemref idref=\"page_" + entry + "\" properties=\"page-spread-" + facing2 + "\"/>\n")
|
f.write("<itemref idref=\"page_" + entry + "\" properties=\"page-spread-" + facing2 + "\"/>\n")
|
||||||
else:
|
else:
|
||||||
@@ -315,14 +325,18 @@ def getImageFileName(imgfile):
|
|||||||
return filename
|
return filename
|
||||||
|
|
||||||
|
|
||||||
def applyImgOptimization(img, isSplit, toRight, options):
|
def applyImgOptimization(img, isSplit, toRight, options, overrideQuality=5):
|
||||||
img.cropWhiteSpace(10.0)
|
img.cropWhiteSpace(10.0)
|
||||||
if options.cutpagenumbers:
|
if options.cutpagenumbers:
|
||||||
img.cutPageNumber()
|
img.cutPageNumber()
|
||||||
img.resizeImage(options.upscale, options.stretch, options.black_borders, isSplit, toRight, options.landscapemode,
|
if overrideQuality != 5:
|
||||||
options.nopanelviewhq)
|
img.resizeImage(options.upscale, options.stretch, options.black_borders, isSplit, toRight,
|
||||||
|
options.landscapemode, overrideQuality)
|
||||||
|
else:
|
||||||
|
img.resizeImage(options.upscale, options.stretch, options.black_borders, isSplit, toRight,
|
||||||
|
options.landscapemode, options.quality)
|
||||||
img.optimizeImage(options.gamma)
|
img.optimizeImage(options.gamma)
|
||||||
if options.forcepng:
|
if options.forcepng and not options.forcecolor:
|
||||||
img.quantizeImage()
|
img.quantizeImage()
|
||||||
|
|
||||||
|
|
||||||
@@ -331,35 +345,64 @@ def dirImgProcess(path):
|
|||||||
work = []
|
work = []
|
||||||
pagenumber = 0
|
pagenumber = 0
|
||||||
pagenumbermodifier = 0
|
pagenumbermodifier = 0
|
||||||
pool = Pool()
|
queue = Queue()
|
||||||
|
pool = Pool(None, fileImgProcess_init, [queue, options])
|
||||||
for (dirpath, dirnames, filenames) in os.walk(path):
|
for (dirpath, dirnames, filenames) in os.walk(path):
|
||||||
for afile in filenames:
|
for afile in filenames:
|
||||||
if getImageFileName(afile) is not None:
|
if getImageFileName(afile) is not None:
|
||||||
pagenumber += 1
|
pagenumber += 1
|
||||||
work.append([afile, dirpath, pagenumber, options])
|
work.append([afile, dirpath, pagenumber])
|
||||||
splitpages = pool.map(fileImgProcess, work)
|
if GUI:
|
||||||
pool.close()
|
GUI.emit(QtCore.SIGNAL("progressBarTick"), pagenumber)
|
||||||
pool.join()
|
if len(work) > 0:
|
||||||
splitpages = filter(None, splitpages)
|
splitpages = pool.map_async(func=fileImgProcess, iterable=work)
|
||||||
splitpages.sort()
|
pool.close()
|
||||||
for page in splitpages:
|
if GUI:
|
||||||
if (page + pagenumbermodifier) % 2 == 0:
|
while not splitpages.ready():
|
||||||
splitCount += 1
|
# noinspection PyBroadException
|
||||||
|
try:
|
||||||
|
queue.get(True, 1)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
GUI.emit(QtCore.SIGNAL("progressBarTick"))
|
||||||
|
pool.join()
|
||||||
|
queue.close()
|
||||||
|
try:
|
||||||
|
splitpages = splitpages.get()
|
||||||
|
except:
|
||||||
|
rmtree(path)
|
||||||
|
raise RuntimeError("One of workers crashed. Cause: " + str(sys.exc_info()[1]))
|
||||||
|
splitpages = filter(None, splitpages)
|
||||||
|
splitpages.sort()
|
||||||
|
for page in splitpages:
|
||||||
|
if (page + pagenumbermodifier) % 2 == 0:
|
||||||
|
splitCount += 1
|
||||||
|
pagenumbermodifier += 1
|
||||||
pagenumbermodifier += 1
|
pagenumbermodifier += 1
|
||||||
pagenumbermodifier += 1
|
|
||||||
|
|
||||||
|
|
||||||
|
def fileImgProcess_init(queue, options):
|
||||||
|
fileImgProcess.queue = queue
|
||||||
|
fileImgProcess.options = options
|
||||||
|
|
||||||
|
|
||||||
|
# noinspection PyUnresolvedReferences
|
||||||
def fileImgProcess(work):
|
def fileImgProcess(work):
|
||||||
afile = work[0]
|
afile = work[0]
|
||||||
dirpath = work[1]
|
dirpath = work[1]
|
||||||
pagenumber = work[2]
|
pagenumber = work[2]
|
||||||
options = work[3]
|
options = fileImgProcess.options
|
||||||
output = None
|
output = None
|
||||||
if options.verbose:
|
if options.verbose:
|
||||||
print "Optimizing " + afile + " for " + options.profile
|
print "Optimizing " + afile + " for " + options.profile
|
||||||
else:
|
else:
|
||||||
print ".",
|
print ".",
|
||||||
img = image.ComicPage(os.path.join(dirpath, afile), options.profile)
|
fileImgProcess.queue.put(".")
|
||||||
|
img = image.ComicPage(os.path.join(dirpath, afile), options.profileData)
|
||||||
|
if options.quality == 2:
|
||||||
|
wipe = False
|
||||||
|
else:
|
||||||
|
wipe = True
|
||||||
if options.nosplitrotate:
|
if options.nosplitrotate:
|
||||||
split = None
|
split = None
|
||||||
else:
|
else:
|
||||||
@@ -374,15 +417,28 @@ def fileImgProcess(work):
|
|||||||
toRight1 = True
|
toRight1 = True
|
||||||
toRight2 = False
|
toRight2 = False
|
||||||
output = pagenumber
|
output = pagenumber
|
||||||
img0 = image.ComicPage(split[0], options.profile)
|
img0 = image.ComicPage(split[0], options.profileData)
|
||||||
applyImgOptimization(img0, True, toRight1, options)
|
applyImgOptimization(img0, True, toRight1, options)
|
||||||
img0.saveToDir(dirpath, options.forcepng, options.forcecolor)
|
img0.saveToDir(dirpath, options.forcepng, options.forcecolor, wipe)
|
||||||
img1 = image.ComicPage(split[1], options.profile)
|
img1 = image.ComicPage(split[1], options.profileData)
|
||||||
applyImgOptimization(img1, True, toRight2, options)
|
applyImgOptimization(img1, True, toRight2, options)
|
||||||
img1.saveToDir(dirpath, options.forcepng, options.forcecolor)
|
img1.saveToDir(dirpath, options.forcepng, options.forcecolor, wipe)
|
||||||
|
if options.quality == 2:
|
||||||
|
img3 = image.ComicPage(split[0], options.profileData)
|
||||||
|
applyImgOptimization(img3, True, toRight1, options, 0)
|
||||||
|
img3.saveToDir(dirpath, options.forcepng, options.forcecolor, True)
|
||||||
|
img4 = image.ComicPage(split[1], options.profileData)
|
||||||
|
applyImgOptimization(img4, True, toRight2, options, 0)
|
||||||
|
img4.saveToDir(dirpath, options.forcepng, options.forcecolor, True)
|
||||||
else:
|
else:
|
||||||
applyImgOptimization(img, False, False, options)
|
applyImgOptimization(img, False, False, options)
|
||||||
img.saveToDir(dirpath, options.forcepng, options.forcecolor, split)
|
img.saveToDir(dirpath, options.forcepng, options.forcecolor, wipe, split)
|
||||||
|
if options.quality == 2:
|
||||||
|
img2 = image.ComicPage(os.path.join(dirpath, afile), options.profileData)
|
||||||
|
if split == "R":
|
||||||
|
img2.image = img2.image.rotate(90)
|
||||||
|
applyImgOptimization(img2, False, False, options, 0)
|
||||||
|
img2.saveToDir(dirpath, options.forcepng, options.forcecolor, True, split)
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
|
||||||
@@ -391,7 +447,7 @@ def genEpubStruct(path):
|
|||||||
filelist = []
|
filelist = []
|
||||||
chapterlist = []
|
chapterlist = []
|
||||||
cover = None
|
cover = None
|
||||||
_, deviceres, _, _, panelviewsize = image.ProfileData.Profiles[options.profile]
|
_, deviceres, _, _, panelviewsize = options.profileData
|
||||||
sanitizeTree(os.path.join(path, 'OEBPS', 'Images'))
|
sanitizeTree(os.path.join(path, 'OEBPS', 'Images'))
|
||||||
os.mkdir(os.path.join(path, 'OEBPS', 'Text'))
|
os.mkdir(os.path.join(path, 'OEBPS', 'Text'))
|
||||||
f = open(os.path.join(path, 'OEBPS', 'Text', 'style.css'), 'w')
|
f = open(os.path.join(path, 'OEBPS', 'Text', 'style.css'), 'w')
|
||||||
@@ -518,20 +574,21 @@ def genEpubStruct(path):
|
|||||||
chapter = False
|
chapter = False
|
||||||
for afile in filenames:
|
for afile in filenames:
|
||||||
filename = getImageFileName(afile)
|
filename = getImageFileName(afile)
|
||||||
if filename is not None:
|
if filename is not None and not "_kcchq" in filename[0]:
|
||||||
filelist.append(buildHTML(dirpath, afile))
|
filelist.append(buildHTML(dirpath, afile))
|
||||||
if not chapter:
|
if not chapter:
|
||||||
chapterlist.append((dirpath.replace('Images', 'Text'), filelist[-1][1]))
|
chapterlist.append((dirpath.replace('Images', 'Text'), filelist[-1][1]))
|
||||||
chapter = True
|
chapter = True
|
||||||
if cover is None:
|
if cover is None:
|
||||||
cover = os.path.join(filelist[-1][0], 'cover' + getImageFileName(filelist[-1][1])[1])
|
cover = os.path.join(os.path.join(path, 'OEBPS', 'Images'),
|
||||||
|
'cover' + getImageFileName(filelist[-1][1])[1])
|
||||||
copyfile(os.path.join(filelist[-1][0], filelist[-1][1]), cover)
|
copyfile(os.path.join(filelist[-1][0], filelist[-1][1]), cover)
|
||||||
buildNCX(path, options.title, chapterlist)
|
buildNCX(path, options.title, chapterlist)
|
||||||
# ensure we're sorting files alphabetically
|
# ensure we're sorting files alphabetically
|
||||||
convert = lambda text: int(text) if text.isdigit() else text
|
convert = lambda text: int(text) if text.isdigit() else text
|
||||||
alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)]
|
alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)]
|
||||||
filelist.sort(key=lambda name: (alphanum_key(name[0].lower()), alphanum_key(name[1].lower())))
|
filelist.sort(key=lambda name: (alphanum_key(name[0].lower()), alphanum_key(name[1].lower())))
|
||||||
buildOPF(options.profile, path, options.title, filelist, cover)
|
buildOPF(path, options.title, filelist, cover)
|
||||||
if options.landscapemode and splitCount > 0:
|
if options.landscapemode and splitCount > 0:
|
||||||
filelist.append(buildBlankHTML(os.path.join(path, 'OEBPS', 'Text')))
|
filelist.append(buildBlankHTML(os.path.join(path, 'OEBPS', 'Text')))
|
||||||
|
|
||||||
@@ -540,11 +597,13 @@ def getWorkFolder(afile):
|
|||||||
workdir = tempfile.mkdtemp()
|
workdir = tempfile.mkdtemp()
|
||||||
if os.path.isdir(afile):
|
if os.path.isdir(afile):
|
||||||
try:
|
try:
|
||||||
import shutil
|
|
||||||
os.rmdir(workdir) # needed for copytree() fails if dst already exists
|
os.rmdir(workdir) # needed for copytree() fails if dst already exists
|
||||||
copytree(afile, workdir)
|
fullPath = os.path.join(workdir, 'OEBPS', 'Images')
|
||||||
path = workdir
|
copytree(afile, fullPath)
|
||||||
|
sanitizeTreeBeforeConversion(fullPath)
|
||||||
|
return workdir
|
||||||
except OSError:
|
except OSError:
|
||||||
|
rmtree(workdir)
|
||||||
raise
|
raise
|
||||||
elif afile.lower().endswith('.pdf'):
|
elif afile.lower().endswith('.pdf'):
|
||||||
pdf = pdfjpgextract.PdfJpgExtract(afile)
|
pdf = pdfjpgextract.PdfJpgExtract(afile)
|
||||||
@@ -555,10 +614,12 @@ def getWorkFolder(afile):
|
|||||||
try:
|
try:
|
||||||
path = cbx.extract(workdir)
|
path = cbx.extract(workdir)
|
||||||
except OSError:
|
except OSError:
|
||||||
|
rmtree(workdir)
|
||||||
print 'Unrar not found, please download from ' + \
|
print 'Unrar not found, please download from ' + \
|
||||||
'http://www.rarlab.com/download.htm and put into your PATH.'
|
'http://www.rarlab.com/download.htm and put into your PATH.'
|
||||||
sys.exit(21)
|
sys.exit(21)
|
||||||
else:
|
else:
|
||||||
|
rmtree(workdir)
|
||||||
raise TypeError
|
raise TypeError
|
||||||
move(path, path + "_temp")
|
move(path, path + "_temp")
|
||||||
move(path + "_temp", os.path.join(path, 'OEBPS', 'Images'))
|
move(path + "_temp", os.path.join(path, 'OEBPS', 'Images'))
|
||||||
@@ -566,10 +627,8 @@ def getWorkFolder(afile):
|
|||||||
|
|
||||||
|
|
||||||
def slugify(value):
|
def slugify(value):
|
||||||
"""
|
# Normalizes string, converts to lowercase, removes non-alpha characters,
|
||||||
Normalizes string, converts to lowercase, removes non-alpha characters,
|
# and converts spaces to hyphens.
|
||||||
and converts spaces to hyphens.
|
|
||||||
"""
|
|
||||||
import unicodedata
|
import unicodedata
|
||||||
value = unicodedata.normalize('NFKD', unicode(value, 'latin1')).encode('ascii', 'ignore')
|
value = unicodedata.normalize('NFKD', unicode(value, 'latin1')).encode('ascii', 'ignore')
|
||||||
value = re.sub('[^\w\s\.-]', '', value).strip().lower()
|
value = re.sub('[^\w\s\.-]', '', value).strip().lower()
|
||||||
@@ -597,6 +656,17 @@ def sanitizeTree(filetree):
|
|||||||
os.rename(os.path.join(root, name), os.path.join(root, slugify(name)))
|
os.rename(os.path.join(root, name), os.path.join(root, slugify(name)))
|
||||||
|
|
||||||
|
|
||||||
|
def sanitizeTreeBeforeConversion(filetree):
|
||||||
|
for root, dirs, files in os.walk(filetree, False):
|
||||||
|
for name in files:
|
||||||
|
os.chmod(os.path.join(root, name), stat.S_IWRITE | stat.S_IREAD)
|
||||||
|
# Detect corrupted files - Phase 1
|
||||||
|
if os.path.getsize(os.path.join(root, name)) == 0:
|
||||||
|
os.remove(os.path.join(root, name))
|
||||||
|
for name in dirs:
|
||||||
|
os.chmod(os.path.join(root, name), stat.S_IWRITE | stat.S_IREAD | stat.S_IEXEC)
|
||||||
|
|
||||||
|
|
||||||
def Copyright():
|
def Copyright():
|
||||||
print ('comic2ebook v%(__version__)s. '
|
print ('comic2ebook v%(__version__)s. '
|
||||||
'Written 2013 by Ciro Mattia Gonano and Pawel Jastrzebski.' % globals())
|
'Written 2013 by Ciro Mattia Gonano and Pawel Jastrzebski.' % globals())
|
||||||
@@ -607,8 +677,8 @@ def Usage():
|
|||||||
parser.print_help()
|
parser.print_help()
|
||||||
|
|
||||||
|
|
||||||
def main(argv=None):
|
def main(argv=None, qtGUI=None):
|
||||||
global parser, options, epub_path, splitCount
|
global parser, options, epub_path, splitCount, GUI
|
||||||
usage = "Usage: %prog [options] comic_file|comic_folder"
|
usage = "Usage: %prog [options] comic_file|comic_folder"
|
||||||
parser = OptionParser(usage=usage, version=__version__)
|
parser = OptionParser(usage=usage, version=__version__)
|
||||||
parser.add_option("-p", "--profile", action="store", dest="profile", default="KHD",
|
parser.add_option("-p", "--profile", action="store", dest="profile", default="KHD",
|
||||||
@@ -618,10 +688,10 @@ def main(argv=None):
|
|||||||
help="Comic title [Default=filename]")
|
help="Comic title [Default=filename]")
|
||||||
parser.add_option("-m", "--manga-style", action="store_true", dest="righttoleft", default=False,
|
parser.add_option("-m", "--manga-style", action="store_true", dest="righttoleft", default=False,
|
||||||
help="Manga style (Right-to-left reading and splitting) [Default=False]")
|
help="Manga style (Right-to-left reading and splitting) [Default=False]")
|
||||||
|
parser.add_option("--quality", type="int", dest="quality", default="0",
|
||||||
|
help="Output quality. 0 - Normal 1 - High 2 - Ultra [Default=0]")
|
||||||
parser.add_option("-c", "--cbz-output", action="store_true", dest="cbzoutput", default=False,
|
parser.add_option("-c", "--cbz-output", action="store_true", dest="cbzoutput", default=False,
|
||||||
help="Outputs a CBZ archive and does not generate EPUB")
|
help="Outputs a CBZ archive and does not generate EPUB")
|
||||||
parser.add_option("--nopanelviewhq", action="store_true", dest="nopanelviewhq", default=False,
|
|
||||||
help="Disable high quality Panel View [Default=False]")
|
|
||||||
parser.add_option("--noprocessing", action="store_false", dest="imgproc", default=True,
|
parser.add_option("--noprocessing", action="store_false", dest="imgproc", default=True,
|
||||||
help="Do not apply image preprocessing (Page splitting and optimizations) [Default=True]")
|
help="Do not apply image preprocessing (Page splitting and optimizations) [Default=True]")
|
||||||
parser.add_option("--forcepng", action="store_true", dest="forcepng", default=False,
|
parser.add_option("--forcepng", action="store_true", dest="forcepng", default=False,
|
||||||
@@ -643,10 +713,21 @@ def main(argv=None):
|
|||||||
help="Do not try to cut page numbering on images [Default=True]")
|
help="Do not try to cut page numbering on images [Default=True]")
|
||||||
parser.add_option("-o", "--output", action="store", dest="output", default=None,
|
parser.add_option("-o", "--output", action="store", dest="output", default=None,
|
||||||
help="Output generated file (EPUB or CBZ) to specified directory or file")
|
help="Output generated file (EPUB or CBZ) to specified directory or file")
|
||||||
|
parser.add_option("--forcecolor", action="store_true", dest="forcecolor", default=False,
|
||||||
|
help="Do not convert images to grayscale [Default=False]")
|
||||||
|
parser.add_option("--customwidth", type="int", dest="customwidth", default=0,
|
||||||
|
help="Replace screen width provided by device profile [Default=0]")
|
||||||
|
parser.add_option("--customheight", type="int", dest="customheight", default=0,
|
||||||
|
help="Replace screen height provided by device profile [Default=0]")
|
||||||
parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False,
|
parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False,
|
||||||
help="Verbose output [Default=False]")
|
help="Verbose output [Default=False]")
|
||||||
options, args = parser.parse_args(argv)
|
options, args = parser.parse_args(argv)
|
||||||
checkOptions()
|
checkOptions()
|
||||||
|
if qtGUI:
|
||||||
|
GUI = qtGUI
|
||||||
|
GUI.emit(QtCore.SIGNAL("progressBarTick"), 1)
|
||||||
|
else:
|
||||||
|
GUI = None
|
||||||
if len(args) != 1:
|
if len(args) != 1:
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
return
|
return
|
||||||
@@ -656,14 +737,18 @@ def main(argv=None):
|
|||||||
splitCount = 0
|
splitCount = 0
|
||||||
if options.imgproc:
|
if options.imgproc:
|
||||||
print "Processing images..."
|
print "Processing images..."
|
||||||
|
if GUI:
|
||||||
|
GUI.emit(QtCore.SIGNAL("progressBarTick"), 'status', 'Processing images')
|
||||||
dirImgProcess(path + "/OEBPS/Images/")
|
dirImgProcess(path + "/OEBPS/Images/")
|
||||||
|
if GUI:
|
||||||
|
GUI.emit(QtCore.SIGNAL("progressBarTick"), 1)
|
||||||
if options.cbzoutput:
|
if options.cbzoutput:
|
||||||
# if CBZ output wanted, compress all images and return filepath
|
# if CBZ output wanted, compress all images and return filepath
|
||||||
print "\nCreating CBZ file..."
|
print "\nCreating CBZ file..."
|
||||||
filepath = getOutputFilename(args[0], options.output, '.cbz')
|
filepath = getOutputFilename(args[0], options.output, '.cbz')
|
||||||
make_archive(path + '_comic', 'zip', path + '/OEBPS/Images')
|
make_archive(path + '_comic', 'zip', path + '/OEBPS/Images')
|
||||||
else:
|
else:
|
||||||
print "\nCreating ePub structure..."
|
print "\nCreating EPUB structure..."
|
||||||
genEpubStruct(path)
|
genEpubStruct(path)
|
||||||
# actually zip the ePub
|
# actually zip the ePub
|
||||||
filepath = getOutputFilename(args[0], options.output, '.epub')
|
filepath = getOutputFilename(args[0], options.output, '.epub')
|
||||||
@@ -701,22 +786,17 @@ def checkOptions():
|
|||||||
else:
|
else:
|
||||||
options.landscapemode = False
|
options.landscapemode = False
|
||||||
# Older Kindle don't support Virtual Panel View. We providing them configuration that will fake that feature.
|
# Older Kindle don't support Virtual Panel View. We providing them configuration that will fake that feature.
|
||||||
if options.profile == 'K3' or options.profile == 'K4NT':
|
# Ultra quality mode require Real Panel View. Landscape mode don't work correcly without Virtual Panel View.
|
||||||
|
if options.profile == 'K3' or options.profile == 'K4NT' or options.quality == 2:
|
||||||
# Real Panel View
|
# Real Panel View
|
||||||
options.panelview = True
|
options.panelview = True
|
||||||
|
options.landscapemode = False
|
||||||
else:
|
else:
|
||||||
# Virtual Panel View
|
# Virtual Panel View
|
||||||
options.panelview = False
|
options.panelview = False
|
||||||
# Older Kindle don't need higher resolution files due lack of Panel View.
|
|
||||||
# Kindle Fire family have very high resolution. Bigger images are not needed.
|
|
||||||
if options.profile == 'K1' or options.profile == 'K2' or options.profile == 'KDX' or options.profile == 'KDXG'\
|
|
||||||
or options.profile == 'KF' or options.profile == 'KFHD' or options.profile == 'KFHD8':
|
|
||||||
options.nopanelviewhq = True
|
|
||||||
# Disabling grayscale conversion for Kindle Fire family.
|
# Disabling grayscale conversion for Kindle Fire family.
|
||||||
# Forcing JPEG output. For now code can't provide color PNG files.
|
if options.profile == 'KF' or options.profile == 'KFHD' or options.profile == 'KFHD8' or options.forcecolor:
|
||||||
if options.profile == 'KF' or options.profile == 'KFHD' or options.profile == 'KFHD8':
|
|
||||||
options.forcecolor = True
|
options.forcecolor = True
|
||||||
options.forcepng = False
|
|
||||||
else:
|
else:
|
||||||
options.forcecolor = False
|
options.forcecolor = False
|
||||||
# Mixing vertical and horizontal pages require real Panel View.
|
# Mixing vertical and horizontal pages require real Panel View.
|
||||||
@@ -724,6 +804,31 @@ def checkOptions():
|
|||||||
if options.rotate:
|
if options.rotate:
|
||||||
options.panelview = True
|
options.panelview = True
|
||||||
options.landscapemode = False
|
options.landscapemode = False
|
||||||
|
# Older Kindle don't need higher resolution files due lack of Panel View.
|
||||||
|
# Kindle Fire family have very high resolution. Bigger images are not needed.
|
||||||
|
if options.profile == 'K1' or options.profile == 'K2' or options.profile == 'KDX' or options.profile == 'KDXG'\
|
||||||
|
or options.profile == 'KF' or options.profile == 'KFHD' or options.profile == 'KFHD8':
|
||||||
|
options.quality = 0
|
||||||
|
if options.profile == 'K1' or options.profile == 'K2' or options.profile == 'KDX' or options.profile == 'KDXG':
|
||||||
|
options.panelview = False
|
||||||
|
# Disable all Kindle features
|
||||||
|
if options.profile == 'OTHER':
|
||||||
|
options.landscapemode = False
|
||||||
|
options.panelview = False
|
||||||
|
options.quality = 0
|
||||||
|
# Override profile data
|
||||||
|
if options.customwidth != 0 or options.customheight != 0:
|
||||||
|
X = image.ProfileData.Profiles[options.profile][1][0]
|
||||||
|
Y = image.ProfileData.Profiles[options.profile][1][1]
|
||||||
|
if options.customwidth != 0:
|
||||||
|
X = options.customwidth
|
||||||
|
if options.customheight != 0:
|
||||||
|
Y = options.customheight
|
||||||
|
newProfile = ("Custom", (X, Y), image.ProfileData.Palette16, image.ProfileData.Profiles[options.profile][3],
|
||||||
|
(int(X*1.5), int(Y*1.5)))
|
||||||
|
image.ProfileData.Profiles["Custom"] = newProfile
|
||||||
|
options.profile = "Custom"
|
||||||
|
options.profileData = image.ProfileData.Profiles[options.profile]
|
||||||
|
|
||||||
|
|
||||||
def getEpubPath():
|
def getEpubPath():
|
||||||
|
|||||||
267
kcc/gui.py
@@ -1,267 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
#
|
|
||||||
# Copyright (c) 2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
|
||||||
#
|
|
||||||
# Permission to use, copy, modify, and/or distribute this software for
|
|
||||||
# any purpose with or without fee is hereby granted, provided that the
|
|
||||||
# above copyright notice and this permission notice appear in all
|
|
||||||
# copies.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
|
||||||
# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
|
||||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
|
||||||
# AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
|
|
||||||
# OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
||||||
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
||||||
# PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
|
|
||||||
__license__ = 'ISC'
|
|
||||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>'
|
|
||||||
__docformat__ = 'restructuredtext en'
|
|
||||||
|
|
||||||
from Tkinter import *
|
|
||||||
import tkFileDialog
|
|
||||||
import tkMessageBox
|
|
||||||
import ttk
|
|
||||||
import comic2ebook
|
|
||||||
import kindlestrip
|
|
||||||
from image import ProfileData
|
|
||||||
from subprocess import call
|
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
import stat
|
|
||||||
import traceback
|
|
||||||
|
|
||||||
|
|
||||||
class MainWindow:
|
|
||||||
|
|
||||||
def clear_files(self):
|
|
||||||
self.filelist = []
|
|
||||||
self.refresh_list()
|
|
||||||
|
|
||||||
def change_gamma(self):
|
|
||||||
if self.aEntry['state'] == DISABLED:
|
|
||||||
self.aEntry['state'] = NORMAL
|
|
||||||
else:
|
|
||||||
self.aEntry['state'] = DISABLED
|
|
||||||
|
|
||||||
def open_files(self):
|
|
||||||
filetypes = [('All files', '.*'), ('Comic files', ('*.cbr', '*.cbz', '*.zip', '*.rar', '*.pdf'))]
|
|
||||||
f = tkFileDialog.askopenfilenames(title="Choose files", filetypes=filetypes)
|
|
||||||
if not isinstance(f, tuple):
|
|
||||||
f = self.master.tk.splitlist(f)
|
|
||||||
self.filelist.extend(f)
|
|
||||||
self.refresh_list()
|
|
||||||
|
|
||||||
def open_folder(self):
|
|
||||||
f = tkFileDialog.askdirectory(title="Choose folder:")
|
|
||||||
self.filelist.extend([f])
|
|
||||||
self.refresh_list()
|
|
||||||
|
|
||||||
def refresh_list(self):
|
|
||||||
self.filelocation.config(state=NORMAL)
|
|
||||||
self.filelocation.delete(0, END)
|
|
||||||
for afile in self.filelist:
|
|
||||||
self.filelocation.insert(END, afile)
|
|
||||||
self.filelocation.config(state=DISABLED)
|
|
||||||
try:
|
|
||||||
if len(self.filelist) > 0:
|
|
||||||
self.submit['state'] = NORMAL
|
|
||||||
else:
|
|
||||||
self.submit['state'] = DISABLED
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def initialize(self):
|
|
||||||
self.filelocation = Listbox(self.master)
|
|
||||||
self.filelocation.grid(row=0, columnspan=4, sticky=W + E + N + S)
|
|
||||||
self.refresh_list()
|
|
||||||
|
|
||||||
self.clear_file = Button(self.master, text="Clear files", command=self.clear_files)
|
|
||||||
self.clear_file.grid(row=4, column=0, sticky=W + E + N + S)
|
|
||||||
self.open_file = Button(self.master, text="Add files", command=self.open_files)
|
|
||||||
self.open_file.grid(row=4, column=1, sticky=W + E + N + S)
|
|
||||||
self.open_folder = Button(self.master, text="Add folder", command=self.open_folder)
|
|
||||||
self.open_folder.grid(row=4, column=2, sticky=W + E + N + S)
|
|
||||||
|
|
||||||
self.profile = StringVar()
|
|
||||||
profiles = sorted(ProfileData.ProfileLabels.iterkeys())
|
|
||||||
self.profile.set(profiles[-1])
|
|
||||||
w = apply(OptionMenu, (self.master, self.profile) + tuple(profiles))
|
|
||||||
w.grid(row=4, column=3, sticky=W + E + N + S)
|
|
||||||
|
|
||||||
self.options = {
|
|
||||||
'Aepub_only': IntVar(None, 0),
|
|
||||||
'Bcbz_only': IntVar(None, 0),
|
|
||||||
'Cmangastyle': IntVar(None, 0),
|
|
||||||
'Dnopanelviewhq': IntVar(None, 0),
|
|
||||||
'Eimage_preprocess': IntVar(None, 0),
|
|
||||||
'Fforcepng': IntVar(None, 0),
|
|
||||||
'Gimage_gamma': DoubleVar(None, 0.0),
|
|
||||||
'Himage_upscale': IntVar(None, 0),
|
|
||||||
'Iimage_stretch': IntVar(None, 0),
|
|
||||||
'Jblack_borders': IntVar(None, 0),
|
|
||||||
'Krotate': IntVar(None, 0),
|
|
||||||
'Lnosplitrotate': IntVar(None, 0),
|
|
||||||
'Mcut_page_numbers': IntVar(None, 0)
|
|
||||||
}
|
|
||||||
self.optionlabels = {
|
|
||||||
'Aepub_only': "Generate EPUB only",
|
|
||||||
'Bcbz_only': "Generate CBZ only (skip EPUB/Mobi generation)",
|
|
||||||
'Cmangastyle': "Manga mode",
|
|
||||||
'Dnopanelviewhq': "Disable high quality Panel View",
|
|
||||||
'Eimage_preprocess': "Disable image optimizations",
|
|
||||||
'Fforcepng': "Create PNG files instead of JPEG",
|
|
||||||
'Gimage_gamma': "Custom gamma correction",
|
|
||||||
'Himage_upscale': "Allow image upscaling",
|
|
||||||
'Iimage_stretch': "Stretch images",
|
|
||||||
'Jblack_borders': "Use black borders (instead of white ones)",
|
|
||||||
'Krotate': "Rotate images (instead of splitting them)",
|
|
||||||
'Lnosplitrotate': "Disable both splitting and rotation",
|
|
||||||
'Mcut_page_numbers': "Disable page numbers cutting"
|
|
||||||
}
|
|
||||||
self.optionsButtons = {}
|
|
||||||
for key in sorted(self.options):
|
|
||||||
if isinstance(self.options[key], IntVar) or isinstance(self.options[key], BooleanVar):
|
|
||||||
self.optionsButtons[key] = Checkbutton(self.master, text=self.optionlabels[key],
|
|
||||||
variable=self.options[key])
|
|
||||||
self.optionsButtons[key].grid(columnspan=4, sticky=W + N + S)
|
|
||||||
elif isinstance(self.options[key], DoubleVar):
|
|
||||||
self.optionsButtons[key] = Checkbutton(self.master, text=self.optionlabels[key],
|
|
||||||
command=self.change_gamma)
|
|
||||||
self.optionsButtons[key].grid(columnspan=4, sticky=W + N + S)
|
|
||||||
self.aEntry = Entry(self.master, textvariable=self.options[key])
|
|
||||||
self.aEntry['state'] = DISABLED
|
|
||||||
self.aEntry.grid(column=3, row=(self.master.grid_size()[1] - 1), sticky=W + N + S)
|
|
||||||
|
|
||||||
self.submit = Button(self.master, text="CONVERT", command=self.start_conversion, fg="red", state=DISABLED)
|
|
||||||
self.submit.grid(columnspan=4, sticky=W + E + N + S)
|
|
||||||
aLabel = Label(self.master, text="File progress:", anchor=W, justify=LEFT)
|
|
||||||
aLabel.grid(column=0, sticky=E)
|
|
||||||
self.progress_file = ttk.Progressbar(orient=HORIZONTAL, length=200, mode='determinate', maximum=4)
|
|
||||||
self.progress_file.grid(column=1, columnspan=3, row=(self.master.grid_size()[1] - 1), sticky=W + E + N + S)
|
|
||||||
aLabel = Label(self.master, text="Overall progress:", anchor=W, justify=LEFT)
|
|
||||||
aLabel.grid(column=0, sticky=E)
|
|
||||||
self.progress_overall = ttk.Progressbar(orient=HORIZONTAL, length=200, mode='determinate')
|
|
||||||
self.progress_overall.grid(column=1, columnspan=3, row=(self.master.grid_size()[1] - 1), sticky=W + E + N + S)
|
|
||||||
|
|
||||||
retcode = call("kindlegen", shell=True)
|
|
||||||
if retcode == 1:
|
|
||||||
self.optionsButtons['Aepub_only'].select()
|
|
||||||
self.optionsButtons['Aepub_only']['state'] = DISABLED
|
|
||||||
|
|
||||||
def start_conversion(self):
|
|
||||||
self.submit['state'] = DISABLED
|
|
||||||
self.master.update()
|
|
||||||
self.convert()
|
|
||||||
self.submit['state'] = NORMAL
|
|
||||||
self.master.update()
|
|
||||||
|
|
||||||
def convert(self):
|
|
||||||
if len(self.filelist) < 1:
|
|
||||||
tkMessageBox.showwarning('No files selected!', "Please choose files to convert.")
|
|
||||||
return
|
|
||||||
profilekey = ProfileData.ProfileLabels[self.profile.get()]
|
|
||||||
argv = ["-p", profilekey]
|
|
||||||
if self.options['Bcbz_only'].get() == 1:
|
|
||||||
argv.append("-c")
|
|
||||||
if self.options['Cmangastyle'].get() == 1:
|
|
||||||
argv.append("-m")
|
|
||||||
if self.options['Dnopanelviewhq'].get() == 1:
|
|
||||||
argv.append("--nopanelviewhq")
|
|
||||||
if self.options['Eimage_preprocess'].get() == 1:
|
|
||||||
argv.append("--noprocessing")
|
|
||||||
if self.options['Fforcepng'].get() == 1:
|
|
||||||
argv.append("--forcepng")
|
|
||||||
if self.options['Gimage_gamma'].get() != 0.0:
|
|
||||||
argv.append("--gamma")
|
|
||||||
argv.append(self.options['Gimage_gamma'].get())
|
|
||||||
if self.options['Himage_upscale'].get() == 1:
|
|
||||||
argv.append("--upscale")
|
|
||||||
if self.options['Iimage_stretch'].get() == 1:
|
|
||||||
argv.append("--stretch")
|
|
||||||
if self.options['Jblack_borders'].get() == 1:
|
|
||||||
argv.append("--blackborders")
|
|
||||||
if self.options['Krotate'].get() == 1:
|
|
||||||
argv.append("--rotate")
|
|
||||||
if self.options['Lnosplitrotate'].get() == 1:
|
|
||||||
argv.append("--nosplitrotate")
|
|
||||||
if self.options['Mcut_page_numbers'].get() == 1:
|
|
||||||
argv.append("--nocutpagenumbers")
|
|
||||||
errors = False
|
|
||||||
left_files = len(self.filelist)
|
|
||||||
filenum = 0
|
|
||||||
self.progress_overall['value'] = 0
|
|
||||||
self.progress_overall['maximum'] = left_files
|
|
||||||
for entry in self.filelist:
|
|
||||||
self.progress_overall['value'] = filenum
|
|
||||||
self.progress_file['value'] = 1
|
|
||||||
self.master.update()
|
|
||||||
filenum += 1
|
|
||||||
subargv = list(argv)
|
|
||||||
try:
|
|
||||||
subargv.append(entry)
|
|
||||||
epub_path = comic2ebook.main(subargv)
|
|
||||||
self.progress_file['value'] = 2
|
|
||||||
self.master.update()
|
|
||||||
except Exception as err:
|
|
||||||
type_, value_, traceback_ = sys.exc_info()
|
|
||||||
tkMessageBox.showerror('KCC Error', "Error on file %s:\n%s\nTraceback:\n%s" %
|
|
||||||
(subargv[-1], str(err), traceback.format_tb(traceback_)))
|
|
||||||
errors = True
|
|
||||||
continue
|
|
||||||
if self.options['Aepub_only'].get() == 0 and self.options['Bcbz_only'].get() == 0:
|
|
||||||
try:
|
|
||||||
if os.path.getsize(epub_path) > 314572800:
|
|
||||||
# do not call kindlegen if source is bigger than 300MB
|
|
||||||
tkMessageBox.showwarning('KindleGen Warning',
|
|
||||||
"ePub file %s is bigger than 300MB, not suitable for kindlegen" %
|
|
||||||
epub_path)
|
|
||||||
continue
|
|
||||||
retcode = call("kindlegen \"" + epub_path + "\"", shell=True)
|
|
||||||
if retcode < 0:
|
|
||||||
print >>sys.stderr, "Child was terminated by signal", -retcode
|
|
||||||
else:
|
|
||||||
print >>sys.stderr, "Child returned", retcode
|
|
||||||
self.progress_file['value'] = 3
|
|
||||||
self.master.update()
|
|
||||||
except OSError as e:
|
|
||||||
tkMessageBox.showerror('KindleGen Error', "Error on file %s:\n%s" % (epub_path, e))
|
|
||||||
errors = True
|
|
||||||
continue
|
|
||||||
mobifile = epub_path.replace('.epub', '.mobi')
|
|
||||||
try:
|
|
||||||
shutil.move(mobifile, mobifile + '_tostrip')
|
|
||||||
kindlestrip.main((mobifile + '_tostrip', mobifile))
|
|
||||||
os.remove(mobifile + '_tostrip')
|
|
||||||
self.progress_file['value'] = 4
|
|
||||||
self.master.update()
|
|
||||||
except Exception, err:
|
|
||||||
tkMessageBox.showerror('KindleStrip Error', "Error on file %s:\n%s" % (mobifile, str(err)))
|
|
||||||
errors = True
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
self.progress_file['value'] = 4
|
|
||||||
self.master.update()
|
|
||||||
if errors:
|
|
||||||
tkMessageBox.showwarning("Done", "Conversion completed with errors.")
|
|
||||||
else:
|
|
||||||
tkMessageBox.showinfo("Done", "Conversion successful!")
|
|
||||||
# reset progressbars
|
|
||||||
self.progress_overall['value'] = 0
|
|
||||||
self.progress_file['value'] = 0
|
|
||||||
self.master.update()
|
|
||||||
|
|
||||||
def remove_readonly(self, fn, path):
|
|
||||||
if fn is os.rmdir:
|
|
||||||
os.chmod(path, stat.S_IWRITE)
|
|
||||||
os.rmdir(path)
|
|
||||||
elif fn is os.remove:
|
|
||||||
os.chmod(path, stat.S_IWRITE)
|
|
||||||
os.remove(path)
|
|
||||||
|
|
||||||
def __init__(self, master):
|
|
||||||
self.filelist = []
|
|
||||||
self.master = master
|
|
||||||
self.initialize()
|
|
||||||
127
kcc/image.py
@@ -16,19 +16,16 @@
|
|||||||
# 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'
|
__license__ = 'ISC'
|
||||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>'
|
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from PIL import Image, ImageOps, ImageStat, ImageChops
|
try:
|
||||||
|
# noinspection PyUnresolvedReferences
|
||||||
|
from PIL import Image, ImageOps, ImageStat, ImageChops
|
||||||
class ImageFlags:
|
except ImportError:
|
||||||
Orient = 1 << 0
|
print "ERROR: Pillow is not installed!"
|
||||||
Resize = 1 << 1
|
exit(1)
|
||||||
Frame = 1 << 2
|
|
||||||
Quantize = 1 << 3
|
|
||||||
Stretch = 1 << 4
|
|
||||||
|
|
||||||
|
|
||||||
class ProfileData:
|
class ProfileData:
|
||||||
@@ -87,7 +84,8 @@ class ProfileData:
|
|||||||
'KDXG': ("Kindle DXG", (824, 1200), Palette16, 1.8, (1236, 1800)),
|
'KDXG': ("Kindle DXG", (824, 1200), Palette16, 1.8, (1236, 1800)),
|
||||||
'KF': ("Kindle Fire", (600, 1024), Palette16, 1.0, (900, 1536)),
|
'KF': ("Kindle Fire", (600, 1024), Palette16, 1.0, (900, 1536)),
|
||||||
'KFHD': ("Kindle Fire HD 7\"", (800, 1280), Palette16, 1.0, (1200, 1920)),
|
'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))
|
'KFHD8': ("Kindle Fire HD 8.9\"", (1200, 1920), Palette16, 1.0, (1800, 2880)),
|
||||||
|
'OTHER': ("Other", (0, 0), Palette16, 1.8, (0, 0)),
|
||||||
}
|
}
|
||||||
|
|
||||||
ProfileLabels = {
|
ProfileLabels = {
|
||||||
@@ -101,39 +99,48 @@ class ProfileData:
|
|||||||
"Kindle DXG": 'KDXG',
|
"Kindle DXG": 'KDXG',
|
||||||
"Kindle Fire": 'KF',
|
"Kindle Fire": 'KF',
|
||||||
"Kindle Fire HD 7\"": 'KFHD',
|
"Kindle Fire HD 7\"": 'KFHD',
|
||||||
"Kindle Fire HD 8.9\"": 'KFHD8'
|
"Kindle Fire HD 8.9\"": 'KFHD8',
|
||||||
|
"Other": 'OTHER'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ComicPage:
|
class ComicPage:
|
||||||
def __init__(self, source, device):
|
def __init__(self, source, device):
|
||||||
try:
|
try:
|
||||||
self.profile = device
|
self.profile_label, self.size, self.palette, self.gamma, self.panelviewsize = device
|
||||||
self.profile_label, self.size, self.palette, self.gamma, self.panelviewsize = ProfileData.Profiles[device]
|
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise RuntimeError('Unexpected output device %s' % device)
|
raise RuntimeError('Unexpected output device %s' % device)
|
||||||
|
# Detect corrupted files - Phase 2
|
||||||
try:
|
try:
|
||||||
self.origFileName = source
|
self.origFileName = source
|
||||||
self.image = Image.open(source)
|
self.image = Image.open(source)
|
||||||
except IOError:
|
except IOError:
|
||||||
raise RuntimeError('Cannot read image file %s' % source)
|
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 = self.image.convert('RGB')
|
self.image = self.image.convert('RGB')
|
||||||
|
|
||||||
def saveToDir(self, targetdir, forcepng, color, sufix=None):
|
def saveToDir(self, targetdir, forcepng, color, wipe, suffix=None):
|
||||||
filename = os.path.basename(self.origFileName)
|
filename = os.path.basename(self.origFileName)
|
||||||
try:
|
try:
|
||||||
if not color:
|
if not color:
|
||||||
self.image = self.image.convert('L') # convert to grayscale
|
self.image = self.image.convert('L') # convert to grayscale
|
||||||
# Sufix is used to recognise which files need horizontal Panel View.
|
if suffix == "R":
|
||||||
if sufix == "R":
|
suffix = "_kccrotated"
|
||||||
sufix = "_rotated"
|
|
||||||
else:
|
else:
|
||||||
sufix = ""
|
suffix = ""
|
||||||
os.remove(os.path.join(targetdir, filename))
|
if wipe:
|
||||||
|
os.remove(os.path.join(targetdir, filename))
|
||||||
|
else:
|
||||||
|
suffix += "_kcchq"
|
||||||
if forcepng:
|
if forcepng:
|
||||||
self.image.save(os.path.join(targetdir, os.path.splitext(filename)[0] + sufix + ".png"), "PNG")
|
self.image.save(os.path.join(targetdir, os.path.splitext(filename)[0] + suffix + ".png"), "PNG")
|
||||||
else:
|
else:
|
||||||
self.image.save(os.path.join(targetdir, os.path.splitext(filename)[0] + sufix + ".jpg"), "JPEG")
|
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))
|
||||||
|
|
||||||
@@ -156,16 +163,17 @@ class ComicPage:
|
|||||||
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 resizeImage(self, upscale=False, stretch=False, black_borders=False, isSplit=False, toRight=False,
|
||||||
landscapeMode=False, noPanelViewHQ=False):
|
landscapeMode=False, qualityMode=0):
|
||||||
method = Image.ANTIALIAS
|
method = Image.ANTIALIAS
|
||||||
if black_borders:
|
if black_borders:
|
||||||
fill = 'black'
|
fill = 'black'
|
||||||
else:
|
else:
|
||||||
fill = 'white'
|
fill = 'white'
|
||||||
if noPanelViewHQ:
|
if qualityMode == 0:
|
||||||
size = (self.size[0], self.size[1])
|
size = (self.size[0], self.size[1])
|
||||||
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 isSplit and landscapeMode:
|
if isSplit and landscapeMode:
|
||||||
upscale = True
|
upscale = True
|
||||||
if self.image.size[0] <= self.size[0] and self.image.size[1] <= self.size[1]:
|
if self.image.size[0] <= self.size[0] and self.image.size[1] <= self.size[1]:
|
||||||
@@ -218,8 +226,8 @@ class ComicPage:
|
|||||||
leftbox = (0, 0, width, height / 2)
|
leftbox = (0, 0, width, height / 2)
|
||||||
rightbox = (0, height / 2, width, height)
|
rightbox = (0, height / 2, width, height)
|
||||||
filename = os.path.splitext(os.path.basename(self.origFileName))
|
filename = os.path.splitext(os.path.basename(self.origFileName))
|
||||||
fileone = targetdir + '/' + filename[0] + '-kcca' + filename[1]
|
fileone = targetdir + '/' + filename[0] + '_kcca' + filename[1]
|
||||||
filetwo = targetdir + '/' + filename[0] + '-kccb' + filename[1]
|
filetwo = targetdir + '/' + filename[0] + '_kccb' + filename[1]
|
||||||
try:
|
try:
|
||||||
if righttoleft:
|
if righttoleft:
|
||||||
pageone = self.image.crop(rightbox)
|
pageone = self.image.crop(rightbox)
|
||||||
@@ -260,7 +268,8 @@ class ComicPage:
|
|||||||
diff -= delta
|
diff -= delta
|
||||||
pageNumberCut2 = diff
|
pageNumberCut2 = diff
|
||||||
diff += delta
|
diff += delta
|
||||||
oldStat = ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg - pageNumberCut2))).var[0]
|
oldStat = ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg,
|
||||||
|
heightImg - pageNumberCut2))).var[0]
|
||||||
while ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg - pageNumberCut2))).var[0]\
|
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
|
||||||
@@ -268,8 +277,8 @@ class ComicPage:
|
|||||||
pageNumberCut3 = diff
|
pageNumberCut3 = diff
|
||||||
delta = 5
|
delta = 5
|
||||||
diff = delta
|
diff = delta
|
||||||
while ImageStat.Stat(self.image.crop((0, heightImg - pageNumberCut2, diff, heightImg))).var[0] < fixedThreshold\
|
while ImageStat.Stat(self.image.crop((0, heightImg - pageNumberCut2, diff, heightImg))).var[0]\
|
||||||
and diff < widthImg:
|
< fixedThreshold and diff < widthImg:
|
||||||
diff += delta
|
diff += delta
|
||||||
diff -= delta
|
diff -= delta
|
||||||
pageNumberX1 = diff
|
pageNumberX1 = diff
|
||||||
@@ -328,62 +337,4 @@ class ComicPage:
|
|||||||
# print "Right crop: %s"%diff
|
# 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])
|
# print "New size: %sx%s"%(self.image.size[0],self.image.size[1])
|
||||||
return self.image
|
return self.image
|
||||||
|
|
||||||
# def addProgressbar(self, file_number, files_totalnumber, size, howoften):
|
|
||||||
# if file_number // howoften != float(file_number) / howoften:
|
|
||||||
# return self.image
|
|
||||||
# white = (255, 255, 255)
|
|
||||||
# black = (0, 0, 0)
|
|
||||||
# widthDev, heightDev = size
|
|
||||||
# widthImg, heightImg = self.image.size
|
|
||||||
# pastePt = (
|
|
||||||
# max(0, (widthDev - widthImg) / 2),
|
|
||||||
# max(0, (heightDev - heightImg) / 2)
|
|
||||||
# )
|
|
||||||
# imageBg = Image.new('RGB', size, white)
|
|
||||||
# imageBg.paste(self.image, pastePt)
|
|
||||||
# self.image = imageBg
|
|
||||||
# widthImg, heightImg = self.image.size
|
|
||||||
# draw = ImageDraw.Draw(self.image)
|
|
||||||
# #Black rectangle
|
|
||||||
# draw.rectangle([(0, heightImg - 3), (widthImg, heightImg)], outline=black, fill=black)
|
|
||||||
# #White rectangle
|
|
||||||
# draw.rectangle([(widthImg * file_number / files_totalnumber, heightImg - 3), (widthImg - 1, heightImg)],
|
|
||||||
# outline=black, fill=white)
|
|
||||||
# #Making notches
|
|
||||||
# for i in range(1, 10):
|
|
||||||
# if i <= (10 * file_number / files_totalnumber):
|
|
||||||
# notch_colour = white # White
|
|
||||||
# else:
|
|
||||||
# notch_colour = black # Black
|
|
||||||
# draw.line([(widthImg * float(i) / 10, heightImg - 3), (widthImg * float(i) / 10, heightImg)],
|
|
||||||
# fill=notch_colour)
|
|
||||||
# #The 50%
|
|
||||||
# if i == 5:
|
|
||||||
# draw.rectangle([(widthImg / 2 - 1, heightImg - 5), (widthImg / 2 + 1, heightImg)],
|
|
||||||
# outline=black, fill=notch_colour)
|
|
||||||
# return self.image
|
|
||||||
#
|
|
||||||
# def frameImage(self):
|
|
||||||
# foreground = tuple(self.palette[:3])
|
|
||||||
# background = tuple(self.palette[-3:])
|
|
||||||
# widthDev, heightDev = self.size
|
|
||||||
# widthImg, heightImg = self.image.size
|
|
||||||
# pastePt = (
|
|
||||||
# max(0, (widthDev - widthImg) / 2),
|
|
||||||
# max(0, (heightDev - heightImg) / 2)
|
|
||||||
# )
|
|
||||||
# corner1 = (
|
|
||||||
# pastePt[0] - 1,
|
|
||||||
# pastePt[1] - 1
|
|
||||||
# )
|
|
||||||
# corner2 = (
|
|
||||||
# pastePt[0] + widthImg + 1,
|
|
||||||
# pastePt[1] + heightImg + 1
|
|
||||||
# )
|
|
||||||
# imageBg = Image.new(self.image.mode, self.size, background)
|
|
||||||
# imageBg.paste(self.image, pastePt)
|
|
||||||
# draw = ImageDraw.Draw(imageBg)
|
|
||||||
# draw.rectangle([corner1, corner2], outline=foreground)
|
|
||||||
# self.image = imageBg
|
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
__license__ = 'ISC'
|
__license__ = 'ISC'
|
||||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>'
|
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|||||||
2
other/qt.conf
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[Paths]
|
||||||
|
Plugins = DumbHackThatFixPY2APP
|
||||||
66
setup.py
@@ -1,7 +1,5 @@
|
|||||||
"""
|
"""
|
||||||
py2app/cx_Freeze build script for KCC.
|
cx_Freeze build script for KCC.
|
||||||
|
|
||||||
Will automatically ensure that all build prerequisites are available via ez_setup
|
|
||||||
|
|
||||||
Usage (Mac OS X):
|
Usage (Mac OS X):
|
||||||
python setup.py py2app
|
python setup.py py2app
|
||||||
@@ -9,20 +7,13 @@ Usage (Mac OS X):
|
|||||||
Usage (Windows):
|
Usage (Windows):
|
||||||
python setup.py build
|
python setup.py build
|
||||||
"""
|
"""
|
||||||
from ez_setup import use_setuptools
|
from sys import platform
|
||||||
use_setuptools()
|
|
||||||
|
|
||||||
import sys
|
|
||||||
|
|
||||||
NAME = "KindleComicConverter"
|
NAME = "KindleComicConverter"
|
||||||
VERSION = "2.10"
|
VERSION = "3.0"
|
||||||
MAIN = "kcc.py"
|
MAIN = "kcc.py"
|
||||||
|
|
||||||
includefiles = ['README.md', 'MANIFEST.in', 'LICENSE.txt', 'comic2ebook.ico', 'comic2ebook.icns']
|
if platform == "darwin":
|
||||||
includes = []
|
|
||||||
excludes = []
|
|
||||||
|
|
||||||
if sys.platform == "darwin":
|
|
||||||
from setuptools import setup
|
from setuptools import setup
|
||||||
extra_options = dict(
|
extra_options = dict(
|
||||||
setup_requires=['py2app'],
|
setup_requires=['py2app'],
|
||||||
@@ -30,58 +21,55 @@ if sys.platform == "darwin":
|
|||||||
options=dict(
|
options=dict(
|
||||||
py2app=dict(
|
py2app=dict(
|
||||||
argv_emulation=True,
|
argv_emulation=True,
|
||||||
iconfile='comic2ebook.icns',
|
iconfile='icons/comic2ebook.icns',
|
||||||
|
includes=['PIL', 'sip', 'PyQt4', 'PyQt4.QtCore', 'PyQt4.QtGui'],
|
||||||
|
resources=['other/qt.conf', 'LICENSE.txt'],
|
||||||
plist=dict(
|
plist=dict(
|
||||||
CFBundleName=NAME,
|
CFBundleName=NAME,
|
||||||
CFBundleShortVersionString=VERSION,
|
CFBundleShortVersionString=VERSION,
|
||||||
CFBundleGetInfoString=NAME + " " + VERSION + ", written 2012-2013 by Ciro Mattia Gonano",
|
CFBundleGetInfoString=NAME + " " + VERSION +
|
||||||
|
", written 2012-2013 by Ciro Mattia Gonano and Pawel Jastrzebski",
|
||||||
CFBundleExecutable=NAME,
|
CFBundleExecutable=NAME,
|
||||||
CFBundleIdentifier='com.github.ciromattia.kcc',
|
CFBundleIdentifier='com.github.ciromattia.kcc',
|
||||||
CFBundleSignature='dplt'
|
CFBundleSignature='dplt',
|
||||||
|
NSHumanReadableCopyright='ISC License (ISCL)'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
elif sys.platform == 'win32':
|
elif platform == "win32":
|
||||||
from cx_Freeze import setup, Executable
|
from cx_Freeze import setup, Executable
|
||||||
base = "Win32GUI"
|
base = "Win32GUI"
|
||||||
extra_options = dict(
|
extra_options = dict(
|
||||||
options={"build_exe": {"include_files": includefiles, 'excludes': excludes, 'compressed': True}},
|
options={"build_exe": {"include_files": ['LICENSE.txt'], "compressed": True}},
|
||||||
executables=[Executable(MAIN,
|
executables=[Executable(MAIN,
|
||||||
base=base,
|
base=base,
|
||||||
icon="comic2ebook.ico",
|
targetName="KCC.exe",
|
||||||
|
icon="icons/comic2ebook.ico",
|
||||||
copyDependentFiles=True,
|
copyDependentFiles=True,
|
||||||
appendScriptToExe=True,
|
appendScriptToExe=True,
|
||||||
appendScriptToLibrary=False,
|
appendScriptToLibrary=False,
|
||||||
compress=True)])
|
compress=True)])
|
||||||
else:
|
else:
|
||||||
|
from cx_Freeze import setup, Executable
|
||||||
extra_options = dict(
|
extra_options = dict(
|
||||||
scripts=[MAIN],
|
options={"build_exe": {"include_files": ['LICENSE.txt'], "compressed": True}},
|
||||||
)
|
executables=[Executable(MAIN,
|
||||||
|
icon="icons/comic2ebook.png",
|
||||||
|
copyDependentFiles=True,
|
||||||
|
appendScriptToExe=True,
|
||||||
|
appendScriptToLibrary=False,
|
||||||
|
compress=True)])
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name=NAME,
|
name=NAME,
|
||||||
version=VERSION,
|
version=VERSION,
|
||||||
author="Ciro Mattia Gonano",
|
author="Ciro Mattia Gonano, Pawel Jastrzebski",
|
||||||
author_email="ciromattia@gmail.com",
|
author_email="ciromattia@gmail.com, pawelj@vulturis.eu",
|
||||||
description="A tool to convert comics (CBR/CBZ/PDFs/image folders) to Mobipocket.",
|
description="A tool to convert comics (CBR/CBZ/PDFs/image folders) to MOBI.",
|
||||||
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",
|
||||||
classifiers=[
|
packages=['kcc'], requires=['Pillow'],
|
||||||
'Development Status :: 4 - Beta'
|
|
||||||
'License :: OSI Approved :: ISC License (ISCL)',
|
|
||||||
'Environment :: Console',
|
|
||||||
'Environment :: MacOS X',
|
|
||||||
'Environment :: Win32 (MS Windows)',
|
|
||||||
'Environment :: X11 Applications',
|
|
||||||
'Intended Audience :: End Users/Desktop',
|
|
||||||
'Operating System :: OS Independent',
|
|
||||||
'Programming Language :: Python',
|
|
||||||
'Programming Language :: Python :: 2.7',
|
|
||||||
'Topic :: Multimedia :: Graphics :: Graphics Conversion',
|
|
||||||
'Topic :: Utilities'
|
|
||||||
],
|
|
||||||
packages=['kcc'],
|
|
||||||
**extra_options
|
**extra_options
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
"""
|
|
||||||
cx_freeze build script for Windows KCC No-GUI release.
|
|
||||||
|
|
||||||
Usage (Windows):
|
|
||||||
python setup_console.py build
|
|
||||||
"""
|
|
||||||
import sys
|
|
||||||
from cx_Freeze import setup, Executable
|
|
||||||
sys.path.insert(0, 'kcc')
|
|
||||||
|
|
||||||
setup(
|
|
||||||
name = "KindleComicConverter",
|
|
||||||
version = "2.10",
|
|
||||||
author = "Ciro Mattia Gonano",
|
|
||||||
author_email = "ciromattia@gmail.com",
|
|
||||||
description = "A tool to convert comics (CBR/CBZ/PDFs/image folders) to MOBI.",
|
|
||||||
license= "ISC License (ISCL)",
|
|
||||||
keywords= "kindle comic mobipocket mobi cbz cbr manga",
|
|
||||||
url = "http://github.com/ciromattia/kcc",
|
|
||||||
executables = [Executable("kcc/comic2ebook.py", compress=True, copyDependentFiles=True, appendScriptToExe=True, appendScriptToLibrary=False),
|
|
||||||
Executable("kcc/kindlestrip.py", compress=True, copyDependentFiles=True, appendScriptToExe=True, appendScriptToLibrary=False)]
|
|
||||||
)
|
|
||||||