mirror of
https://github.com/ciromattia/kcc
synced 2026-04-17 14:38:47 +00:00
Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7bd9c766cc | ||
|
|
c6b1417d9c | ||
|
|
98bf28a713 | ||
|
|
f2d6d5b458 | ||
|
|
5de492ffb6 | ||
|
|
5c2c6ed825 | ||
|
|
c2730ab01c | ||
|
|
bfba66d47d | ||
|
|
b5bc2f8e00 | ||
|
|
917eaef548 | ||
|
|
3187ebb054 | ||
|
|
b9276e9ede | ||
|
|
147d815057 | ||
|
|
180123fee2 | ||
|
|
2768e622f2 | ||
|
|
b629b45d46 | ||
|
|
f66c83425c | ||
|
|
68b4b7114d | ||
|
|
36f8c82eaf | ||
|
|
bd665c3261 | ||
|
|
94586fa590 | ||
|
|
89806dfcfc | ||
|
|
c9eb73ab90 | ||
|
|
2edcc0369a | ||
|
|
bc0a52b848 | ||
|
|
5ae72bf06d | ||
|
|
24c32643c1 | ||
|
|
40b988f964 | ||
|
|
ac794eff85 | ||
|
|
eaa387a9d6 | ||
|
|
d0f5d6dac4 |
27
KCC-Linux.ui
27
KCC-Linux.ui
@@ -71,7 +71,7 @@
|
|||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p style='white-space:pre'>Disable image optimizations.<br/>Input images must be already resized.</p></body></html></string>
|
<string><html><head/><body><p style='white-space:pre'>Disable image optimizations.<br/><span style=" font-weight:600;">Input images must be already resized.</span></p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>No optimisation</string>
|
<string>No optimisation</string>
|
||||||
@@ -110,7 +110,7 @@
|
|||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p>Enable auto-splitting of webtoons like <span style=" font-style:italic;">Tower of God</span> or <span style=" font-style:italic;">Noblesse</span>.<br/>This mode was created for pages with a low width, high height and vertical panel flow.</p></body></html></string>
|
<string><html><head/><body><p style='white-space:pre'>Enable special parsing mode for WebToons.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Webtoon mode</string>
|
<string>Webtoon mode</string>
|
||||||
@@ -167,7 +167,7 @@
|
|||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p style='white-space:pre'>Disable splitting and rotation.</p></body></html></string>
|
<string><html><head/><body><p style='white-space:pre'>Disable page splitting and rotation.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>No split/rotate</string>
|
<string>No split/rotate</string>
|
||||||
@@ -241,7 +241,7 @@
|
|||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p style='white-space:pre'>Shift+Click to select the output directory.</p></body></html></string>
|
<string><html><head/><body><p style='white-space:pre'>Shift+Click to select the output directory.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Convert</string>
|
<string>Convert</string>
|
||||||
@@ -269,6 +269,9 @@
|
|||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p style='white-space:pre'>Add directory containing JPG, PNG or GIF files to queue.<br/><span style=" font-weight:600;">CBR, CBZ and CB7 files inside will not be processed!</span></p></body></html></string>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Add directory</string>
|
<string>Add directory</string>
|
||||||
</property>
|
</property>
|
||||||
@@ -295,6 +298,9 @@
|
|||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p style='white-space:pre'>Add CBR, CBZ, CB7 or PDF file to queue.</p></body></html></string>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Add file</string>
|
<string>Add file</string>
|
||||||
</property>
|
</property>
|
||||||
@@ -386,7 +392,7 @@
|
|||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p><span style=" font-weight:600; text-decoration: underline;">Unchecked - Normal quality mode</span><br/>Maximal quality of images but very poor magnification quality.<br/>Use it only when zoom is not needed or output files needs to be small.</p><p><span style=" font-weight:600; text-decoration: underline;">Indeterminate - High quality mode</span><br/>In most cases high quality of images and magnification.<br/>Overall quality highly depends on the resolution of source files.<br/>On Kindle models older than Paperwhite non-zoomed images might be a little blurred.<br/><br/><span style=" font-weight:600; text-decoration: underline;">Checked - Ultra quality mode</span><br/>Highest possible quality. Output files will be big.</p></body></html></string>
|
<string><html><head/><body><p style='white-space:pre'>Quality of Panel View/zoom. Highly impact size of output file.<br/><span style=" font-weight:600;">This option control only quality of magnification!</span></p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>High/Ultra quality</string>
|
<string>High/Ultra quality</string>
|
||||||
@@ -445,6 +451,9 @@
|
|||||||
<property name="styleSheet">
|
<property name="styleSheet">
|
||||||
<string notr="true">QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}</string>
|
<string notr="true">QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="verticalScrollBarPolicy">
|
||||||
|
<enum>Qt::ScrollBarAlwaysOn</enum>
|
||||||
|
</property>
|
||||||
<property name="showDropIndicator" stdset="0">
|
<property name="showDropIndicator" stdset="0">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
@@ -661,7 +670,7 @@
|
|||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p>Resolution of target device.</p></body></html></string>
|
<string><html><head/><body><p style='white-space:pre'>Resolution of target device.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Custom width: </string>
|
<string>Custom width: </string>
|
||||||
@@ -694,7 +703,7 @@
|
|||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p>Resolution of target device.</p></body></html></string>
|
<string><html><head/><body><p style='white-space:pre'>Resolution of target device.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="inputMask">
|
<property name="inputMask">
|
||||||
<string>0000</string>
|
<string>0000</string>
|
||||||
@@ -712,7 +721,7 @@
|
|||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p>Resolution of target device.</p></body></html></string>
|
<string><html><head/><body><p style='white-space:pre'>Resolution of target device.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Custom height: </string>
|
<string>Custom height: </string>
|
||||||
@@ -745,7 +754,7 @@
|
|||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p>Resolution of target device.</p></body></html></string>
|
<string><html><head/><body><p style='white-space:pre'>Resolution of target device.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="inputMask">
|
<property name="inputMask">
|
||||||
<string>0000</string>
|
<string>0000</string>
|
||||||
|
|||||||
21
KCC-OSX.ui
21
KCC-OSX.ui
@@ -69,7 +69,7 @@
|
|||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p style='white-space:pre'>Disable image optimizations.<br/>Input images must be already resized.</p></body></html></string>
|
<string><html><head/><body><p style='white-space:pre'>Disable image optimizations.<br/><span style=" font-weight:600;">Input images must be already resized.</span></p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>No optimisation</string>
|
<string>No optimisation</string>
|
||||||
@@ -110,7 +110,7 @@
|
|||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p>Enable auto-splitting of webtoons like <span style=" font-style:italic;">Tower of God </span>or <span style=" font-style:italic;">Noblesse</span>.<br/>This mode was created for pages with a low width, high height and vertical panel flow.</p><p><br/></p></body></html></string>
|
<string><html><head/><body><p style='white-space:pre'>Enable special parsing mode for WebToons.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Webtoon mode</string>
|
<string>Webtoon mode</string>
|
||||||
@@ -170,7 +170,7 @@
|
|||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p style='white-space:pre'>Disable splitting and rotation.</p></body></html></string>
|
<string><html><head/><body><p style='white-space:pre'>Disable page splitting and rotation.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>No split/rotate</string>
|
<string>No split/rotate</string>
|
||||||
@@ -220,7 +220,7 @@
|
|||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p style='white-space:pre'>Output format.</p></body></html></string>
|
<string><html><head/><body><p style='white-space:pre'>Output format.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QPushButton" name="ConvertButton">
|
<widget class="QPushButton" name="ConvertButton">
|
||||||
@@ -244,7 +244,7 @@
|
|||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p style='white-space:pre'>Shift+Click to select the output directory.</p></body></html></string>
|
<string><html><head/><body><p style='white-space:pre'>Shift+Click to select the output directory.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Convert</string>
|
<string>Convert</string>
|
||||||
@@ -272,6 +272,9 @@
|
|||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p style='white-space:pre'>Add directory containing JPG, PNG or GIF files to queue.<br/><span style=" font-weight:600;">CBR, CBZ and CB7 files inside will not be processed!</span></p></body></html></string>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Add directory</string>
|
<string>Add directory</string>
|
||||||
</property>
|
</property>
|
||||||
@@ -298,6 +301,9 @@
|
|||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p style='white-space:pre'>Add CBR, CBZ, CB7 or PDF file to queue.</p></body></html></string>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Add file</string>
|
<string>Add file</string>
|
||||||
</property>
|
</property>
|
||||||
@@ -391,7 +397,7 @@
|
|||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p><span style=" font-weight:600; text-decoration: underline;">Unchecked - Normal quality mode</span><br/>Maximal quality of images but very poor magnification quality.<br/>Use it only when zoom is not needed or output files needs to be small.</p><p><span style=" font-weight:600; text-decoration: underline;">Indeterminate - High quality mode</span><br/>In most cases high quality of images and magnification.<br/>Overall quality highly depends on the resolution of source files.<br/>On Kindle models older than Paperwhite non-zoomed images might be a little blurred.</p><p><span style=" font-weight:600; text-decoration: underline;">Checked - Ultra quality mode</span><br/>Highest possible quality. Output files will be big.</p></body></html></string>
|
<string><html><head/><body><p style='white-space:pre'>Quality of Panel View/zoom. Highly impact size of output file.<br/><span style=" font-weight:600;">This option control only quality of magnification!</span></p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>High/Ultra quality</string>
|
<string>High/Ultra quality</string>
|
||||||
@@ -450,6 +456,9 @@
|
|||||||
<property name="styleSheet">
|
<property name="styleSheet">
|
||||||
<string notr="true">QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}</string>
|
<string notr="true">QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="verticalScrollBarPolicy">
|
||||||
|
<enum>Qt::ScrollBarAlwaysOn</enum>
|
||||||
|
</property>
|
||||||
<property name="showDropIndicator" stdset="0">
|
<property name="showDropIndicator" stdset="0">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
|
|||||||
17
KCC.ui
17
KCC.ui
@@ -65,7 +65,7 @@
|
|||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p style='white-space:pre'>Disable image optimizations.<br/>Input images must be already resized.</p></body></html></string>
|
<string><html><head/><body><p style='white-space:pre'>Disable image optimizations.<br/><span style=" font-weight:600;">Input images must be already resized.</span></p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>No optimisation</string>
|
<string>No optimisation</string>
|
||||||
@@ -94,7 +94,7 @@
|
|||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p style="white-space:pre">Enable auto-splitting of webtoons like <span style=" font-style:italic;">Tower of God</span> or <span style=" font-style:italic;">Noblesse</span>.<br/>This mode is created for pages with a low width, high height and vertical panel flow.</p></body></html></string>
|
<string><html><head/><body><p style='white-space:pre'>Enable special parsing mode for WebToons.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Webtoon mode</string>
|
<string>Webtoon mode</string>
|
||||||
@@ -136,7 +136,7 @@
|
|||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p style='white-space:pre'>Disable splitting and rotation.</p></body></html></string>
|
<string><html><head/><body><p style='white-space:pre'>Disable page splitting and rotation.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>No split/rotate</string>
|
<string>No split/rotate</string>
|
||||||
@@ -234,6 +234,9 @@
|
|||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p style='white-space:pre'>Add directory containing JPG, PNG or GIF files to queue.<br/><span style=" font-weight:600;">CBR, CBZ and CB7 files inside will not be processed!</span></p></body></html></string>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Add directory</string>
|
<string>Add directory</string>
|
||||||
</property>
|
</property>
|
||||||
@@ -259,6 +262,9 @@
|
|||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p style='white-space:pre'>Add CBR, CBZ, CB7 or PDF file to queue.</p></body></html></string>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Add file</string>
|
<string>Add file</string>
|
||||||
</property>
|
</property>
|
||||||
@@ -338,7 +344,7 @@
|
|||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p style="white-space:pre"><span style=" font-weight:600; text-decoration: underline;">Unchecked - Normal quality mode<br/></span>Maximal quality of images but very poor magnification quality.<br/>Use it only when zoom is not needed or output files needs to be small.</p><p style="white-space:pre"><span style=" font-weight:600; text-decoration: underline;">Indeterminate - High quality mode<br/></span>In most cases high quality of images and magnification.<br/>Overall quality highly depends on the resolution of source files.<br/>On Kindle models older than Paperwhite non-zoomed images might be a little blurred.</p><p style="white-space:pre"><span style=" font-weight:600; text-decoration: underline;">Checked - Ultra quality mode<br/></span>Highest possible quality. Output files will be big.</p></body></html></string>
|
<string><html><head/><body><p style='white-space:pre'>Quality of Panel View/zoom. Highly impact size of output file.<br/><span style=" font-weight:600;">This option control only quality of magnification!</span></p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>High/Ultra quality</string>
|
<string>High/Ultra quality</string>
|
||||||
@@ -385,6 +391,9 @@
|
|||||||
<property name="styleSheet">
|
<property name="styleSheet">
|
||||||
<string notr="true">QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}</string>
|
<string notr="true">QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="verticalScrollBarPolicy">
|
||||||
|
<enum>Qt::ScrollBarAlwaysOn</enum>
|
||||||
|
</property>
|
||||||
<property name="showDropIndicator" stdset="0">
|
<property name="showDropIndicator" stdset="0">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
ISC LICENSE
|
ISC LICENSE
|
||||||
|
|
||||||
Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
Copyright (c) 2013-2014 Paweł Jastrzębski <pawelj@iosphe.re>
|
Copyright (c) 2013-2015 Paweł Jastrzębski <pawelj@iosphe.re>
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for
|
Permission to use, copy, modify, and/or distribute this software for
|
||||||
any purpose with or without fee is hereby granted, provided that the
|
any purpose with or without fee is hereby granted, provided that the
|
||||||
|
|||||||
381
README.md
381
README.md
@@ -13,8 +13,7 @@ _KC2_ in no way is a replacement for **KCC** so you can be quite confident we'll
|
|||||||
### Issues / new features / donations
|
### Issues / new features / donations
|
||||||
If you have general questions about usage, feedback etc. please [post it here](http://www.mobileread.com/forums/showthread.php?t=207461).
|
If you have general questions about usage, feedback etc. please [post it here](http://www.mobileread.com/forums/showthread.php?t=207461).
|
||||||
If you have some **technical** problems using KCC please [file an issue here](https://github.com/ciromattia/kcc/issues/new).
|
If you have some **technical** problems using KCC please [file an issue here](https://github.com/ciromattia/kcc/issues/new).
|
||||||
If you can fix an open issue, fork & make a pull request.
|
If you can fix an open issue, fork & make a pull request.
|
||||||
If you want more chances an issue is fixes or your wanted feature added, consider [placing a bounty](https://www.bountysource.com/trackers/65571-ciromattia-kcc)!
|
|
||||||
|
|
||||||
If you find **KCC** valuable you can consider donating to the authors:
|
If you find **KCC** valuable you can consider donating to the authors:
|
||||||
- Ciro Mattia Gonano:
|
- Ciro Mattia Gonano:
|
||||||
@@ -32,7 +31,7 @@ You can find the latest released binary at the following links:
|
|||||||
|
|
||||||
## INPUT FORMATS
|
## INPUT FORMATS
|
||||||
**KCC** can understand and convert, at the moment, the following input types:
|
**KCC** can understand and convert, at the moment, the following input types:
|
||||||
- Folders containing: PNG, JPG, GIF, TIFF or BMP files
|
- Folders containing: PNG, JPG or GIF files
|
||||||
- CBZ, ZIP
|
- CBZ, ZIP
|
||||||
- CBR, RAR *(With `unrar` executable)*
|
- CBR, RAR *(With `unrar` executable)*
|
||||||
- CB7, 7Z *(With `7za` executable)*
|
- CB7, 7Z *(With `7za` executable)*
|
||||||
@@ -45,20 +44,20 @@ You can find the latest released binary at the following links:
|
|||||||
|
|
||||||
### For running from source:
|
### For running from source:
|
||||||
- Python 3.3+
|
- Python 3.3+
|
||||||
- [PyQt5](http://www.riverbankcomputing.co.uk/software/pyqt/download5) 5.2.0+
|
- [PyQt](http://www.riverbankcomputing.co.uk/software/pyqt/download5) 5.2.0+
|
||||||
- [Pillow](http://pypi.python.org/pypi/Pillow/) 2.5.0+
|
- [Pillow](http://pypi.python.org/pypi/Pillow/) 2.7.0+
|
||||||
- [psutil](https://pypi.python.org/pypi/psutil) 2.0+
|
- [psutil](https://pypi.python.org/pypi/psutil) 2.0+
|
||||||
- [python-slugify](http://pypi.python.org/pypi/python-slugify)
|
- [python-slugify](http://pypi.python.org/pypi/python-slugify) 0.1.0+
|
||||||
|
|
||||||
On Debian based distributions these two commands should install all dependencies:
|
On Debian based distributions these two commands should install all dependencies:
|
||||||
```
|
```
|
||||||
sudo apt-get install python3 python3-dev python3-pip python3-pyqt5 libtiff-dev libpng-dev libjpeg-dev p7zip-full unrar
|
sudo apt-get install python3 python3-dev python3-pip python3-pyqt5 libpng-dev libjpeg-dev p7zip-full unrar
|
||||||
sudo pip3 install pillow python-slugify psutil
|
sudo pip3 install pillow python-slugify psutil
|
||||||
```
|
```
|
||||||
|
|
||||||
### For freezing code:
|
### For freezing code:
|
||||||
- Windows - [py2exe](https://pypi.python.org/pypi/py2exe) 0.9.2+
|
- Windows - [py2exe](https://pypi.python.org/pypi/py2exe) 0.9.2.2+
|
||||||
- OS X - [py2app](https://bitbucket.org/ronaldoussoren/py2app) 0.8.0+
|
- OS X - [py2app](https://bitbucket.org/ronaldoussoren/py2app) 0.9.0+
|
||||||
|
|
||||||
## USAGE
|
## USAGE
|
||||||
|
|
||||||
@@ -143,7 +142,7 @@ This script born as a cross-platform alternative to `KindleComicParser` by **Dc5
|
|||||||
The app relies and includes the following scripts:
|
The app relies and includes the following scripts:
|
||||||
|
|
||||||
- `DualMetaFix` script by **K. Hendricks**. Released with GPL-3 License.
|
- `DualMetaFix` script by **K. Hendricks**. Released with GPL-3 License.
|
||||||
- `rarfile.py` script © 2005-2011 **Marko Kreen** <markokr@gmail.com>. Released with ISC License.
|
- `rarfile.py` script © 2005-2014 **Marko Kreen** <markokr@gmail.com>. Released with ISC License.
|
||||||
- `image.py` class from **Alex Yatskov**'s [Mangle](https://github.com/FooSoft/mangle/) with subsequent [proDOOMman](https://github.com/proDOOMman/Mangle)'s and [Birua](https://github.com/Birua/Mangle)'s patches.
|
- `image.py` class from **Alex Yatskov**'s [Mangle](https://github.com/FooSoft/mangle/) with subsequent [proDOOMman](https://github.com/proDOOMman/Mangle)'s and [Birua](https://github.com/Birua/Mangle)'s patches.
|
||||||
- Icon is by **Nikolay Verin** ([http://ncrow.deviantart.com/](http://ncrow.deviantart.com/)) and released under [CC BY-NC-SA 3.0](http://creativecommons.org/licenses/by-nc-sa/3.0/) License.
|
- 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.
|
||||||
|
|
||||||
@@ -159,113 +158,119 @@ The app relies and includes the following scripts:
|
|||||||
* [Kobo Aura H2O](http://kcc.iosphe.re/Samples/Ubunchu!-KoAH2O.cbz)
|
* [Kobo Aura H2O](http://kcc.iosphe.re/Samples/Ubunchu!-KoAH2O.cbz)
|
||||||
|
|
||||||
## CHANGELOG
|
## CHANGELOG
|
||||||
####1.0
|
####4.4.1:
|
||||||
* Initial version
|
* Fixed problems with OSX GUI
|
||||||
|
* Added one missing DLL to Windows installer
|
||||||
|
|
||||||
####1.1
|
####4.4:
|
||||||
* Added support for CBZ/CBR files in comic2ebook.py
|
* Improved speed and quality of conversion
|
||||||
|
* Added RAR5 support
|
||||||
|
* Dropped BMP and TIFF support
|
||||||
|
* Fixed some WebToon mode bugs
|
||||||
|
* Fixed CBR parsing on OSX
|
||||||
|
|
||||||
####1.1.1
|
####4.3.1:
|
||||||
* Added support for CBZ/CBR files in Kindle Comic Converter
|
* Fixed Kindle Voyage profile
|
||||||
|
* Fixed some bugs in OS X release
|
||||||
|
* CLI version now support multiple input files at once
|
||||||
|
* Disabled MCB support
|
||||||
|
* Other minor tweaks
|
||||||
|
|
||||||
####1.2
|
####4.3:
|
||||||
* Comic optimizations! Split pages not target-oriented (landscape with portrait target or portrait with landscape target), add palette and other image optimizations from Mangle. WARNING: PIL is required for all image mangling!
|
* Added profiles for Kindle Voyage and Kobo Aura H2O
|
||||||
|
* Added missing features to CLI version
|
||||||
|
* Other minor bug fixes
|
||||||
|
|
||||||
####1.3
|
####4.2.1:
|
||||||
* Fixed an issue in OPF generation for device resolution
|
* Improved margin color detection
|
||||||
* Reworked options system (call with -h option to get the inline help)
|
* Fixed random crashes of MOBI processing step
|
||||||
|
* Fixed resizing problems in high quality mode
|
||||||
|
* Fixed some MCD support bugs
|
||||||
|
* Default output format for Kindle DX is now CBZ
|
||||||
|
|
||||||
####1.4
|
####4.2:
|
||||||
* Added some options for controlling image optimization
|
* Added [Manga Cover Database](http://manga.joentjuh.nl/) support
|
||||||
* Further optimization (ImageOps, page numbering cut, autocontrast)
|
* Officially dropped Windows XP support
|
||||||
|
* Fixed _Other_ profile
|
||||||
|
* Fixed problems with page order on stock KOBO CBZ reader
|
||||||
|
* Many other small bug fixes and tweaks
|
||||||
|
|
||||||
####1.4.1
|
####4.1:
|
||||||
* Fixed a serious bug on resizing when img ratio was bigger than device one
|
* Thanks to code contributed by Kevin Hendricks speed of MOBI creation was greatly increased
|
||||||
|
* Improved performance on Windows
|
||||||
|
* Improved MOBI splitting and changed maximal size of output file
|
||||||
|
* Fixed _No optimization_ mode
|
||||||
|
* Multiple small tweaks nad minor bug fixes
|
||||||
|
|
||||||
####1.5
|
####4.0.2:
|
||||||
* Added subfolder support for multiple chapters.
|
* Fixed some Windows and OSX specific bugs
|
||||||
|
* Fixed problem with marigns when using HQ mode
|
||||||
|
|
||||||
####2.0
|
####4.0.1:
|
||||||
* GUI! AppleScript is gone and Tk is used to provide cross-platform GUI support.
|
* Fixed file lock problems that plagued some Windows users
|
||||||
|
* Fixed content server failing to start on Windows
|
||||||
|
* Improved performance of WebToon splitter
|
||||||
|
* Tweaked margin color detection
|
||||||
|
|
||||||
####2.1
|
####4.0:
|
||||||
* Added basic error reporting
|
* KCC now use Python 3.3 and Qt 5.2
|
||||||
|
* Full UTF-8 awareness
|
||||||
|
* CBZ output now support Manga mode
|
||||||
|
* Improved Panel View support and margin color detection
|
||||||
|
* Added drag&drop support
|
||||||
|
* Output directory can be now selected
|
||||||
|
* Windows release now have auto-updater
|
||||||
|
* Names of chapters on Kindle should be now more user friendly
|
||||||
|
* Fixed OSX file association support
|
||||||
|
* Many extensive internal changes and tweaks
|
||||||
|
|
||||||
####2.2:
|
####3.7.2:
|
||||||
* Added (valid!) EPUB 2.0 output
|
* Fixed problems with HQ mode
|
||||||
* Rename .zip files to .cbz to avoid overwriting
|
|
||||||
|
|
||||||
####2.3
|
####3.7.1:
|
||||||
* Fixed win32 EPUB generation, folder handling, filenames with spaces and subfolders
|
* Hotfixed Kobo profiles
|
||||||
|
|
||||||
####2.4
|
####3.7:
|
||||||
* Use temporary directory as workdir (fixes converting from external volumes and zipfiles renaming)
|
* Added profiles for KOBO devices
|
||||||
* Fixed "add folders" from GUI.
|
* Improved Panel View support
|
||||||
|
* Improved WebToon splitter
|
||||||
|
* Improved margin color autodetection
|
||||||
|
* Tweaked EPUB output
|
||||||
|
* Fixed stretching option
|
||||||
|
* GUI tweaks and minor bugfixes
|
||||||
|
|
||||||
####2.5
|
####3.6.2:
|
||||||
* Added --black-borders option to set added borders black when page's ratio is not the device's one (#11).
|
* Fixed previous PNG output fix
|
||||||
* Fixes EPUB containing zipped itself (#10)
|
* Fixed Panel View anomalies
|
||||||
|
|
||||||
####2.6
|
####3.6.1:
|
||||||
* Added --rotate option to rotate landscape images instead of splitting them (#16, #24)
|
* Fixed PNG output
|
||||||
* Added --output option to customize EPUB output dir/file (#22)
|
|
||||||
* Add rendition:layout and rendition:orientation EPUB meta tags (supported by new kindlegen 2.8)
|
|
||||||
* Fixed natural sorting for files (#18)
|
|
||||||
|
|
||||||
####2.7
|
####3.6:
|
||||||
* Lots of GUI improvements (#27, #13)
|
* Increased quality of Panel View zoom
|
||||||
* Added gamma support within --gamma option (defaults to profile-specified gamma) (#26, #27)
|
* Creation of multipart MOBI output is now faster on machines with 4GB+ RAM
|
||||||
* Added --nodithering option to prevent dithering optimizations (#27)
|
* Automatic gamma correction now distinguishes color and grayscale images
|
||||||
* EPUB margins support (#30)
|
* Added ComicRack metadata parser
|
||||||
* Fixed no file added if file has no spaces on Windows (#25)
|
* Implemented new method to detect border color in non-webtoon comics
|
||||||
* Gracefully exit if unrar missing (#15)
|
* Upscaling is now enabled by default for Kindle Fire HD/HDX
|
||||||
* Do not call kindlegen if source EPUB is bigger than 320MB (#17)
|
* Windows nad Linux releases now have tray icon
|
||||||
* Get filetype from magic number (#14)
|
* Fixed Kindle Fire HDX 7" output
|
||||||
* PDF conversion works again
|
* Increased target resolution for Kindle DX/DXG CBZ output
|
||||||
|
|
||||||
####2.8
|
####3.5:
|
||||||
* Updated rarfile library
|
* Added simple content server - Converted files can be now delivered wireless
|
||||||
* Panel View support + HQ support (#36) - new option: --nopanelviewhq
|
* Added proper Windows installer
|
||||||
* Split profiles for K4NT and K4T
|
* Improved multiprocessing speed
|
||||||
* Rewrite of Landscape Mode support (huge readability improvement for KPW)
|
* GUI tweaks and minor bug fixes
|
||||||
* Upscale use now BILINEAR method
|
|
||||||
* Added generic CSS file
|
|
||||||
* Optimized archive extraction for zip/rar files (#40)
|
|
||||||
|
|
||||||
####2.9
|
####3.4:
|
||||||
* Added support for generating a plain CBZ (skipping all the EPUB/MOBI generation) (#45)
|
* Improved PNG output
|
||||||
* Prevent output file overwriting the source one: if a duplicate name is detected, append _kcc to the name
|
* Increased quality of upscaling
|
||||||
* Rarfile library updated to 2.6
|
* Added support of file association - KCC can now open CBZ, CBR, CB7, ZIP, RAR, 7Z and PDF files directly
|
||||||
* Added GIF, TIFF and BMP to supported formats (#42)
|
* Paths that contain UTF-8 characters are now supported
|
||||||
* Filenames slugifications (#28, #31, #9, #8)
|
* Migrated to new version of Pillow library
|
||||||
|
* Merged DX and DXG profiles
|
||||||
####2.10:
|
* Many other minor bug fixes and GUI tweaks
|
||||||
* Multiprocessing support
|
|
||||||
* Kindle Fire support (color EPUB/MOBI)
|
|
||||||
* Panel View support for horizontal content
|
|
||||||
* Fixed panel order for horizontal pages when --rotate is enabled
|
|
||||||
* Disabled cropping and page number cutting for blank pages
|
|
||||||
* Fixed some slugify issues with specific file naming conventions (#50, #51)
|
|
||||||
|
|
||||||
####3.0:
|
|
||||||
* New QT GUI
|
|
||||||
* Merge with AWKCC
|
|
||||||
* Added ultra quality mode
|
|
||||||
* Added support for custom width/height
|
|
||||||
* Added option to disable color conversion
|
|
||||||
|
|
||||||
####3.1:
|
|
||||||
* Added profile: Kindle for Android
|
|
||||||
* Add file/directory dialogs now support multiselect
|
|
||||||
* Many small fixes and tweaks
|
|
||||||
|
|
||||||
####3.2:
|
|
||||||
* Too big EPUB files are now splitted before conversion to MOBI
|
|
||||||
* Added experimental parser of manga webtoons
|
|
||||||
* Improved error handling
|
|
||||||
|
|
||||||
####3.2.1:
|
|
||||||
* Hotfixed crash occurring on OS with Russian locale
|
|
||||||
|
|
||||||
####3.3:
|
####3.3:
|
||||||
* Margins are now automatically omitted in Panel View mode
|
* Margins are now automatically omitted in Panel View mode
|
||||||
@@ -281,105 +286,117 @@ The app relies and includes the following scripts:
|
|||||||
* Windows release is now bundled with UnRAR and 7za
|
* Windows release is now bundled with UnRAR and 7za
|
||||||
* Small GUI tweaks
|
* Small GUI tweaks
|
||||||
|
|
||||||
####3.4:
|
####3.2:
|
||||||
* Improved PNG output
|
* Too big EPUB files are now splitted before conversion to MOBI
|
||||||
* Increased quality of upscaling
|
* Added experimental parser of manga webtoons
|
||||||
* Added support of file association - KCC can now open CBZ, CBR, CB7, ZIP, RAR, 7Z and PDF files directly
|
* Improved error handling
|
||||||
* Paths that contain UTF-8 characters are now supported
|
|
||||||
* Migrated to new version of Pillow library
|
|
||||||
* Merged DX and DXG profiles
|
|
||||||
* Many other minor bug fixes and GUI tweaks
|
|
||||||
|
|
||||||
####3.5:
|
####3.2.1:
|
||||||
* Added simple content server - Converted files can be now delivered wireless
|
* Hotfixed crash occurring on OS with Russian locale
|
||||||
* Added proper Windows installer
|
|
||||||
* Improved multiprocessing speed
|
|
||||||
* GUI tweaks and minor bug fixes
|
|
||||||
|
|
||||||
####3.6:
|
####3.1:
|
||||||
* Increased quality of Panel View zoom
|
* Added profile: Kindle for Android
|
||||||
* Creation of multipart MOBI output is now faster on machines with 4GB+ RAM
|
* Add file/directory dialogs now support multiselect
|
||||||
* Automatic gamma correction now distinguishes color and grayscale images
|
* Many small fixes and tweaks
|
||||||
* Added ComicRack metadata parser
|
|
||||||
* Implemented new method to detect border color in non-webtoon comics
|
|
||||||
* Upscaling is now enabled by default for Kindle Fire HD/HDX
|
|
||||||
* Windows nad Linux releases now have tray icon
|
|
||||||
* Fixed Kindle Fire HDX 7" output
|
|
||||||
* Increased target resolution for Kindle DX/DXG CBZ output
|
|
||||||
|
|
||||||
####3.6.1:
|
####3.0:
|
||||||
* Fixed PNG output
|
* New QT GUI
|
||||||
|
* Merge with AWKCC
|
||||||
|
* Added ultra quality mode
|
||||||
|
* Added support for custom width/height
|
||||||
|
* Added option to disable color conversion
|
||||||
|
|
||||||
####3.6.2:
|
####2.10:
|
||||||
* Fixed previous PNG output fix
|
* Multiprocessing support
|
||||||
* Fixed Panel View anomalies
|
* Kindle Fire support (color EPUB/MOBI)
|
||||||
|
* Panel View support for horizontal content
|
||||||
|
* Fixed panel order for horizontal pages when --rotate is enabled
|
||||||
|
* Disabled cropping and page number cutting for blank pages
|
||||||
|
* Fixed some slugify issues with specific file naming conventions (#50, #51)
|
||||||
|
|
||||||
####3.7:
|
####2.9
|
||||||
* Added profiles for KOBO devices
|
* Added support for generating a plain CBZ (skipping all the EPUB/MOBI generation) (#45)
|
||||||
* Improved Panel View support
|
* Prevent output file overwriting the source one: if a duplicate name is detected, append _kcc to the name
|
||||||
* Improved WebToon splitter
|
* Rarfile library updated to 2.6
|
||||||
* Improved margin color autodetection
|
* Added GIF, TIFF and BMP to supported formats (#42)
|
||||||
* Tweaked EPUB output
|
* Filenames slugifications (#28, #31, #9, #8)
|
||||||
* Fixed stretching option
|
|
||||||
* GUI tweaks and minor bugfixes
|
|
||||||
|
|
||||||
####3.7.1:
|
####2.8
|
||||||
* Hotfixed Kobo profiles
|
* Updated rarfile library
|
||||||
|
* Panel View support + HQ support (#36) - new option: --nopanelviewhq
|
||||||
|
* Split profiles for K4NT and K4T
|
||||||
|
* Rewrite of Landscape Mode support (huge readability improvement for KPW)
|
||||||
|
* Upscale use now BILINEAR method
|
||||||
|
* Added generic CSS file
|
||||||
|
* Optimized archive extraction for zip/rar files (#40)
|
||||||
|
|
||||||
####3.7.2:
|
####2.7
|
||||||
* Fixed problems with HQ mode
|
* Lots of GUI improvements (#27, #13)
|
||||||
|
* Added gamma support within --gamma option (defaults to profile-specified gamma) (#26, #27)
|
||||||
|
* Added --nodithering option to prevent dithering optimizations (#27)
|
||||||
|
* EPUB margins support (#30)
|
||||||
|
* Fixed no file added if file has no spaces on Windows (#25)
|
||||||
|
* Gracefully exit if unrar missing (#15)
|
||||||
|
* Do not call kindlegen if source EPUB is bigger than 320MB (#17)
|
||||||
|
* Get filetype from magic number (#14)
|
||||||
|
* PDF conversion works again
|
||||||
|
|
||||||
####4.0:
|
####2.6
|
||||||
* KCC now use Python 3.3 and Qt 5.2
|
* Added --rotate option to rotate landscape images instead of splitting them (#16, #24)
|
||||||
* Full UTF-8 awareness
|
* Added --output option to customize EPUB output dir/file (#22)
|
||||||
* CBZ output now support Manga mode
|
* Add rendition:layout and rendition:orientation EPUB meta tags (supported by new kindlegen 2.8)
|
||||||
* Improved Panel View support and margin color detection
|
* Fixed natural sorting for files (#18)
|
||||||
* Added drag&drop support
|
|
||||||
* Output directory can be now selected
|
|
||||||
* Windows release now have auto-updater
|
|
||||||
* Names of chapters on Kindle should be now more user friendly
|
|
||||||
* Fixed OSX file association support
|
|
||||||
* Many extensive internal changes and tweaks
|
|
||||||
|
|
||||||
####4.0.1:
|
####2.5
|
||||||
* Fixed file lock problems that plagued some Windows users
|
* Added --black-borders option to set added borders black when page's ratio is not the device's one (#11).
|
||||||
* Fixed content server failing to start on Windows
|
* Fixes EPUB containing zipped itself (#10)
|
||||||
* Improved performance of WebToon splitter
|
|
||||||
* Tweaked margin color detection
|
|
||||||
|
|
||||||
####4.0.2:
|
####2.4
|
||||||
* Fixed some Windows and OSX specific bugs
|
* Use temporary directory as workdir (fixes converting from external volumes and zipfiles renaming)
|
||||||
* Fixed problem with marigns when using HQ mode
|
* Fixed "add folders" from GUI.
|
||||||
|
|
||||||
####4.1:
|
####2.3
|
||||||
* Thanks to code contributed by Kevin Hendricks speed of MOBI creation was greatly increased
|
* Fixed win32 EPUB generation, folder handling, filenames with spaces and subfolders
|
||||||
* Improved performance on Windows
|
|
||||||
* Improved MOBI splitting and changed maximal size of output file
|
|
||||||
* Fixed _No optimization_ mode
|
|
||||||
* Multiple small tweaks nad minor bug fixes
|
|
||||||
|
|
||||||
####4.2:
|
####2.2:
|
||||||
* Added [Manga Cover Database](http://manga.joentjuh.nl/) support
|
* Added (valid!) EPUB 2.0 output
|
||||||
* Officially dropped Windows XP support
|
* Rename .zip files to .cbz to avoid overwriting
|
||||||
* Fixed _Other_ profile
|
|
||||||
* Fixed problems with page order on stock KOBO CBZ reader
|
|
||||||
* Many other small bug fixes and tweaks
|
|
||||||
|
|
||||||
####4.2.1:
|
####2.1
|
||||||
* Improved margin color detection
|
* Added basic error reporting
|
||||||
* Fixed random crashes of MOBI processing step
|
|
||||||
* Fixed resizing problems in high quality mode
|
|
||||||
* Fixed some MCD support bugs
|
|
||||||
* Default output format for Kindle DX is now CBZ
|
|
||||||
|
|
||||||
####4.3:
|
####2.0
|
||||||
* Added profiles for Kindle Voyage and Kobo Aura H2O
|
* GUI! AppleScript is gone and Tk is used to provide cross-platform GUI support.
|
||||||
* Added missing features to CLI version
|
|
||||||
* Other minor bug fixes
|
####1.5
|
||||||
|
* Added subfolder support for multiple chapters.
|
||||||
|
|
||||||
|
####1.4.1
|
||||||
|
* Fixed a serious bug on resizing when img ratio was bigger than device one
|
||||||
|
|
||||||
|
####1.4
|
||||||
|
* Added some options for controlling image optimization
|
||||||
|
* Further optimization (ImageOps, page numbering cut, autocontrast)
|
||||||
|
|
||||||
|
####1.3
|
||||||
|
* Fixed an issue in OPF generation for device resolution
|
||||||
|
* Reworked options system (call with -h option to get the inline help)
|
||||||
|
|
||||||
|
####1.2
|
||||||
|
* Comic optimizations! Split pages not target-oriented (landscape with portrait target or portrait with landscape target), add palette and other image optimizations from Mangle. WARNING: PIL is required for all image mangling!
|
||||||
|
|
||||||
|
####1.1.1
|
||||||
|
* Added support for CBZ/CBR files in Kindle Comic Converter
|
||||||
|
|
||||||
|
####1.1
|
||||||
|
* Added support for CBZ/CBR files in comic2ebook.py
|
||||||
|
|
||||||
|
####1.0
|
||||||
|
* Initial version
|
||||||
|
|
||||||
## KNOWN ISSUES
|
## KNOWN ISSUES
|
||||||
Please check [wiki page](https://github.com/ciromattia/kcc/wiki/Known-issues).
|
Please check [wiki page](https://github.com/ciromattia/kcc/wiki/Known-issues).
|
||||||
|
|
||||||
## COPYRIGHT
|
## COPYRIGHT
|
||||||
Copyright (c) 2012-2014 Ciro Mattia Gonano and Paweł Jastrzębski.
|
Copyright (c) 2012-2015 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.
|
||||||
|
|||||||
41
kcc-c2e.py
41
kcc-c2e.py
@@ -2,7 +2,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
# Copyright (c) 2013-2014 Pawel Jastrzebski <pawelj@iosphe.re>
|
# Copyright (c) 2013-2015 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, and/or distribute this software for
|
# Permission to use, copy, modify, and/or distribute this software for
|
||||||
# any purpose with or without fee is hereby granted, provided that the
|
# any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -18,9 +18,9 @@
|
|||||||
# 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__ = '4.3'
|
__version__ = '4.4.1'
|
||||||
__license__ = 'ISC'
|
__license__ = 'ISC'
|
||||||
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
|
__copyright__ = '2012-2015, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
@@ -28,39 +28,8 @@ if sys.version_info[0] != 3:
|
|||||||
print('ERROR: This is Python 3 script!')
|
print('ERROR: This is Python 3 script!')
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
# Dependency check
|
from kcc.shared import dependencyCheck
|
||||||
missing = []
|
dependencyCheck(2)
|
||||||
try:
|
|
||||||
# noinspection PyUnresolvedReferences
|
|
||||||
import psutil
|
|
||||||
if tuple(map(int, ('2.0.0'.split(".")))) > tuple(map(int, psutil.version_info)):
|
|
||||||
missing.append('psutil 2.0.0+')
|
|
||||||
except ImportError:
|
|
||||||
missing.append('psutil 2.0.0+')
|
|
||||||
try:
|
|
||||||
# noinspection PyUnresolvedReferences
|
|
||||||
import PIL
|
|
||||||
if tuple(map(int, ('2.5.0'.split(".")))) > tuple(map(int, (PIL.PILLOW_VERSION.split(".")))):
|
|
||||||
missing.append('Pillow 2.5.0+')
|
|
||||||
except ImportError:
|
|
||||||
missing.append('Pillow 2.5.0+')
|
|
||||||
try:
|
|
||||||
# noinspection PyUnresolvedReferences
|
|
||||||
import slugify
|
|
||||||
except ImportError:
|
|
||||||
missing.append('python-slugify')
|
|
||||||
if len(missing) > 0:
|
|
||||||
try:
|
|
||||||
# noinspection PyUnresolvedReferences
|
|
||||||
import tkinter
|
|
||||||
# noinspection PyUnresolvedReferences
|
|
||||||
import tkinter.messagebox
|
|
||||||
importRoot = tkinter.Tk()
|
|
||||||
importRoot.withdraw()
|
|
||||||
tkinter.messagebox.showerror('KCC - Error', 'ERROR: ' + ', '.join(missing) + ' is not installed!')
|
|
||||||
except ImportError:
|
|
||||||
print('ERROR: ' + ', '.join(missing) + ' is not installed!')
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
from multiprocessing import freeze_support
|
from multiprocessing import freeze_support
|
||||||
from kcc.comic2ebook import main
|
from kcc.comic2ebook import main
|
||||||
|
|||||||
31
kcc-c2p.py
31
kcc-c2p.py
@@ -2,7 +2,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
# Copyright (c) 2013-2014 Pawel Jastrzebski <pawelj@iosphe.re>
|
# Copyright (c) 2013-2015 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, and/or distribute this software for
|
# Permission to use, copy, modify, and/or distribute this software for
|
||||||
# any purpose with or without fee is hereby granted, provided that the
|
# any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -18,9 +18,9 @@
|
|||||||
# 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__ = '4.3'
|
__version__ = '4.4.1'
|
||||||
__license__ = 'ISC'
|
__license__ = 'ISC'
|
||||||
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
|
__copyright__ = '2012-2015, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
@@ -28,33 +28,14 @@ if sys.version_info[0] != 3:
|
|||||||
print('ERROR: This is Python 3 script!')
|
print('ERROR: This is Python 3 script!')
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
# Dependency check
|
from kcc.shared import dependencyCheck
|
||||||
missing = []
|
dependencyCheck(1)
|
||||||
try:
|
|
||||||
# noinspection PyUnresolvedReferences
|
|
||||||
import PIL
|
|
||||||
if tuple(map(int, ('2.5.0'.split(".")))) > tuple(map(int, (PIL.PILLOW_VERSION.split(".")))):
|
|
||||||
missing.append('Pillow 2.5.0+')
|
|
||||||
except ImportError:
|
|
||||||
missing.append('Pillow 2.5.0+')
|
|
||||||
if len(missing) > 0:
|
|
||||||
try:
|
|
||||||
# noinspection PyUnresolvedReferences
|
|
||||||
import tkinter
|
|
||||||
# noinspection PyUnresolvedReferences
|
|
||||||
import tkinter.messagebox
|
|
||||||
importRoot = tkinter.Tk()
|
|
||||||
importRoot.withdraw()
|
|
||||||
tkinter.messagebox.showerror('KCC - Error', 'ERROR: ' + ', '.join(missing) + ' is not installed!')
|
|
||||||
except ImportError:
|
|
||||||
print('ERROR: ' + ', '.join(missing) + ' is not installed!')
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
from multiprocessing import freeze_support
|
from multiprocessing import freeze_support
|
||||||
from kcc.comic2panel import main
|
from kcc.comic2panel import main
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
freeze_support()
|
freeze_support()
|
||||||
print(('comic2ebook v%(__version__)s. Written by Ciro Mattia Gonano and Pawel Jastrzebski.' % globals()))
|
print(('comic2panel v%(__version__)s. Written by Ciro Mattia Gonano and Pawel Jastrzebski.' % globals()))
|
||||||
main(sys.argv[1:])
|
main(sys.argv[1:])
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
4
kcc.iss
4
kcc.iss
@@ -1,5 +1,5 @@
|
|||||||
#define MyAppName "Kindle Comic Converter"
|
#define MyAppName "Kindle Comic Converter"
|
||||||
#define MyAppVersion "4.3"
|
#define MyAppVersion "4.4.1"
|
||||||
#define MyAppPublisher "Ciro Mattia Gonano, Paweł Jastrzębski"
|
#define MyAppPublisher "Ciro Mattia Gonano, Paweł Jastrzębski"
|
||||||
#define MyAppURL "http://kcc.iosphe.re/"
|
#define MyAppURL "http://kcc.iosphe.re/"
|
||||||
#define MyAppExeName "KCC.exe"
|
#define MyAppExeName "KCC.exe"
|
||||||
@@ -12,7 +12,7 @@ AppPublisher={#MyAppPublisher}
|
|||||||
AppPublisherURL={#MyAppURL}
|
AppPublisherURL={#MyAppURL}
|
||||||
AppSupportURL={#MyAppURL}
|
AppSupportURL={#MyAppURL}
|
||||||
AppUpdatesURL={#MyAppURL}
|
AppUpdatesURL={#MyAppURL}
|
||||||
AppCopyright=Copyright (C) 2012-2014 Ciro Mattia Gonano and Paweł Jastrzębski
|
AppCopyright=Copyright (C) 2012-2015 Ciro Mattia Gonano and Paweł Jastrzębski
|
||||||
DefaultDirName={pf}\{#MyAppName}
|
DefaultDirName={pf}\{#MyAppName}
|
||||||
DefaultGroupName={#MyAppName}
|
DefaultGroupName={#MyAppName}
|
||||||
AllowNoIcons=yes
|
AllowNoIcons=yes
|
||||||
|
|||||||
136
kcc.py
136
kcc.py
@@ -2,7 +2,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
# Copyright (c) 2013-2014 Pawel Jastrzebski <pawelj@iosphe.re>
|
# Copyright (c) 2013-2015 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, and/or distribute this software for
|
# Permission to use, copy, modify, and/or distribute this software for
|
||||||
# any purpose with or without fee is hereby granted, provided that the
|
# any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -18,9 +18,9 @@
|
|||||||
# 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__ = '4.3'
|
__version__ = '4.4.1'
|
||||||
__license__ = 'ISC'
|
__license__ = 'ISC'
|
||||||
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
|
__copyright__ = '2012-2015, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
@@ -28,57 +28,13 @@ if sys.version_info[0] != 3:
|
|||||||
print('ERROR: This is Python 3 script!')
|
print('ERROR: This is Python 3 script!')
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
# Dependency check
|
|
||||||
missing = []
|
|
||||||
try:
|
|
||||||
# noinspection PyUnresolvedReferences
|
|
||||||
from PyQt5 import QtCore, QtNetwork, QtWidgets
|
|
||||||
if tuple(map(int, ('5.2.0'.split(".")))) > tuple(map(int, (QtCore.qVersion().split(".")))):
|
|
||||||
missing.append('PyQt5 5.2.0+')
|
|
||||||
except ImportError:
|
|
||||||
missing.append('PyQt5 5.2.0+')
|
|
||||||
try:
|
|
||||||
# noinspection PyUnresolvedReferences
|
|
||||||
import psutil
|
|
||||||
if tuple(map(int, ('2.0.0'.split(".")))) > tuple(map(int, psutil.version_info)):
|
|
||||||
missing.append('psutil 2.0.0+')
|
|
||||||
except ImportError:
|
|
||||||
missing.append('psutil 2.0.0+')
|
|
||||||
try:
|
|
||||||
# noinspection PyUnresolvedReferences
|
|
||||||
import PIL
|
|
||||||
if tuple(map(int, ('2.5.0'.split(".")))) > tuple(map(int, (PIL.PILLOW_VERSION.split(".")))):
|
|
||||||
missing.append('Pillow 2.5.0+')
|
|
||||||
except ImportError:
|
|
||||||
missing.append('Pillow 2.5.0+')
|
|
||||||
try:
|
|
||||||
# noinspection PyUnresolvedReferences
|
|
||||||
import slugify
|
|
||||||
except ImportError:
|
|
||||||
missing.append('python-slugify')
|
|
||||||
if len(missing) > 0:
|
|
||||||
try:
|
|
||||||
# noinspection PyUnresolvedReferences
|
|
||||||
import tkinter
|
|
||||||
# noinspection PyUnresolvedReferences
|
|
||||||
import tkinter.messagebox
|
|
||||||
importRoot = tkinter.Tk()
|
|
||||||
importRoot.withdraw()
|
|
||||||
tkinter.messagebox.showerror('KCC - Error', 'ERROR: ' + ', '.join(missing) + ' is not installed!')
|
|
||||||
except ImportError:
|
|
||||||
print('ERROR: ' + ', '.join(missing) + ' is not installed!')
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
import os
|
|
||||||
from multiprocessing import freeze_support
|
|
||||||
from kcc import KCC_gui
|
|
||||||
|
|
||||||
# OS specific PATH variable workarounds
|
# OS specific PATH variable workarounds
|
||||||
|
import os
|
||||||
if sys.platform.startswith('darwin'):
|
if sys.platform.startswith('darwin'):
|
||||||
if 'RESOURCEPATH' in os.environ:
|
if 'RESOURCEPATH' not in os.environ:
|
||||||
os.environ['PATH'] = os.environ['RESOURCEPATH'] + ':' + os.environ['PATH']
|
|
||||||
else:
|
|
||||||
os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + '/other/:' + os.environ['PATH']
|
os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + '/other/:' + os.environ['PATH']
|
||||||
|
else:
|
||||||
|
os.environ['PATH'] = './../Resources:/usr/local/bin:/usr/bin:/bin'
|
||||||
elif sys.platform.startswith('win'):
|
elif sys.platform.startswith('win'):
|
||||||
if getattr(sys, 'frozen', False):
|
if getattr(sys, 'frozen', False):
|
||||||
os.chdir(os.path.dirname(os.path.abspath(sys.executable)))
|
os.chdir(os.path.dirname(os.path.abspath(sys.executable)))
|
||||||
@@ -96,79 +52,23 @@ elif sys.platform.startswith('win'):
|
|||||||
os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + '/other/;' + os.environ['PATH']
|
os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + '/other/;' + os.environ['PATH']
|
||||||
os.chdir(os.path.dirname(os.path.abspath(__file__)))
|
os.chdir(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
|
from kcc.shared import dependencyCheck
|
||||||
|
dependencyCheck(3)
|
||||||
|
|
||||||
# Implementing detection of already running KCC instance and forwarding argv to it
|
from multiprocessing import freeze_support
|
||||||
class QApplicationMessaging(QtWidgets.QApplication):
|
from kcc import KCC_gui
|
||||||
messageFromOtherInstance = QtCore.pyqtSignal(bytes)
|
|
||||||
|
|
||||||
def __init__(self, argv):
|
|
||||||
QtWidgets.QApplication.__init__(self, argv)
|
|
||||||
self._key = 'KCC'
|
|
||||||
self._timeout = 1000
|
|
||||||
self._locked = False
|
|
||||||
socket = QtNetwork.QLocalSocket(self)
|
|
||||||
socket.connectToServer(self._key, QtCore.QIODevice.WriteOnly)
|
|
||||||
if not socket.waitForConnected(self._timeout):
|
|
||||||
self._server = QtNetwork.QLocalServer(self)
|
|
||||||
# noinspection PyUnresolvedReferences
|
|
||||||
self._server.newConnection.connect(self.handleMessage)
|
|
||||||
self._server.listen(self._key)
|
|
||||||
else:
|
|
||||||
self._locked = True
|
|
||||||
socket.disconnectFromServer()
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
if not self._locked:
|
|
||||||
self._server.close()
|
|
||||||
|
|
||||||
def event(self, e):
|
|
||||||
if e.type() == QtCore.QEvent.FileOpen:
|
|
||||||
self.messageFromOtherInstance.emit(bytes(e.file(), 'UTF-8'))
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return QtWidgets.QApplication.event(self, e)
|
|
||||||
|
|
||||||
def isRunning(self):
|
|
||||||
return self._locked
|
|
||||||
|
|
||||||
def handleMessage(self):
|
|
||||||
socket = self._server.nextPendingConnection()
|
|
||||||
if socket.waitForReadyRead(self._timeout):
|
|
||||||
self.messageFromOtherInstance.emit(socket.readAll().data())
|
|
||||||
|
|
||||||
def sendMessage(self, message):
|
|
||||||
socket = QtNetwork.QLocalSocket(self)
|
|
||||||
socket.connectToServer(self._key, QtCore.QIODevice.WriteOnly)
|
|
||||||
socket.waitForConnected(self._timeout)
|
|
||||||
socket.write(bytes(message, 'UTF-8'))
|
|
||||||
socket.waitForBytesWritten(self._timeout)
|
|
||||||
socket.disconnectFromServer()
|
|
||||||
|
|
||||||
|
|
||||||
# Adding signals to QMainWindow
|
|
||||||
class QMainWindowKCC(QtWidgets.QMainWindow):
|
|
||||||
progressBarTick = QtCore.pyqtSignal(str)
|
|
||||||
modeConvert = QtCore.pyqtSignal(int)
|
|
||||||
addMessage = QtCore.pyqtSignal(str, str, bool)
|
|
||||||
addTrayMessage = QtCore.pyqtSignal(str, str)
|
|
||||||
showDialog = QtCore.pyqtSignal(str, str)
|
|
||||||
hideProgressBar = QtCore.pyqtSignal()
|
|
||||||
forceShutdown = QtCore.pyqtSignal()
|
|
||||||
dialogAnswer = QtCore.pyqtSignal(int)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
freeze_support()
|
freeze_support()
|
||||||
KCCAplication = QApplicationMessaging(sys.argv)
|
KCCAplication = KCC_gui.QApplicationMessaging(sys.argv)
|
||||||
if KCCAplication.isRunning():
|
if KCCAplication.isRunning():
|
||||||
if len(sys.argv) > 1:
|
if len(sys.argv) > 1:
|
||||||
KCCAplication.sendMessage(sys.argv[1])
|
KCCAplication.sendMessage(sys.argv[1])
|
||||||
sys.exit(0)
|
|
||||||
else:
|
else:
|
||||||
KCCAplication.sendMessage('ARISE')
|
KCCAplication.sendMessage('ARISE')
|
||||||
sys.exit(0)
|
else:
|
||||||
KCCWindow = QMainWindowKCC()
|
KCCWindow = KCC_gui.QMainWindowKCC()
|
||||||
KCCUI = KCC_gui.KCCGUI(KCCAplication, KCCWindow)
|
KCCUI = KCC_gui.KCCGUI(KCCAplication, KCCWindow)
|
||||||
if len(sys.argv) > 1:
|
if len(sys.argv) > 1:
|
||||||
KCCUI.handleMessage(sys.argv[1])
|
KCCUI.handleMessage(sys.argv[1])
|
||||||
sys.exit(KCCAplication.exec_())
|
sys.exit(KCCAplication.exec_())
|
||||||
|
|||||||
223
kcc/KCC_gui.py
223
kcc/KCC_gui.py
@@ -1,7 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
# Copyright (c) 2013-2014 Pawel Jastrzebski <pawelj@iosphe.re>
|
# Copyright (c) 2013-2015 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, and/or distribute this software for
|
# Permission to use, copy, modify, and/or distribute this software for
|
||||||
# any purpose with or without fee is hereby granted, provided that the
|
# any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -17,9 +17,9 @@
|
|||||||
# 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__ = '4.3'
|
__version__ = '4.4.1'
|
||||||
__license__ = 'ISC'
|
__license__ = 'ISC'
|
||||||
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
|
__copyright__ = '2012-2015, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import os
|
import os
|
||||||
@@ -33,12 +33,12 @@ from shutil import move
|
|||||||
from http.server import BaseHTTPRequestHandler, HTTPServer
|
from http.server import BaseHTTPRequestHandler, HTTPServer
|
||||||
from socketserver import ThreadingMixIn
|
from socketserver import ThreadingMixIn
|
||||||
from subprocess import STDOUT, PIPE
|
from subprocess import STDOUT, PIPE
|
||||||
from PyQt5 import QtGui, QtCore, QtWidgets
|
from PyQt5 import QtGui, QtCore, QtWidgets, QtNetwork
|
||||||
from xml.dom.minidom import parse
|
from xml.dom.minidom import parse
|
||||||
from html.parser import HTMLParser
|
|
||||||
from psutil import Popen, Process
|
from psutil import Popen, Process
|
||||||
from copy import copy
|
from copy import copy
|
||||||
from .shared import md5Checksum
|
from distutils.version import StrictVersion
|
||||||
|
from .shared import md5Checksum, HTMLStripper
|
||||||
from . import comic2ebook
|
from . import comic2ebook
|
||||||
from . import KCC_rc_web
|
from . import KCC_rc_web
|
||||||
if sys.platform.startswith('darwin'):
|
if sys.platform.startswith('darwin'):
|
||||||
@@ -49,6 +49,63 @@ else:
|
|||||||
from . import KCC_ui
|
from . import KCC_ui
|
||||||
|
|
||||||
|
|
||||||
|
class QApplicationMessaging(QtWidgets.QApplication):
|
||||||
|
messageFromOtherInstance = QtCore.pyqtSignal(bytes)
|
||||||
|
|
||||||
|
def __init__(self, argv):
|
||||||
|
QtWidgets.QApplication.__init__(self, argv)
|
||||||
|
self._key = 'KCC'
|
||||||
|
self._timeout = 1000
|
||||||
|
self._locked = False
|
||||||
|
socket = QtNetwork.QLocalSocket(self)
|
||||||
|
socket.connectToServer(self._key, QtCore.QIODevice.WriteOnly)
|
||||||
|
if not socket.waitForConnected(self._timeout):
|
||||||
|
self._server = QtNetwork.QLocalServer(self)
|
||||||
|
# noinspection PyUnresolvedReferences
|
||||||
|
self._server.newConnection.connect(self.handleMessage)
|
||||||
|
self._server.listen(self._key)
|
||||||
|
else:
|
||||||
|
self._locked = True
|
||||||
|
socket.disconnectFromServer()
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
if not self._locked:
|
||||||
|
self._server.close()
|
||||||
|
|
||||||
|
def event(self, e):
|
||||||
|
if e.type() == QtCore.QEvent.FileOpen:
|
||||||
|
self.messageFromOtherInstance.emit(bytes(e.file(), 'UTF-8'))
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return QtWidgets.QApplication.event(self, e)
|
||||||
|
|
||||||
|
def isRunning(self):
|
||||||
|
return self._locked
|
||||||
|
|
||||||
|
def handleMessage(self):
|
||||||
|
socket = self._server.nextPendingConnection()
|
||||||
|
if socket.waitForReadyRead(self._timeout):
|
||||||
|
self.messageFromOtherInstance.emit(socket.readAll().data())
|
||||||
|
|
||||||
|
def sendMessage(self, message):
|
||||||
|
socket = QtNetwork.QLocalSocket(self)
|
||||||
|
socket.connectToServer(self._key, QtCore.QIODevice.WriteOnly)
|
||||||
|
socket.waitForConnected(self._timeout)
|
||||||
|
socket.write(bytes(message, 'UTF-8'))
|
||||||
|
socket.waitForBytesWritten(self._timeout)
|
||||||
|
socket.disconnectFromServer()
|
||||||
|
|
||||||
|
|
||||||
|
class QMainWindowKCC(QtWidgets.QMainWindow):
|
||||||
|
progressBarTick = QtCore.pyqtSignal(str)
|
||||||
|
modeConvert = QtCore.pyqtSignal(int)
|
||||||
|
addMessage = QtCore.pyqtSignal(str, str, bool)
|
||||||
|
addTrayMessage = QtCore.pyqtSignal(str, str)
|
||||||
|
showDialog = QtCore.pyqtSignal(str, str)
|
||||||
|
hideProgressBar = QtCore.pyqtSignal()
|
||||||
|
forceShutdown = QtCore.pyqtSignal()
|
||||||
|
|
||||||
|
|
||||||
class Icons:
|
class Icons:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.deviceKindle = QtGui.QIcon()
|
self.deviceKindle = QtGui.QIcon()
|
||||||
@@ -76,19 +133,6 @@ class Icons:
|
|||||||
self.programIcon.addPixmap(QtGui.QPixmap(":/Icon/icons/comic2ebook.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
self.programIcon.addPixmap(QtGui.QPixmap(":/Icon/icons/comic2ebook.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
|
||||||
|
|
||||||
class HTMLStripper(HTMLParser):
|
|
||||||
def __init__(self):
|
|
||||||
HTMLParser.__init__(self)
|
|
||||||
self.reset()
|
|
||||||
self.fed = []
|
|
||||||
|
|
||||||
def handle_data(self, d):
|
|
||||||
self.fed.append(d)
|
|
||||||
|
|
||||||
def get_data(self):
|
|
||||||
return ''.join(self.fed)
|
|
||||||
|
|
||||||
|
|
||||||
class WebServerHandler(BaseHTTPRequestHandler):
|
class WebServerHandler(BaseHTTPRequestHandler):
|
||||||
# noinspection PyAttributeOutsideInit, PyArgumentList
|
# noinspection PyAttributeOutsideInit, PyArgumentList
|
||||||
def do_GET(self):
|
def do_GET(self):
|
||||||
@@ -111,15 +155,15 @@ class WebServerHandler(BaseHTTPRequestHandler):
|
|||||||
self.send_header('Content-type', 'text/html')
|
self.send_header('Content-type', 'text/html')
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
self.wfile.write(bytes('<!DOCTYPE html>\n'
|
self.wfile.write(bytes('<!DOCTYPE html>\n'
|
||||||
'<html lang="en">\n'
|
'<html lang="en">\n'
|
||||||
'<head><meta charset="utf-8">\n'
|
'<head><meta charset="utf-8">\n'
|
||||||
'<link href="' + GUI.webContent.favicon + '" rel="icon" type="image/x-icon" />\n'
|
'<link href="' + GUI.webContent.favicon + '" rel="icon" type="image/x-icon" />\n'
|
||||||
'<title>Kindle Comic Converter</title>\n'
|
'<title>Kindle Comic Converter</title>\n'
|
||||||
'</head>\n'
|
'</head>\n'
|
||||||
'<body>\n'
|
'<body>\n'
|
||||||
'<div style="text-align: center; font-size:25px">\n'
|
'<div style="text-align: center; font-size:25px">\n'
|
||||||
'<p style="font-size:50px">- <img style="vertical-align: middle" '
|
'<p style="font-size:50px">- <img style="vertical-align: middle" '
|
||||||
'alt="KCC Logo" src="' + GUI.webContent.logo + '" /> -</p>\n', 'UTF-8'))
|
'alt="KCC Logo" src="' + GUI.webContent.logo + '" /> -</p>\n', 'UTF-8'))
|
||||||
if len(GUI.completedWork) > 0 and not GUI.conversionAlive:
|
if len(GUI.completedWork) > 0 and not GUI.conversionAlive:
|
||||||
for key in sorted(GUI.completedWork.keys()):
|
for key in sorted(GUI.completedWork.keys()):
|
||||||
self.wfile.write(bytes('<p><a href="' + key + '">' + key.split('.')[0] + '</a></p>\n', 'UTF-8'))
|
self.wfile.write(bytes('<p><a href="' + key + '">' + key.split('.')[0] + '</a></p>\n', 'UTF-8'))
|
||||||
@@ -127,8 +171,8 @@ class WebServerHandler(BaseHTTPRequestHandler):
|
|||||||
self.wfile.write(bytes('<p style="font-weight: bold">No downloads are available.<br/>'
|
self.wfile.write(bytes('<p style="font-weight: bold">No downloads are available.<br/>'
|
||||||
'Convert some files and refresh this page.</p>\n', 'UTF-8'))
|
'Convert some files and refresh this page.</p>\n', 'UTF-8'))
|
||||||
self.wfile.write(bytes('</div>\n'
|
self.wfile.write(bytes('</div>\n'
|
||||||
'</body>\n'
|
'</body>\n'
|
||||||
'</html>\n', 'UTF-8'))
|
'</html>\n', 'UTF-8'))
|
||||||
elif sendReply:
|
elif sendReply:
|
||||||
outputFile = GUI.completedWork[unquote(self.path[1:])]
|
outputFile = GUI.completedWork[unquote(self.path[1:])]
|
||||||
fp = open(outputFile, 'rb')
|
fp = open(outputFile, 'rb')
|
||||||
@@ -189,6 +233,8 @@ class VersionThread(QtCore.QThread):
|
|||||||
QtCore.QThread.__init__(self)
|
QtCore.QThread.__init__(self)
|
||||||
self.newVersion = ''
|
self.newVersion = ''
|
||||||
self.md5 = ''
|
self.md5 = ''
|
||||||
|
self.barProgress = 0
|
||||||
|
self.answer = None
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
self.wait()
|
self.wait()
|
||||||
@@ -200,22 +246,28 @@ class VersionThread(QtCore.QThread):
|
|||||||
except Exception:
|
except Exception:
|
||||||
return
|
return
|
||||||
latestVersion = XML.childNodes[0].getElementsByTagName('latest')[0].childNodes[0].toxml()
|
latestVersion = XML.childNodes[0].getElementsByTagName('latest')[0].childNodes[0].toxml()
|
||||||
if tuple(map(int, (latestVersion.split(".")))) > tuple(map(int, (__version__.split(".")))):
|
if StrictVersion(latestVersion) > StrictVersion(__version__):
|
||||||
if sys.platform.startswith('win'):
|
if sys.platform.startswith('win'):
|
||||||
self.newVersion = latestVersion
|
self.newVersion = latestVersion
|
||||||
self.md5 = XML.childNodes[0].getElementsByTagName('WindowsMD5')[0].childNodes[0].toxml()
|
self.md5 = XML.childNodes[0].getElementsByTagName('WindowsMD5')[0].childNodes[0].toxml()
|
||||||
MW.showDialog.emit('<b>New version released!</b> <a href="https://github.com/ciromattia/kcc/releases/">'
|
MW.showDialog.emit('<b>New version released!</b> <a href="https://github.com/ciromattia/kcc/releases/">'
|
||||||
'See changelog.</a><<br/><br/>Installed version: ' + __version__ +
|
'See changelog.</a><br/><br/>Installed version: ' + __version__ +
|
||||||
'<br/>Current version: ' + latestVersion +
|
'<br/>Current version: ' + latestVersion +
|
||||||
'<br/><br/>Would you like to start automatic update?', 'question')
|
'<br/><br/>Would you like to start automatic update?', 'question')
|
||||||
|
self.getNewVersion()
|
||||||
else:
|
else:
|
||||||
MW.addMessage.emit('<a href="http://kcc.iosphe.re/">'
|
MW.addMessage.emit('<a href="http://kcc.iosphe.re/">'
|
||||||
'<b>New version is available!</b></a> '
|
'<b>New version is available!</b></a> '
|
||||||
'(<a href="https://github.com/ciromattia/kcc/releases/">'
|
'(<a href="https://github.com/ciromattia/kcc/releases/">'
|
||||||
'Changelog</a>)', 'warning', False)
|
'Changelog</a>)', 'warning', False)
|
||||||
|
|
||||||
def getNewVersion(self, dialogAnswer):
|
def setAnswer(self, dialogAnswer):
|
||||||
if dialogAnswer == QtWidgets.QMessageBox.Yes:
|
self.answer = dialogAnswer
|
||||||
|
|
||||||
|
def getNewVersion(self):
|
||||||
|
while self.answer is None:
|
||||||
|
sleep(1)
|
||||||
|
if self.answer == QtWidgets.QMessageBox.Yes:
|
||||||
try:
|
try:
|
||||||
MW.modeConvert.emit(-1)
|
MW.modeConvert.emit(-1)
|
||||||
MW.progressBarTick.emit('Downloading update')
|
MW.progressBarTick.emit('Downloading update')
|
||||||
@@ -234,9 +286,12 @@ class VersionThread(QtCore.QThread):
|
|||||||
MW.modeConvert.emit(1)
|
MW.modeConvert.emit(1)
|
||||||
|
|
||||||
def getNewVersionTick(self, size, blockSize, totalSize):
|
def getNewVersionTick(self, size, blockSize, totalSize):
|
||||||
|
progress = int((size / (totalSize // blockSize)) * 100)
|
||||||
if size == 0:
|
if size == 0:
|
||||||
MW.progressBarTick.emit(str(int(totalSize / blockSize)))
|
MW.progressBarTick.emit('100')
|
||||||
MW.progressBarTick.emit('tick')
|
if progress > self.barProgress:
|
||||||
|
self.barProgress = progress
|
||||||
|
MW.progressBarTick.emit('tick')
|
||||||
|
|
||||||
|
|
||||||
class ProgressThread(QtCore.QThread):
|
class ProgressThread(QtCore.QThread):
|
||||||
@@ -525,6 +580,7 @@ class KCCGUI(KCC_ui.Ui_KCC):
|
|||||||
dname = dname.replace('/', '\\')
|
dname = dname.replace('/', '\\')
|
||||||
self.lastPath = os.path.abspath(os.path.join(dname, os.pardir))
|
self.lastPath = os.path.abspath(os.path.join(dname, os.pardir))
|
||||||
GUI.JobList.addItem(dname)
|
GUI.JobList.addItem(dname)
|
||||||
|
GUI.JobList.scrollToBottom()
|
||||||
|
|
||||||
def selectFile(self):
|
def selectFile(self):
|
||||||
if self.needClean:
|
if self.needClean:
|
||||||
@@ -550,6 +606,7 @@ class KCCGUI(KCC_ui.Ui_KCC):
|
|||||||
fname = fname.replace('/', '\\')
|
fname = fname.replace('/', '\\')
|
||||||
self.lastPath = os.path.abspath(os.path.join(fname, os.pardir))
|
self.lastPath = os.path.abspath(os.path.join(fname, os.pardir))
|
||||||
GUI.JobList.addItem(fname)
|
GUI.JobList.addItem(fname)
|
||||||
|
GUI.JobList.scrollToBottom()
|
||||||
|
|
||||||
def clearJobs(self):
|
def clearJobs(self):
|
||||||
GUI.JobList.clear()
|
GUI.JobList.clear()
|
||||||
@@ -838,9 +895,9 @@ class KCCGUI(KCC_ui.Ui_KCC):
|
|||||||
if kind == 'error':
|
if kind == 'error':
|
||||||
QtWidgets.QMessageBox.critical(MW, 'KCC - Error', message, QtWidgets.QMessageBox.Ok)
|
QtWidgets.QMessageBox.critical(MW, 'KCC - Error', message, QtWidgets.QMessageBox.Ok)
|
||||||
elif kind == 'question':
|
elif kind == 'question':
|
||||||
dialogResponse = QtWidgets.QMessageBox.question(MW, 'KCC - Question', message,
|
GUI.versionCheck.setAnswer(QtWidgets.QMessageBox.question(MW, 'KCC - Question', message,
|
||||||
QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
|
QtWidgets.QMessageBox.Yes,
|
||||||
MW.dialogAnswer.emit(dialogResponse)
|
QtWidgets.QMessageBox.No))
|
||||||
|
|
||||||
def updateProgressbar(self, command):
|
def updateProgressbar(self, command):
|
||||||
if command == 'tick':
|
if command == 'tick':
|
||||||
@@ -885,15 +942,19 @@ class KCCGUI(KCC_ui.Ui_KCC):
|
|||||||
self.addMessage('Target resolution is not set!', 'error')
|
self.addMessage('Target resolution is not set!', 'error')
|
||||||
self.needClean = True
|
self.needClean = True
|
||||||
return
|
return
|
||||||
if str(GUI.FormatBox.currentText()) == 'MOBI' and not GUI.KindleGen:
|
if str(GUI.FormatBox.currentText()) == 'MOBI' and not self.KindleGen:
|
||||||
self.addMessage('Cannot find <a href="http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1000765211">'
|
self.detectKindleGen()
|
||||||
'<b>KindleGen</b></a>! MOBI conversion is not possible!', 'error')
|
if not self.KindleGen:
|
||||||
if sys.platform.startswith('win'):
|
GUI.JobList.clear()
|
||||||
self.addMessage('Download it and place EXE in KCC directory.', 'error')
|
self.addMessage('Cannot find <a href="http://www.amazon.com/gp/feature.html'
|
||||||
else:
|
'?ie=UTF8&docId=1000765211"><b>KindleGen</b></a>!'
|
||||||
self.addMessage('Download it, and place executable in /usr/local/bin directory.', 'error')
|
' MOBI conversion is unavailable!', 'error')
|
||||||
self.needClean = True
|
if sys.platform.startswith('win'):
|
||||||
return
|
self.addMessage('Download it and place EXE in KCC directory.', 'error')
|
||||||
|
else:
|
||||||
|
self.addMessage('Download it and place executable in /usr/local/bin directory.', 'error')
|
||||||
|
self.needClean = True
|
||||||
|
return
|
||||||
self.worker.start()
|
self.worker.start()
|
||||||
|
|
||||||
def hideProgressBar(self):
|
def hideProgressBar(self):
|
||||||
@@ -954,10 +1015,12 @@ class KCCGUI(KCC_ui.Ui_KCC):
|
|||||||
formats = ['.cbz', '.zip', '.pdf']
|
formats = ['.cbz', '.zip', '.pdf']
|
||||||
if os.path.isdir(message):
|
if os.path.isdir(message):
|
||||||
GUI.JobList.addItem(message)
|
GUI.JobList.addItem(message)
|
||||||
|
GUI.JobList.scrollToBottom()
|
||||||
elif os.path.isfile(message):
|
elif os.path.isfile(message):
|
||||||
extension = os.path.splitext(message)
|
extension = os.path.splitext(message)
|
||||||
if extension[1].lower() in formats:
|
if extension[1].lower() in formats:
|
||||||
GUI.JobList.addItem(message)
|
GUI.JobList.addItem(message)
|
||||||
|
GUI.JobList.scrollToBottom()
|
||||||
else:
|
else:
|
||||||
self.addMessage('This file type is unsupported!', 'error')
|
self.addMessage('This file type is unsupported!', 'error')
|
||||||
|
|
||||||
@@ -979,6 +1042,34 @@ class KCCGUI(KCC_ui.Ui_KCC):
|
|||||||
self.saveSettings(None)
|
self.saveSettings(None)
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
def detectKindleGen(self, startup=False):
|
||||||
|
if not sys.platform.startswith('win'):
|
||||||
|
try:
|
||||||
|
os.chmod('/usr/local/bin/kindlegen', 0o755)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
kindleGenExitCode = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, shell=True)
|
||||||
|
if kindleGenExitCode.wait() == 0:
|
||||||
|
self.KindleGen = True
|
||||||
|
versionCheck = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, shell=True)
|
||||||
|
for line in versionCheck.stdout:
|
||||||
|
line = line.decode("utf-8")
|
||||||
|
if 'Amazon kindlegen' in line:
|
||||||
|
versionCheck = line.split('V')[1].split(' ')[0]
|
||||||
|
if StrictVersion(versionCheck) < StrictVersion('2.9'):
|
||||||
|
self.addMessage('Your <a href="http://www.amazon.com/gp/feature.html?ie=UTF8&docId='
|
||||||
|
'1000765211">KindleGen</a> is outdated! MOBI conversion might fail.', 'warning')
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
self.KindleGen = False
|
||||||
|
if startup:
|
||||||
|
self.addMessage('Cannot find <a href="http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1000765211">'
|
||||||
|
'<b>KindleGen</b></a>! MOBI conversion will be unavailable!', 'error')
|
||||||
|
if sys.platform.startswith('win'):
|
||||||
|
self.addMessage('Download it and place EXE in KCC directory.', 'error')
|
||||||
|
else:
|
||||||
|
self.addMessage('Download it and place executable in /usr/local/bin directory.', 'error')
|
||||||
|
|
||||||
# noinspection PyArgumentList
|
# noinspection PyArgumentList
|
||||||
def __init__(self, KCCAplication, KCCWindow):
|
def __init__(self, KCCAplication, KCCWindow):
|
||||||
global APP, MW, GUI
|
global APP, MW, GUI
|
||||||
@@ -986,16 +1077,10 @@ class KCCGUI(KCC_ui.Ui_KCC):
|
|||||||
MW = KCCWindow
|
MW = KCCWindow
|
||||||
GUI = self
|
GUI = self
|
||||||
self.setupUi(MW)
|
self.setupUi(MW)
|
||||||
# User settings will be reverted to default ones if were created in one of the following versions
|
|
||||||
# Empty string cover all versions before this system was implemented
|
|
||||||
purgeSettingsVersions = ['']
|
|
||||||
self.icons = Icons()
|
self.icons = Icons()
|
||||||
self.webContent = KCC_rc_web.WebContent()
|
self.webContent = KCC_rc_web.WebContent()
|
||||||
self.settings = QtCore.QSettings('KindleComicConverter', 'KindleComicConverter')
|
self.settings = QtCore.QSettings('KindleComicConverter', 'KindleComicConverter')
|
||||||
self.settingsVersion = self.settings.value('settingsVersion', '', type=str)
|
self.settingsVersion = self.settings.value('settingsVersion', '', type=str)
|
||||||
if self.settingsVersion in purgeSettingsVersions:
|
|
||||||
QtCore.QSettings.clear(self.settings)
|
|
||||||
self.settingsVersion = self.settings.value('settingsVersion', '', type=str)
|
|
||||||
self.lastPath = self.settings.value('lastPath', '', type=str)
|
self.lastPath = self.settings.value('lastPath', '', type=str)
|
||||||
self.lastDevice = self.settings.value('lastDevice', 0, type=int)
|
self.lastDevice = self.settings.value('lastDevice', 0, type=int)
|
||||||
self.currentMode = self.settings.value('currentMode', 1, type=int)
|
self.currentMode = self.settings.value('currentMode', 1, type=int)
|
||||||
@@ -1009,6 +1094,7 @@ class KCCGUI(KCC_ui.Ui_KCC):
|
|||||||
self.tray = SystemTrayIcon()
|
self.tray = SystemTrayIcon()
|
||||||
self.conversionAlive = False
|
self.conversionAlive = False
|
||||||
self.needClean = True
|
self.needClean = True
|
||||||
|
self.KindleGen = False
|
||||||
self.GammaValue = 1.0
|
self.GammaValue = 1.0
|
||||||
self.completedWork = {}
|
self.completedWork = {}
|
||||||
self.targetDirectory = ''
|
self.targetDirectory = ''
|
||||||
@@ -1016,11 +1102,13 @@ class KCCGUI(KCC_ui.Ui_KCC):
|
|||||||
self.listFontSize = 11
|
self.listFontSize = 11
|
||||||
self.statusBarFontSize = 10
|
self.statusBarFontSize = 10
|
||||||
self.statusBarStyle = 'QLabel{padding-top:2px;padding-bottom:3px;}'
|
self.statusBarStyle = 'QLabel{padding-top:2px;padding-bottom:3px;}'
|
||||||
self.ProgressBar.setStyleSheet('QProgressBar{padding-top:5px;text-align:center;}')
|
self.ProgressBar.setStyleSheet('QProgressBar{font-size:13px;text-align:center;'
|
||||||
|
'border:2px solid grey;border-radius:5px;}'
|
||||||
|
'QProgressBar::chunk{background-color:steelblue;width:20px;}')
|
||||||
elif sys.platform.startswith('linux'):
|
elif sys.platform.startswith('linux'):
|
||||||
self.listFontSize = 8
|
self.listFontSize = 8
|
||||||
self.statusBarFontSize = 8
|
self.statusBarFontSize = 8
|
||||||
self.statusBarStyle = 'QLabel{padding-top:5px;padding-bottom:3px;}'
|
self.statusBarStyle = 'QLabel{padding-top:3px;padding-bottom:3px;}'
|
||||||
self.statusBar.setStyleSheet('QStatusBar::item{border:0px;border-top:2px solid #C2C7CB;}')
|
self.statusBar.setStyleSheet('QStatusBar::item{border:0px;border-top:2px solid #C2C7CB;}')
|
||||||
else:
|
else:
|
||||||
self.listFontSize = 9
|
self.listFontSize = 9
|
||||||
@@ -1108,27 +1196,6 @@ class KCCGUI(KCC_ui.Ui_KCC):
|
|||||||
self.addMessage('Since you are new user of <b>KCC</b> please see few '
|
self.addMessage('Since you are new user of <b>KCC</b> please see few '
|
||||||
'<a href="https://github.com/ciromattia/kcc/wiki/Important-tips">important tips</a>.',
|
'<a href="https://github.com/ciromattia/kcc/wiki/Important-tips">important tips</a>.',
|
||||||
'info')
|
'info')
|
||||||
if not sys.platform.startswith('win'):
|
|
||||||
try:
|
|
||||||
os.chmod('/usr/local/bin/kindlegen', 0o755)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
kindleGenExitCode = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, shell=True)
|
|
||||||
if kindleGenExitCode.wait() == 0:
|
|
||||||
self.KindleGen = True
|
|
||||||
versionCheck = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, shell=True)
|
|
||||||
for line in versionCheck.stdout:
|
|
||||||
line = line.decode("utf-8")
|
|
||||||
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 <a href="http://www.amazon.com/gp/feature.html?ie=UTF8&docId='
|
|
||||||
'1000765211">kindlegen</a> is outdated! Creating MOBI might fail.'
|
|
||||||
' Please update <a href="http://www.amazon.com/gp/feature.html?ie=UTF8&docId='
|
|
||||||
'1000765211">kindlegen</a> from Amazon\'s website.', 'warning')
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
self.KindleGen = False
|
|
||||||
rarExitCode = Popen('unrar', stdout=PIPE, stderr=STDOUT, shell=True)
|
rarExitCode = Popen('unrar', stdout=PIPE, stderr=STDOUT, shell=True)
|
||||||
rarExitCode = rarExitCode.wait()
|
rarExitCode = rarExitCode.wait()
|
||||||
if rarExitCode == 0 or rarExitCode == 7:
|
if rarExitCode == 0 or rarExitCode == 7:
|
||||||
@@ -1145,6 +1212,7 @@ class KCCGUI(KCC_ui.Ui_KCC):
|
|||||||
self.sevenza = False
|
self.sevenza = False
|
||||||
self.addMessage('Cannot find <a href="http://www.7-zip.org/download.html">7za</a>!'
|
self.addMessage('Cannot find <a href="http://www.7-zip.org/download.html">7za</a>!'
|
||||||
' Processing of CB7/7Z files will be disabled.', 'warning')
|
' Processing of CB7/7Z files will be disabled.', 'warning')
|
||||||
|
self.detectKindleGen(True)
|
||||||
|
|
||||||
APP.messageFromOtherInstance.connect(self.handleMessage)
|
APP.messageFromOtherInstance.connect(self.handleMessage)
|
||||||
GUI.BasicModeButton.clicked.connect(self.modeBasic)
|
GUI.BasicModeButton.clicked.connect(self.modeBasic)
|
||||||
@@ -1166,7 +1234,6 @@ class KCCGUI(KCC_ui.Ui_KCC):
|
|||||||
MW.showDialog.connect(self.showDialog)
|
MW.showDialog.connect(self.showDialog)
|
||||||
MW.hideProgressBar.connect(self.hideProgressBar)
|
MW.hideProgressBar.connect(self.hideProgressBar)
|
||||||
MW.forceShutdown.connect(self.forceShutdown)
|
MW.forceShutdown.connect(self.forceShutdown)
|
||||||
MW.dialogAnswer.connect(self.versionCheck.getNewVersion)
|
|
||||||
MW.closeEvent = self.saveSettings
|
MW.closeEvent = self.saveSettings
|
||||||
MW.addTrayMessage.connect(self.tray.addTrayMessage)
|
MW.addTrayMessage.connect(self.tray.addTrayMessage)
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
# Form implementation generated from reading ui file 'KCC.ui'
|
# Form implementation generated from reading ui file 'KCC.ui'
|
||||||
#
|
#
|
||||||
# Created: Sun May 18 09:08:27 2014
|
# Created: Sun Jan 4 09:58:25 2015
|
||||||
# by: PyQt5 UI code generator 5.2.1
|
# by: PyQt5 UI code generator 5.4
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
|
||||||
@@ -139,6 +139,7 @@ class Ui_KCC(object):
|
|||||||
self.JobList.setGeometry(QtCore.QRect(10, 50, 401, 101))
|
self.JobList.setGeometry(QtCore.QRect(10, 50, 401, 101))
|
||||||
self.JobList.setFocusPolicy(QtCore.Qt.NoFocus)
|
self.JobList.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
self.JobList.setStyleSheet("QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}")
|
self.JobList.setStyleSheet("QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}")
|
||||||
|
self.JobList.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
|
||||||
self.JobList.setProperty("showDropIndicator", False)
|
self.JobList.setProperty("showDropIndicator", False)
|
||||||
self.JobList.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
|
self.JobList.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
|
||||||
self.JobList.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel)
|
self.JobList.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel)
|
||||||
@@ -260,28 +261,30 @@ class Ui_KCC(object):
|
|||||||
def retranslateUi(self, KCC):
|
def retranslateUi(self, KCC):
|
||||||
_translate = QtCore.QCoreApplication.translate
|
_translate = QtCore.QCoreApplication.translate
|
||||||
KCC.setWindowTitle(_translate("KCC", "Kindle Comic Converter"))
|
KCC.setWindowTitle(_translate("KCC", "Kindle Comic Converter"))
|
||||||
self.ProcessingBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Disable image optimizations.<br/>Input images must be already resized.</p></body></html>"))
|
self.ProcessingBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Disable image optimizations.<br/><span style=\" font-weight:600;\">Input images must be already resized.</span></p></body></html>"))
|
||||||
self.ProcessingBox.setText(_translate("KCC", "No optimisation"))
|
self.ProcessingBox.setText(_translate("KCC", "No optimisation"))
|
||||||
self.UpscaleBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Nothing<br/></span>Images smaller than device resolution will not be resized.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - Stretching<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be not preserved.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Upscaling<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be preserved.</p></body></html>"))
|
self.UpscaleBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Nothing<br/></span>Images smaller than device resolution will not be resized.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - Stretching<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be not preserved.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Upscaling<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be preserved.</p></body></html>"))
|
||||||
self.UpscaleBox.setText(_translate("KCC", "Stretch/Upscale"))
|
self.UpscaleBox.setText(_translate("KCC", "Stretch/Upscale"))
|
||||||
self.WebtoonBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\"white-space:pre\">Enable auto-splitting of webtoons like <span style=\" font-style:italic;\">Tower of God</span> or <span style=\" font-style:italic;\">Noblesse</span>.<br/>This mode is created for pages with a low width, high height and vertical panel flow.</p></body></html>"))
|
self.WebtoonBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Enable special parsing mode for WebToons.</p></body></html>"))
|
||||||
self.WebtoonBox.setText(_translate("KCC", "Webtoon mode"))
|
self.WebtoonBox.setText(_translate("KCC", "Webtoon mode"))
|
||||||
self.NoDitheringBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Create PNG files instead JPEG.<br/>Quality increase is not noticeable on most of devices.<br/>Output files <span style=\" font-weight:600;\">might</span> be smaller.<br/><span style=\" font-weight:600;\">MOBI conversion will be much slower.</span></p></body></html>"))
|
self.NoDitheringBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Create PNG files instead JPEG.<br/>Quality increase is not noticeable on most of devices.<br/>Output files <span style=\" font-weight:600;\">might</span> be smaller.<br/><span style=\" font-weight:600;\">MOBI conversion will be much slower.</span></p></body></html>"))
|
||||||
self.NoDitheringBox.setText(_translate("KCC", "PNG output"))
|
self.NoDitheringBox.setText(_translate("KCC", "PNG output"))
|
||||||
self.BorderBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Autodetection<br/></span>Color of margins fill will be detected automatically.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - White<br/></span>Margins will be filled with white color.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Black<br/></span>Margins will be filled with black color.</p></body></html>"))
|
self.BorderBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Autodetection<br/></span>Color of margins fill will be detected automatically.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - White<br/></span>Margins will be filled with white color.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Black<br/></span>Margins will be filled with black color.</p></body></html>"))
|
||||||
self.BorderBox.setText(_translate("KCC", "W/B margins"))
|
self.BorderBox.setText(_translate("KCC", "W/B margins"))
|
||||||
self.NoRotateBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Disable splitting and rotation.</p></body></html>"))
|
self.NoRotateBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Disable page splitting and rotation.</p></body></html>"))
|
||||||
self.NoRotateBox.setText(_translate("KCC", "No split/rotate"))
|
self.NoRotateBox.setText(_translate("KCC", "No split/rotate"))
|
||||||
self.DeviceBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Target device.</p></body></html>"))
|
self.DeviceBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Target device.</p></body></html>"))
|
||||||
self.FormatBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Output format.</p></body></html>"))
|
self.FormatBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Output format.</p></body></html>"))
|
||||||
self.ConvertButton.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Shift+Click to select the output directory.</p></body></html>"))
|
self.ConvertButton.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Shift+Click to select the output directory.</p></body></html>"))
|
||||||
self.ConvertButton.setText(_translate("KCC", "Convert"))
|
self.ConvertButton.setText(_translate("KCC", "Convert"))
|
||||||
|
self.DirectoryButton.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Add directory containing JPG, PNG or GIF files to queue.<br/><span style=\" font-weight:600;\">CBR, CBZ and CB7 files inside will not be processed!</span></p></body></html>"))
|
||||||
self.DirectoryButton.setText(_translate("KCC", "Add directory"))
|
self.DirectoryButton.setText(_translate("KCC", "Add directory"))
|
||||||
|
self.FileButton.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Add CBR, CBZ, CB7 or PDF file to queue.</p></body></html>"))
|
||||||
self.FileButton.setText(_translate("KCC", "Add file"))
|
self.FileButton.setText(_translate("KCC", "Add file"))
|
||||||
self.ClearButton.setText(_translate("KCC", "Clear list"))
|
self.ClearButton.setText(_translate("KCC", "Clear list"))
|
||||||
self.MangaBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Enable right-to-left reading.</p></body></html>"))
|
self.MangaBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Enable right-to-left reading.</p></body></html>"))
|
||||||
self.MangaBox.setText(_translate("KCC", "Manga mode"))
|
self.MangaBox.setText(_translate("KCC", "Manga mode"))
|
||||||
self.QualityBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\"white-space:pre\"><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Normal quality mode<br/></span>Maximal quality of images but very poor magnification quality.<br/>Use it only when zoom is not needed or output files needs to be small.</p><p style=\"white-space:pre\"><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - High quality mode<br/></span>In most cases high quality of images and magnification.<br/>Overall quality highly depends on the resolution of source files.<br/>On Kindle models older than Paperwhite non-zoomed images might be a little blurred.</p><p style=\"white-space:pre\"><span style=\" font-weight:600; text-decoration: underline;\">Checked - Ultra quality mode<br/></span>Highest possible quality. Output files will be big.</p></body></html>"))
|
self.QualityBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Quality of Panel View/zoom. Highly impact size of output file.<br/><span style=\" font-weight:600;\">This option control only quality of magnification!</span></p></body></html>"))
|
||||||
self.QualityBox.setText(_translate("KCC", "High/Ultra quality"))
|
self.QualityBox.setText(_translate("KCC", "High/Ultra quality"))
|
||||||
self.RotateBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Disable splitting of two-page spreads.<br/>They will be rotated instead.</p></body></html>"))
|
self.RotateBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Disable splitting of two-page spreads.<br/>They will be rotated instead.</p></body></html>"))
|
||||||
self.RotateBox.setText(_translate("KCC", "Horizontal mode"))
|
self.RotateBox.setText(_translate("KCC", "Horizontal mode"))
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
# Form implementation generated from reading ui file 'KCC-Linux.ui'
|
# Form implementation generated from reading ui file 'KCC-Linux.ui'
|
||||||
#
|
#
|
||||||
# Created: Sun May 18 09:08:37 2014
|
# Created: Sun Jan 4 10:06:14 2015
|
||||||
# by: PyQt5 UI code generator 5.2.1
|
# by: PyQt5 UI code generator 5.4
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
|
||||||
@@ -179,6 +179,7 @@ class Ui_KCC(object):
|
|||||||
self.JobList.setFont(font)
|
self.JobList.setFont(font)
|
||||||
self.JobList.setFocusPolicy(QtCore.Qt.NoFocus)
|
self.JobList.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
self.JobList.setStyleSheet("QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}")
|
self.JobList.setStyleSheet("QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}")
|
||||||
|
self.JobList.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
|
||||||
self.JobList.setProperty("showDropIndicator", False)
|
self.JobList.setProperty("showDropIndicator", False)
|
||||||
self.JobList.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
|
self.JobList.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
|
||||||
self.JobList.setIconSize(QtCore.QSize(18, 18))
|
self.JobList.setIconSize(QtCore.QSize(18, 18))
|
||||||
@@ -329,28 +330,30 @@ class Ui_KCC(object):
|
|||||||
def retranslateUi(self, KCC):
|
def retranslateUi(self, KCC):
|
||||||
_translate = QtCore.QCoreApplication.translate
|
_translate = QtCore.QCoreApplication.translate
|
||||||
KCC.setWindowTitle(_translate("KCC", "Kindle Comic Converter"))
|
KCC.setWindowTitle(_translate("KCC", "Kindle Comic Converter"))
|
||||||
self.ProcessingBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Disable image optimizations.<br/>Input images must be already resized.</p></body></html>"))
|
self.ProcessingBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Disable image optimizations.<br/><span style=\" font-weight:600;\">Input images must be already resized.</span></p></body></html>"))
|
||||||
self.ProcessingBox.setText(_translate("KCC", "No optimisation"))
|
self.ProcessingBox.setText(_translate("KCC", "No optimisation"))
|
||||||
self.UpscaleBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Nothing<br/></span>Images smaller than device resolution will not be resized.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - Stretching<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be not preserved.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Upscaling<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be preserved.</p></body></html>"))
|
self.UpscaleBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Nothing<br/></span>Images smaller than device resolution will not be resized.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - Stretching<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be not preserved.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Upscaling<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be preserved.</p></body></html>"))
|
||||||
self.UpscaleBox.setText(_translate("KCC", "Stretch/Upscale"))
|
self.UpscaleBox.setText(_translate("KCC", "Stretch/Upscale"))
|
||||||
self.WebtoonBox.setToolTip(_translate("KCC", "<html><head/><body><p>Enable auto-splitting of webtoons like <span style=\" font-style:italic;\">Tower of God</span> or <span style=\" font-style:italic;\">Noblesse</span>.<br/>This mode was created for pages with a low width, high height and vertical panel flow.</p></body></html>"))
|
self.WebtoonBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Enable special parsing mode for WebToons.</p></body></html>"))
|
||||||
self.WebtoonBox.setText(_translate("KCC", "Webtoon mode"))
|
self.WebtoonBox.setText(_translate("KCC", "Webtoon mode"))
|
||||||
self.NoDitheringBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Create PNG files instead JPEG.<br/>Quality increase is not noticeable on most of devices.<br/>Output files <span style=\" font-weight:600;\">might</span> be smaller.<br/><span style=\" font-weight:600;\">MOBI conversion will be much slower.</span></p></body></html>"))
|
self.NoDitheringBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Create PNG files instead JPEG.<br/>Quality increase is not noticeable on most of devices.<br/>Output files <span style=\" font-weight:600;\">might</span> be smaller.<br/><span style=\" font-weight:600;\">MOBI conversion will be much slower.</span></p></body></html>"))
|
||||||
self.NoDitheringBox.setText(_translate("KCC", "PNG output"))
|
self.NoDitheringBox.setText(_translate("KCC", "PNG output"))
|
||||||
self.BorderBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Autodetection<br/></span>Color of margins fill will be detected automatically.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - White<br/></span>Margins will be filled with white color.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Black<br/></span>Margins will be filled with black color.</p></body></html>"))
|
self.BorderBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Autodetection<br/></span>Color of margins fill will be detected automatically.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - White<br/></span>Margins will be filled with white color.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Black<br/></span>Margins will be filled with black color.</p></body></html>"))
|
||||||
self.BorderBox.setText(_translate("KCC", "W/B margins"))
|
self.BorderBox.setText(_translate("KCC", "W/B margins"))
|
||||||
self.NoRotateBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Disable splitting and rotation.</p></body></html>"))
|
self.NoRotateBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Disable page splitting and rotation.</p></body></html>"))
|
||||||
self.NoRotateBox.setText(_translate("KCC", "No split/rotate"))
|
self.NoRotateBox.setText(_translate("KCC", "No split/rotate"))
|
||||||
self.DeviceBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Target device.</p></body></html>"))
|
self.DeviceBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Target device.</p></body></html>"))
|
||||||
self.FormatBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Output format.</p></body></html>"))
|
self.FormatBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Output format.</p></body></html>"))
|
||||||
self.ConvertButton.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Shift+Click to select the output directory.</p></body></html>"))
|
self.ConvertButton.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Shift+Click to select the output directory.</p></body></html>"))
|
||||||
self.ConvertButton.setText(_translate("KCC", "Convert"))
|
self.ConvertButton.setText(_translate("KCC", "Convert"))
|
||||||
|
self.DirectoryButton.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Add directory containing JPG, PNG or GIF files to queue.<br/><span style=\" font-weight:600;\">CBR, CBZ and CB7 files inside will not be processed!</span></p></body></html>"))
|
||||||
self.DirectoryButton.setText(_translate("KCC", "Add directory"))
|
self.DirectoryButton.setText(_translate("KCC", "Add directory"))
|
||||||
|
self.FileButton.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Add CBR, CBZ, CB7 or PDF file to queue.</p></body></html>"))
|
||||||
self.FileButton.setText(_translate("KCC", "Add file"))
|
self.FileButton.setText(_translate("KCC", "Add file"))
|
||||||
self.ClearButton.setText(_translate("KCC", "Clear list"))
|
self.ClearButton.setText(_translate("KCC", "Clear list"))
|
||||||
self.MangaBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Enable right-to-left reading.</p></body></html>"))
|
self.MangaBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Enable right-to-left reading.</p></body></html>"))
|
||||||
self.MangaBox.setText(_translate("KCC", "Manga mode"))
|
self.MangaBox.setText(_translate("KCC", "Manga mode"))
|
||||||
self.QualityBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Normal quality mode</span><br/>Maximal quality of images but very poor magnification quality.<br/>Use it only when zoom is not needed or output files needs to be small.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - High quality mode</span><br/>In most cases high quality of images and magnification.<br/>Overall quality highly depends on the resolution of source files.<br/>On Kindle models older than Paperwhite non-zoomed images might be a little blurred.<br/><br/><span style=\" font-weight:600; text-decoration: underline;\">Checked - Ultra quality mode</span><br/>Highest possible quality. Output files will be big.</p></body></html>"))
|
self.QualityBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Quality of Panel View/zoom. Highly impact size of output file.<br/><span style=\" font-weight:600;\">This option control only quality of magnification!</span></p></body></html>"))
|
||||||
self.QualityBox.setText(_translate("KCC", "High/Ultra quality"))
|
self.QualityBox.setText(_translate("KCC", "High/Ultra quality"))
|
||||||
self.RotateBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Disable splitting of two-page spreads.<br/>They will be rotated instead.</p></body></html>"))
|
self.RotateBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Disable splitting of two-page spreads.<br/>They will be rotated instead.</p></body></html>"))
|
||||||
self.RotateBox.setText(_translate("KCC", "Horizontal mode"))
|
self.RotateBox.setText(_translate("KCC", "Horizontal mode"))
|
||||||
@@ -359,13 +362,13 @@ class Ui_KCC(object):
|
|||||||
self.GammaLabel.setText(_translate("KCC", "Gamma: Auto"))
|
self.GammaLabel.setText(_translate("KCC", "Gamma: Auto"))
|
||||||
self.ColorBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Don\'t convert images to grayscale.</p></body></html>"))
|
self.ColorBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Don\'t convert images to grayscale.</p></body></html>"))
|
||||||
self.ColorBox.setText(_translate("KCC", "Color mode"))
|
self.ColorBox.setText(_translate("KCC", "Color mode"))
|
||||||
self.wLabel.setToolTip(_translate("KCC", "<html><head/><body><p>Resolution of target device.</p></body></html>"))
|
self.wLabel.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Resolution of target device.</p></body></html>"))
|
||||||
self.wLabel.setText(_translate("KCC", "Custom width: "))
|
self.wLabel.setText(_translate("KCC", "Custom width: "))
|
||||||
self.customWidth.setToolTip(_translate("KCC", "<html><head/><body><p>Resolution of target device.</p></body></html>"))
|
self.customWidth.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Resolution of target device.</p></body></html>"))
|
||||||
self.customWidth.setInputMask(_translate("KCC", "0000"))
|
self.customWidth.setInputMask(_translate("KCC", "0000"))
|
||||||
self.hLabel.setToolTip(_translate("KCC", "<html><head/><body><p>Resolution of target device.</p></body></html>"))
|
self.hLabel.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Resolution of target device.</p></body></html>"))
|
||||||
self.hLabel.setText(_translate("KCC", "Custom height: "))
|
self.hLabel.setText(_translate("KCC", "Custom height: "))
|
||||||
self.customHeight.setToolTip(_translate("KCC", "<html><head/><body><p>Resolution of target device.</p></body></html>"))
|
self.customHeight.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Resolution of target device.</p></body></html>"))
|
||||||
self.customHeight.setInputMask(_translate("KCC", "0000"))
|
self.customHeight.setInputMask(_translate("KCC", "0000"))
|
||||||
self.ActionBasic.setText(_translate("KCC", "Basic"))
|
self.ActionBasic.setText(_translate("KCC", "Basic"))
|
||||||
self.ActionAdvanced.setText(_translate("KCC", "Advanced"))
|
self.ActionAdvanced.setText(_translate("KCC", "Advanced"))
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
# Form implementation generated from reading ui file 'KCC-OSX.ui'
|
# Form implementation generated from reading ui file 'KCC-OSX.ui'
|
||||||
#
|
#
|
||||||
# Created: Sun May 18 09:08:44 2014
|
# Created: Sun Jan 4 10:26:09 2015
|
||||||
# by: PyQt5 UI code generator 5.2.1
|
# by: PyQt5 UI code generator 5.4
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
|
||||||
@@ -186,6 +186,7 @@ class Ui_KCC(object):
|
|||||||
self.JobList.setFont(font)
|
self.JobList.setFont(font)
|
||||||
self.JobList.setFocusPolicy(QtCore.Qt.NoFocus)
|
self.JobList.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
self.JobList.setStyleSheet("QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}")
|
self.JobList.setStyleSheet("QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}")
|
||||||
|
self.JobList.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
|
||||||
self.JobList.setProperty("showDropIndicator", False)
|
self.JobList.setProperty("showDropIndicator", False)
|
||||||
self.JobList.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
|
self.JobList.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
|
||||||
self.JobList.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel)
|
self.JobList.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel)
|
||||||
@@ -352,28 +353,30 @@ class Ui_KCC(object):
|
|||||||
def retranslateUi(self, KCC):
|
def retranslateUi(self, KCC):
|
||||||
_translate = QtCore.QCoreApplication.translate
|
_translate = QtCore.QCoreApplication.translate
|
||||||
KCC.setWindowTitle(_translate("KCC", "Kindle Comic Converter"))
|
KCC.setWindowTitle(_translate("KCC", "Kindle Comic Converter"))
|
||||||
self.ProcessingBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Disable image optimizations.<br/>Input images must be already resized.</p></body></html>"))
|
self.ProcessingBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Disable image optimizations.<br/><span style=\" font-weight:600;\">Input images must be already resized.</span></p></body></html>"))
|
||||||
self.ProcessingBox.setText(_translate("KCC", "No optimisation"))
|
self.ProcessingBox.setText(_translate("KCC", "No optimisation"))
|
||||||
self.UpscaleBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Nothing<br/></span>Images smaller than device resolution will not be resized.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - Stretching<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be not preserved.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Upscaling<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be preserved.</p></body></html>"))
|
self.UpscaleBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Nothing<br/></span>Images smaller than device resolution will not be resized.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - Stretching<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be not preserved.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Upscaling<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be preserved.</p></body></html>"))
|
||||||
self.UpscaleBox.setText(_translate("KCC", "Stretch/Upscale"))
|
self.UpscaleBox.setText(_translate("KCC", "Stretch/Upscale"))
|
||||||
self.WebtoonBox.setToolTip(_translate("KCC", "<html><head/><body><p>Enable auto-splitting of webtoons like <span style=\" font-style:italic;\">Tower of God </span>or <span style=\" font-style:italic;\">Noblesse</span>.<br/>This mode was created for pages with a low width, high height and vertical panel flow.</p><p><br/></p></body></html>"))
|
self.WebtoonBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Enable special parsing mode for WebToons.</p></body></html>"))
|
||||||
self.WebtoonBox.setText(_translate("KCC", "Webtoon mode"))
|
self.WebtoonBox.setText(_translate("KCC", "Webtoon mode"))
|
||||||
self.NoDitheringBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Create PNG files instead JPEG.<br/>Quality increase is not noticeable on most of devices.<br/>Output files <span style=\" font-weight:600;\">might</span> be smaller.<br/><span style=\" font-weight:600;\">MOBI conversion will be much slower.</span></p></body></html>"))
|
self.NoDitheringBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Create PNG files instead JPEG.<br/>Quality increase is not noticeable on most of devices.<br/>Output files <span style=\" font-weight:600;\">might</span> be smaller.<br/><span style=\" font-weight:600;\">MOBI conversion will be much slower.</span></p></body></html>"))
|
||||||
self.NoDitheringBox.setText(_translate("KCC", "PNG output"))
|
self.NoDitheringBox.setText(_translate("KCC", "PNG output"))
|
||||||
self.BorderBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Autodetection<br/></span>Color of margins fill will be detected automatically.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - White<br/></span>Margins will be filled with white color.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Black<br/></span>Margins will be filled with black color.</p></body></html>"))
|
self.BorderBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Autodetection<br/></span>Color of margins fill will be detected automatically.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - White<br/></span>Margins will be filled with white color.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Black<br/></span>Margins will be filled with black color.</p></body></html>"))
|
||||||
self.BorderBox.setText(_translate("KCC", "W/B margins"))
|
self.BorderBox.setText(_translate("KCC", "W/B margins"))
|
||||||
self.NoRotateBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Disable splitting and rotation.</p></body></html>"))
|
self.NoRotateBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Disable page splitting and rotation.</p></body></html>"))
|
||||||
self.NoRotateBox.setText(_translate("KCC", "No split/rotate"))
|
self.NoRotateBox.setText(_translate("KCC", "No split/rotate"))
|
||||||
self.DeviceBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Target device.</p></body></html>"))
|
self.DeviceBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Target device.</p></body></html>"))
|
||||||
self.FormatBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Output format.</p></body></html>"))
|
self.FormatBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Output format.</p></body></html>"))
|
||||||
self.ConvertButton.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Shift+Click to select the output directory.</p></body></html>"))
|
self.ConvertButton.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Shift+Click to select the output directory.</p></body></html>"))
|
||||||
self.ConvertButton.setText(_translate("KCC", "Convert"))
|
self.ConvertButton.setText(_translate("KCC", "Convert"))
|
||||||
|
self.DirectoryButton.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Add directory containing JPG, PNG or GIF files to queue.<br/><span style=\" font-weight:600;\">CBR, CBZ and CB7 files inside will not be processed!</span></p></body></html>"))
|
||||||
self.DirectoryButton.setText(_translate("KCC", "Add directory"))
|
self.DirectoryButton.setText(_translate("KCC", "Add directory"))
|
||||||
|
self.FileButton.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Add CBR, CBZ, CB7 or PDF file to queue.</p></body></html>"))
|
||||||
self.FileButton.setText(_translate("KCC", "Add file"))
|
self.FileButton.setText(_translate("KCC", "Add file"))
|
||||||
self.ClearButton.setText(_translate("KCC", "Clear list"))
|
self.ClearButton.setText(_translate("KCC", "Clear list"))
|
||||||
self.MangaBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Enable right-to-left reading.</p></body></html>"))
|
self.MangaBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Enable right-to-left reading.</p></body></html>"))
|
||||||
self.MangaBox.setText(_translate("KCC", "Manga mode"))
|
self.MangaBox.setText(_translate("KCC", "Manga mode"))
|
||||||
self.QualityBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Normal quality mode</span><br/>Maximal quality of images but very poor magnification quality.<br/>Use it only when zoom is not needed or output files needs to be small.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - High quality mode</span><br/>In most cases high quality of images and magnification.<br/>Overall quality highly depends on the resolution of source files.<br/>On Kindle models older than Paperwhite non-zoomed images might be a little blurred.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Ultra quality mode</span><br/>Highest possible quality. Output files will be big.</p></body></html>"))
|
self.QualityBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Quality of Panel View/zoom. Highly impact size of output file.<br/><span style=\" font-weight:600;\">This option control only quality of magnification!</span></p></body></html>"))
|
||||||
self.QualityBox.setText(_translate("KCC", "High/Ultra quality"))
|
self.QualityBox.setText(_translate("KCC", "High/Ultra quality"))
|
||||||
self.RotateBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Disable splitting of two-page spreads.<br/>They will be rotated instead.</p></body></html>"))
|
self.RotateBox.setToolTip(_translate("KCC", "<html><head/><body><p style=\'white-space:pre\'>Disable splitting of two-page spreads.<br/>They will be rotated instead.</p></body></html>"))
|
||||||
self.RotateBox.setText(_translate("KCC", "Horizontal mode"))
|
self.RotateBox.setText(_translate("KCC", "Horizontal mode"))
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
__version__ = '4.3'
|
__version__ = '4.4.1'
|
||||||
__license__ = 'ISC'
|
__license__ = 'ISC'
|
||||||
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
|
__copyright__ = '2012-2015, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
# Copyright (c) 2013-2014 Pawel Jastrzebski <pawelj@iosphe.re>
|
# Copyright (c) 2013-2015 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, and/or distribute this software for
|
# Permission to use, copy, modify, and/or distribute this software for
|
||||||
# any purpose with or without fee is hereby granted, provided that the
|
# any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
__license__ = 'ISC'
|
__license__ = 'ISC'
|
||||||
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
|
__copyright__ = '2012-2015, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
@@ -27,6 +27,7 @@ from subprocess import STDOUT, PIPE
|
|||||||
from psutil import Popen
|
from psutil import Popen
|
||||||
from shutil import move, copy
|
from shutil import move, copy
|
||||||
from . import rarfile
|
from . import rarfile
|
||||||
|
from .shared import check7ZFile as is_7zfile
|
||||||
|
|
||||||
|
|
||||||
class CBxArchive:
|
class CBxArchive:
|
||||||
@@ -36,7 +37,7 @@ class CBxArchive:
|
|||||||
self.compressor = 'zip'
|
self.compressor = 'zip'
|
||||||
elif rarfile.is_rarfile(origFileName):
|
elif rarfile.is_rarfile(origFileName):
|
||||||
self.compressor = 'rar'
|
self.compressor = 'rar'
|
||||||
elif origFileName.endswith('.7z') or origFileName.endswith('.cb7'):
|
elif is_7zfile(origFileName):
|
||||||
self.compressor = '7z'
|
self.compressor = '7z'
|
||||||
else:
|
else:
|
||||||
self.compressor = None
|
self.compressor = None
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
# Copyright (c) 2013-2014 Pawel Jastrzebski <pawelj@iosphe.re>
|
# Copyright (c) 2013-2015 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, and/or distribute this software for
|
# Permission to use, copy, modify, and/or distribute this software for
|
||||||
# any purpose with or without fee is hereby granted, provided that the
|
# any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -18,16 +18,18 @@
|
|||||||
# PERFORMANCE OF THIS SOFTWARE.
|
# PERFORMANCE OF THIS SOFTWARE.
|
||||||
#
|
#
|
||||||
|
|
||||||
__version__ = '4.3'
|
__version__ = '4.4.1'
|
||||||
__license__ = 'ISC'
|
__license__ = 'ISC'
|
||||||
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
|
__copyright__ = '2012-2015, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
from copy import copy
|
||||||
|
from glob import glob
|
||||||
from json import loads
|
from json import loads
|
||||||
from urllib.request import Request, urlopen
|
from urllib.request import Request, urlopen
|
||||||
from re import split, sub, compile
|
from re import split, sub
|
||||||
from stat import S_IWRITE, S_IREAD, S_IEXEC
|
from stat import S_IWRITE, S_IREAD, S_IEXEC
|
||||||
from zipfile import ZipFile, ZIP_STORED, ZIP_DEFLATED
|
from zipfile import ZipFile, ZIP_STORED, ZIP_DEFLATED
|
||||||
from tempfile import mkdtemp
|
from tempfile import mkdtemp
|
||||||
@@ -55,12 +57,21 @@ from . import dualmetafix
|
|||||||
def main(argv=None):
|
def main(argv=None):
|
||||||
global options
|
global options
|
||||||
parser = makeParser()
|
parser = makeParser()
|
||||||
options, args = parser.parse_args(argv)
|
optionstemplate, args = parser.parse_args(argv)
|
||||||
checkOptions()
|
if len(args) == 0:
|
||||||
if len(args) != 1:
|
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
return
|
return
|
||||||
outputPath = makeBook(args[0])
|
sources = set([source for arg in args for source in glob(arg)])
|
||||||
|
outputPath = []
|
||||||
|
if len(sources) == 0:
|
||||||
|
print('No matching files found.')
|
||||||
|
return
|
||||||
|
for source in sources:
|
||||||
|
options = copy(optionstemplate)
|
||||||
|
checkOptions()
|
||||||
|
if len(sources) > 1:
|
||||||
|
print('\nWorking on ' + source)
|
||||||
|
outputPath = makeBook(source)
|
||||||
return outputPath
|
return outputPath
|
||||||
|
|
||||||
|
|
||||||
@@ -409,7 +420,7 @@ def buildEPUB(path, chapterNames, tomeNumber):
|
|||||||
chapter = False
|
chapter = False
|
||||||
for afile in filenames:
|
for afile in filenames:
|
||||||
filename = getImageFileName(afile)
|
filename = getImageFileName(afile)
|
||||||
if not '-kcc-hq' in filename[0]:
|
if '-kcc-hq' not in filename[0]:
|
||||||
filelist.append(buildHTML(dirpath, afile, os.path.join(dirpath, afile)))
|
filelist.append(buildHTML(dirpath, afile, os.path.join(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]))
|
||||||
@@ -433,12 +444,12 @@ def imgOptimization(img, opt, hqImage=None):
|
|||||||
img.cropWhiteSpace()
|
img.cropWhiteSpace()
|
||||||
if opt.cutpagenumbers and not opt.webtoon:
|
if opt.cutpagenumbers and not opt.webtoon:
|
||||||
img.cutPageNumber()
|
img.cutPageNumber()
|
||||||
img.optimizeImage(opt.gamma)
|
img.optimizeImage()
|
||||||
if hqImage:
|
if hqImage:
|
||||||
img.resizeImage(opt.upscale, opt.stretch, opt.bordersColor, 0)
|
img.resizeImage(0)
|
||||||
img.calculateBorder(hqImage, True)
|
img.calculateBorder(hqImage, True)
|
||||||
else:
|
else:
|
||||||
img.resizeImage(opt.upscale, opt.stretch, opt.bordersColor, opt.quality)
|
img.resizeImage()
|
||||||
if opt.panelview:
|
if opt.panelview:
|
||||||
if opt.quality == 0:
|
if opt.quality == 0:
|
||||||
img.calculateBorder(img)
|
img.calculateBorder(img)
|
||||||
@@ -504,7 +515,7 @@ def imgFileProcessing(work):
|
|||||||
dirpath = work[1]
|
dirpath = work[1]
|
||||||
opt = work[2]
|
opt = work[2]
|
||||||
output = []
|
output = []
|
||||||
img = image.ComicPage(os.path.join(dirpath, afile), opt.profileData)
|
img = image.ComicPage(os.path.join(dirpath, afile), opt)
|
||||||
if opt.quality == 2:
|
if opt.quality == 2:
|
||||||
wipe = False
|
wipe = False
|
||||||
else:
|
else:
|
||||||
@@ -512,39 +523,39 @@ def imgFileProcessing(work):
|
|||||||
if opt.nosplitrotate:
|
if opt.nosplitrotate:
|
||||||
splitter = None
|
splitter = None
|
||||||
else:
|
else:
|
||||||
splitter = img.splitPage(dirpath, opt.righttoleft, opt.rotate)
|
splitter = img.splitPage(dirpath)
|
||||||
if splitter is not None:
|
if splitter is not None:
|
||||||
img0 = image.ComicPage(splitter[0], opt.profileData)
|
img0 = image.ComicPage(splitter[0], opt)
|
||||||
imgOptimization(img0, opt)
|
imgOptimization(img0, opt)
|
||||||
output.append(img0.saveToDir(dirpath, opt.forcepng, opt.forcecolor))
|
output.append(img0.saveToDir(dirpath))
|
||||||
img1 = image.ComicPage(splitter[1], opt.profileData)
|
img1 = image.ComicPage(splitter[1], opt)
|
||||||
imgOptimization(img1, opt)
|
imgOptimization(img1, opt)
|
||||||
output.append(img1.saveToDir(dirpath, opt.forcepng, opt.forcecolor))
|
output.append(img1.saveToDir(dirpath))
|
||||||
if wipe:
|
if wipe:
|
||||||
output.append(img0.origFileName)
|
output.append(img0.origFileName)
|
||||||
output.append(img1.origFileName)
|
output.append(img1.origFileName)
|
||||||
if opt.quality == 2:
|
if opt.quality == 2:
|
||||||
img0b = image.ComicPage(splitter[0], opt.profileData, img0.fill)
|
img0b = image.ComicPage(splitter[0], opt, img0.fill)
|
||||||
imgOptimization(img0b, opt, img0)
|
imgOptimization(img0b, opt, img0)
|
||||||
output.append(img0b.saveToDir(dirpath, opt.forcepng, opt.forcecolor))
|
output.append(img0b.saveToDir(dirpath))
|
||||||
img1b = image.ComicPage(splitter[1], opt.profileData, img1.fill)
|
img1b = image.ComicPage(splitter[1], opt, img1.fill)
|
||||||
imgOptimization(img1b, opt, img1)
|
imgOptimization(img1b, opt, img1)
|
||||||
output.append(img1b.saveToDir(dirpath, opt.forcepng, opt.forcecolor))
|
output.append(img1b.saveToDir(dirpath))
|
||||||
output.append(img0.origFileName)
|
output.append(img0.origFileName)
|
||||||
output.append(img1.origFileName)
|
output.append(img1.origFileName)
|
||||||
output.append(img.origFileName)
|
output.append(img.origFileName)
|
||||||
else:
|
else:
|
||||||
imgOptimization(img, opt)
|
imgOptimization(img, opt)
|
||||||
output.append(img.saveToDir(dirpath, opt.forcepng, opt.forcecolor))
|
output.append(img.saveToDir(dirpath))
|
||||||
if wipe:
|
if wipe:
|
||||||
output.append(img.origFileName)
|
output.append(img.origFileName)
|
||||||
if opt.quality == 2:
|
if opt.quality == 2:
|
||||||
img2 = image.ComicPage(os.path.join(dirpath, afile), opt.profileData, img.fill)
|
img2 = image.ComicPage(os.path.join(dirpath, afile), opt, img.fill)
|
||||||
if img.rotated:
|
if img.rotated:
|
||||||
img2.image = img2.image.rotate(90)
|
img2.image = img2.image.rotate(90, Image.BICUBIC, True)
|
||||||
img2.rotated = True
|
img2.rotated = True
|
||||||
imgOptimization(img2, opt, img)
|
imgOptimization(img2, opt, img)
|
||||||
output.append(img2.saveToDir(dirpath, opt.forcepng, opt.forcecolor))
|
output.append(img2.saveToDir(dirpath))
|
||||||
output.append(img.origFileName)
|
output.append(img.origFileName)
|
||||||
return output
|
return output
|
||||||
except Exception:
|
except Exception:
|
||||||
@@ -667,11 +678,12 @@ def getComicInfo(path, originalPath):
|
|||||||
options.authors.sort()
|
options.authors.sort()
|
||||||
else:
|
else:
|
||||||
options.authors = ['KCC']
|
options.authors = ['KCC']
|
||||||
if len(xml.getElementsByTagName('ScanInformation')) != 0:
|
# Disabled due to closure of MCD
|
||||||
coverId = xml.getElementsByTagName('ScanInformation')[0].firstChild.nodeValue
|
# if len(xml.getElementsByTagName('ScanInformation')) != 0:
|
||||||
coverId = compile('(MCD\\()(\\d+)(\\))').search(coverId)
|
# coverId = xml.getElementsByTagName('ScanInformation')[0].firstChild.nodeValue
|
||||||
if coverId:
|
# coverId = compile('(MCD\\()(\\d+)(\\))').search(coverId)
|
||||||
options.remoteCovers = getCoversFromMCB(coverId.group(2))
|
# if coverId:
|
||||||
|
# options.remoteCovers = getCoversFromMCB(coverId.group(2))
|
||||||
os.remove(xmlPath)
|
os.remove(xmlPath)
|
||||||
|
|
||||||
|
|
||||||
@@ -812,11 +824,15 @@ def splitProcess(path, mode):
|
|||||||
output = []
|
output = []
|
||||||
currentSize = 0
|
currentSize = 0
|
||||||
currentTarget = path
|
currentTarget = path
|
||||||
|
if options.webtoon:
|
||||||
|
targetSize = 104857600
|
||||||
|
else:
|
||||||
|
targetSize = 419430400
|
||||||
if mode == 0:
|
if mode == 0:
|
||||||
for root, dirs, files in walkLevel(path, 0):
|
for root, dirs, files in walkLevel(path, 0):
|
||||||
for name in files:
|
for name in files:
|
||||||
size = os.path.getsize(os.path.join(root, name))
|
size = os.path.getsize(os.path.join(root, name))
|
||||||
if currentSize + size > 419430400:
|
if currentSize + size > targetSize:
|
||||||
currentTarget, pathRoot = createNewTome()
|
currentTarget, pathRoot = createNewTome()
|
||||||
output.append(pathRoot)
|
output.append(pathRoot)
|
||||||
currentSize = size
|
currentSize = size
|
||||||
@@ -828,7 +844,7 @@ def splitProcess(path, mode):
|
|||||||
for root, dirs, files in walkLevel(path, 0):
|
for root, dirs, files in walkLevel(path, 0):
|
||||||
for name in dirs:
|
for name in dirs:
|
||||||
size = getDirectorySize(os.path.join(root, name))
|
size = getDirectorySize(os.path.join(root, name))
|
||||||
if currentSize + size > 419430400:
|
if currentSize + size > targetSize:
|
||||||
currentTarget, pathRoot = createNewTome()
|
currentTarget, pathRoot = createNewTome()
|
||||||
output.append(pathRoot)
|
output.append(pathRoot)
|
||||||
currentSize = size
|
currentSize = size
|
||||||
@@ -842,7 +858,7 @@ def splitProcess(path, mode):
|
|||||||
for name in dirs:
|
for name in dirs:
|
||||||
size = getDirectorySize(os.path.join(root, name))
|
size = getDirectorySize(os.path.join(root, name))
|
||||||
currentSize = 0
|
currentSize = 0
|
||||||
if size > 419430400:
|
if size > targetSize:
|
||||||
if not firstTome:
|
if not firstTome:
|
||||||
currentTarget, pathRoot = createNewTome()
|
currentTarget, pathRoot = createNewTome()
|
||||||
output.append(pathRoot)
|
output.append(pathRoot)
|
||||||
@@ -851,7 +867,7 @@ def splitProcess(path, mode):
|
|||||||
for rootInside, dirsInside, filesInside in walkLevel(os.path.join(root, name), 0):
|
for rootInside, dirsInside, filesInside in walkLevel(os.path.join(root, name), 0):
|
||||||
for nameInside in dirsInside:
|
for nameInside in dirsInside:
|
||||||
size = getDirectorySize(os.path.join(rootInside, nameInside))
|
size = getDirectorySize(os.path.join(rootInside, nameInside))
|
||||||
if currentSize + size > 419430400:
|
if currentSize + size > targetSize:
|
||||||
currentTarget, pathRoot = createNewTome()
|
currentTarget, pathRoot = createNewTome()
|
||||||
output.append(pathRoot)
|
output.append(pathRoot)
|
||||||
currentSize = size
|
currentSize = size
|
||||||
@@ -1144,7 +1160,10 @@ def makeBook(source, qtGUI=None):
|
|||||||
GUI.progressBarTick.emit('tick')
|
GUI.progressBarTick.emit('tick')
|
||||||
options.baseTitle = options.title
|
options.baseTitle = options.title
|
||||||
for tome in tomes:
|
for tome in tomes:
|
||||||
if len(tomes) > 1:
|
if len(tomes) > 9:
|
||||||
|
tomeNumber += 1
|
||||||
|
options.title = options.baseTitle + ' [' + str(tomeNumber).zfill(2) + '/' + str(len(tomes)).zfill(2) + ']'
|
||||||
|
elif len(tomes) > 1:
|
||||||
tomeNumber += 1
|
tomeNumber += 1
|
||||||
options.title = options.baseTitle + ' [' + str(tomeNumber) + '/' + str(len(tomes)) + ']'
|
options.title = options.baseTitle + ' [' + str(tomeNumber) + '/' + str(len(tomes)) + ']'
|
||||||
if options.format == 'CBZ':
|
if options.format == 'CBZ':
|
||||||
@@ -1254,4 +1273,4 @@ def makeMOBI(work, qtGUI=None):
|
|||||||
makeMOBIWorkerPool.apply_async(func=makeMOBIWorker, args=(i, ), callback=makeMOBIWorkerTick)
|
makeMOBIWorkerPool.apply_async(func=makeMOBIWorker, args=(i, ), callback=makeMOBIWorkerTick)
|
||||||
makeMOBIWorkerPool.close()
|
makeMOBIWorkerPool.close()
|
||||||
makeMOBIWorkerPool.join()
|
makeMOBIWorkerPool.join()
|
||||||
return makeMOBIWorkerOutput
|
return makeMOBIWorkerOutput
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
# Copyright (c) 2013-2014 Pawel Jastrzebski <pawelj@iosphe.re>
|
# Copyright (c) 2013-2015 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, and/or distribute this software for
|
# Permission to use, copy, modify, and/or distribute this software for
|
||||||
# any purpose with or without fee is hereby granted, provided that the
|
# any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -18,9 +18,9 @@
|
|||||||
# PERFORMANCE OF THIS SOFTWARE.
|
# PERFORMANCE OF THIS SOFTWARE.
|
||||||
#
|
#
|
||||||
|
|
||||||
__version__ = '4.3'
|
__version__ = '4.4.1'
|
||||||
__license__ = 'ISC'
|
__license__ = 'ISC'
|
||||||
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
|
__copyright__ = '2012-2015, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import os
|
import os
|
||||||
@@ -28,7 +28,7 @@ import sys
|
|||||||
from shutil import rmtree, copytree, move
|
from shutil import rmtree, copytree, move
|
||||||
from optparse import OptionParser, OptionGroup
|
from optparse import OptionParser, OptionGroup
|
||||||
from multiprocessing import Pool
|
from multiprocessing import Pool
|
||||||
from PIL import Image, ImageStat
|
from PIL import Image, ImageStat, ImageOps
|
||||||
from .shared import getImageFileName, walkLevel
|
from .shared import getImageFileName, walkLevel
|
||||||
try:
|
try:
|
||||||
from PyQt5 import QtCore
|
from PyQt5 import QtCore
|
||||||
@@ -50,9 +50,9 @@ def mergeDirectory(work):
|
|||||||
try:
|
try:
|
||||||
directory = work[0]
|
directory = work[0]
|
||||||
images = []
|
images = []
|
||||||
imagesClear = []
|
imagesValid = []
|
||||||
sizes = []
|
sizes = []
|
||||||
h = 0
|
targetHeight = 0
|
||||||
for root, dirs, files in walkLevel(directory, 0):
|
for root, dirs, files in walkLevel(directory, 0):
|
||||||
for name in files:
|
for name in files:
|
||||||
if getImageFileName(name) is not None:
|
if getImageFileName(name) is not None:
|
||||||
@@ -60,23 +60,26 @@ def mergeDirectory(work):
|
|||||||
images.append([os.path.join(root, name), i.size[0], i.size[1]])
|
images.append([os.path.join(root, name), i.size[0], i.size[1]])
|
||||||
sizes.append(i.size[0])
|
sizes.append(i.size[0])
|
||||||
if len(images) > 0:
|
if len(images) > 0:
|
||||||
mw = max(set(sizes), key=sizes.count)
|
targetWidth = max(set(sizes), key=sizes.count)
|
||||||
for i in images:
|
for i in images:
|
||||||
if i[1] == mw:
|
if i[1] <= targetWidth:
|
||||||
h += i[2]
|
targetHeight += i[2]
|
||||||
imagesClear.append(i[0])
|
imagesValid.append(i[0])
|
||||||
# Silently drop directories that contain too many images
|
# Silently drop directories that contain too many images
|
||||||
if h > 262144:
|
# 131072 = GIMP_MAX_IMAGE_SIZE / 4
|
||||||
|
if targetHeight > 131072:
|
||||||
return None
|
return None
|
||||||
result = Image.new('RGB', (mw, h))
|
result = Image.new('RGB', (targetWidth, targetHeight))
|
||||||
y = 0
|
y = 0
|
||||||
for i in imagesClear:
|
for i in imagesValid:
|
||||||
img = Image.open(i)
|
img = Image.open(i)
|
||||||
img = img.convert('RGB')
|
img = img.convert('RGB')
|
||||||
|
if img.size[0] < targetWidth:
|
||||||
|
img = ImageOps.fit(img, (targetWidth, img.size[1]), method=Image.BICUBIC, centering=(0.5, 0.5))
|
||||||
result.paste(img, (0, y))
|
result.paste(img, (0, y))
|
||||||
y += img.size[1]
|
y += img.size[1]
|
||||||
os.remove(i)
|
os.remove(i)
|
||||||
savePath = os.path.split(imagesClear[0])
|
savePath = os.path.split(imagesValid[0])
|
||||||
result.save(os.path.join(savePath[0], os.path.splitext(savePath[1])[0] + '.png'), 'PNG')
|
result.save(os.path.join(savePath[0], os.path.splitext(savePath[1])[0] + '.png'), 'PNG')
|
||||||
except Exception:
|
except Exception:
|
||||||
return str(sys.exc_info()[1])
|
return str(sys.exc_info()[1])
|
||||||
@@ -84,7 +87,7 @@ def mergeDirectory(work):
|
|||||||
|
|
||||||
def sanitizePanelSize(panel, opt):
|
def sanitizePanelSize(panel, opt):
|
||||||
newPanels = []
|
newPanels = []
|
||||||
if panel[2] > 8 * opt.height:
|
if panel[2] > 6 * opt.height:
|
||||||
diff = int(panel[2] / 8)
|
diff = int(panel[2] / 8)
|
||||||
newPanels.append([panel[0], panel[1] - diff*7, diff])
|
newPanels.append([panel[0], panel[1] - diff*7, diff])
|
||||||
newPanels.append([panel[1] - diff*7, panel[1] - diff*6, diff])
|
newPanels.append([panel[1] - diff*7, panel[1] - diff*6, diff])
|
||||||
@@ -94,13 +97,13 @@ def sanitizePanelSize(panel, opt):
|
|||||||
newPanels.append([panel[1] - diff*3, panel[1] - diff*2, diff])
|
newPanels.append([panel[1] - diff*3, panel[1] - diff*2, diff])
|
||||||
newPanels.append([panel[1] - diff*2, panel[1] - diff, diff])
|
newPanels.append([panel[1] - diff*2, panel[1] - diff, diff])
|
||||||
newPanels.append([panel[1] - diff, panel[1], diff])
|
newPanels.append([panel[1] - diff, panel[1], diff])
|
||||||
elif panel[2] > 4 * opt.height:
|
elif panel[2] > 3 * opt.height:
|
||||||
diff = int(panel[2] / 4)
|
diff = int(panel[2] / 4)
|
||||||
newPanels.append([panel[0], panel[1] - diff*3, diff])
|
newPanels.append([panel[0], panel[1] - diff*3, diff])
|
||||||
newPanels.append([panel[1] - diff*3, panel[1] - diff*2, diff])
|
newPanels.append([panel[1] - diff*3, panel[1] - diff*2, diff])
|
||||||
newPanels.append([panel[1] - diff*2, panel[1] - diff, diff])
|
newPanels.append([panel[1] - diff*2, panel[1] - diff, diff])
|
||||||
newPanels.append([panel[1] - diff, panel[1], diff])
|
newPanels.append([panel[1] - diff, panel[1], diff])
|
||||||
elif panel[2] > 2 * opt.height:
|
elif panel[2] > 1.5 * opt.height:
|
||||||
newPanels.append([panel[0], panel[1] - int(panel[2] / 2), int(panel[2] / 2)])
|
newPanels.append([panel[0], panel[1] - int(panel[2] / 2), int(panel[2] / 2)])
|
||||||
newPanels.append([panel[1] - int(panel[2] / 2), panel[1], int(panel[2] / 2)])
|
newPanels.append([panel[1] - int(panel[2] / 2), panel[1], int(panel[2] / 2)])
|
||||||
else:
|
else:
|
||||||
@@ -199,8 +202,7 @@ def splitImage(work):
|
|||||||
panelImg = image.crop([0, panels[panel][0], widthImg, panels[panel][1]])
|
panelImg = image.crop([0, panels[panel][0], widthImg, panels[panel][1]])
|
||||||
newPage.paste(panelImg, (0, targetHeight))
|
newPage.paste(panelImg, (0, targetHeight))
|
||||||
targetHeight += panels[panel][2]
|
targetHeight += panels[panel][2]
|
||||||
newPage.save(os.path.join(path, fileExpanded[0] + '-' +
|
newPage.save(os.path.join(path, fileExpanded[0] + '-' + str(pageNumber) + '.png'), 'PNG')
|
||||||
str(pageNumber) + '.png'), 'PNG')
|
|
||||||
pageNumber += 1
|
pageNumber += 1
|
||||||
os.remove(filePath)
|
os.remove(filePath)
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Based on initial version of DualMetaFix. Copyright (C) 2013 Kevin Hendricks
|
# Based on initial version of DualMetaFix. Copyright (C) 2013 Kevin Hendricks
|
||||||
# Changes for KCC Copyright (C) 2014 Pawel Jastrzebski <pawelj@iosphe.re>
|
# Changes for KCC Copyright (C) 2014-2015 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
85
kcc/image.py
85
kcc/image.py
@@ -1,7 +1,7 @@
|
|||||||
# Copyright (C) 2010 Alex Yatskov
|
# Copyright (C) 2010 Alex Yatskov
|
||||||
# Copyright (C) 2011 Stanislav (proDOOMman) Kosolapov <prodoomman@gmail.com>
|
# Copyright (C) 2011 Stanislav (proDOOMman) Kosolapov <prodoomman@gmail.com>
|
||||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
# Copyright (c) 2013-2014 Pawel Jastrzebski <pawelj@iosphe.re>
|
# Copyright (c) 2013-2015 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -16,9 +16,9 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
__version__ = '4.3'
|
__version__ = '4.4.1'
|
||||||
__license__ = 'ISC'
|
__license__ = 'ISC'
|
||||||
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
|
__copyright__ = '2012-2015, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import os
|
import os
|
||||||
@@ -87,7 +87,7 @@ class ProfileData:
|
|||||||
'K345': ("Kindle", (600, 800), Palette16, 1.8, (900, 1200)),
|
'K345': ("Kindle", (600, 800), Palette16, 1.8, (900, 1200)),
|
||||||
'KDX': ("Kindle DX/DXG", (824, 1000), Palette16, 1.8, (1236, 1500)),
|
'KDX': ("Kindle DX/DXG", (824, 1000), Palette16, 1.8, (1236, 1500)),
|
||||||
'KPW': ("Kindle Paperwhite", (758, 1024), Palette16, 1.8, (1137, 1536)),
|
'KPW': ("Kindle Paperwhite", (758, 1024), Palette16, 1.8, (1137, 1536)),
|
||||||
'KV': ("Kindle Voyage", (1080, 1440), Palette16, 1.8, (1620, 2160)),
|
'KV': ("Kindle Voyage", (1072, 1448), Palette16, 1.8, (1608, 2172)),
|
||||||
'KFHD': ("K. Fire HD", (800, 1280), PalleteNull, 1.0, (1200, 1920)),
|
'KFHD': ("K. Fire HD", (800, 1280), PalleteNull, 1.0, (1200, 1920)),
|
||||||
'KFHDX': ("K. Fire HDX", (1200, 1920), PalleteNull, 1.0, (1800, 2880)),
|
'KFHDX': ("K. Fire HDX", (1200, 1920), PalleteNull, 1.0, (1800, 2880)),
|
||||||
'KFHDX8': ("K. Fire HDX 8.9", (1600, 2560), PalleteNull, 1.0, (2400, 3840)),
|
'KFHDX8': ("K. Fire HDX 8.9", (1600, 2560), PalleteNull, 1.0, (2400, 3840)),
|
||||||
@@ -102,16 +102,15 @@ class ProfileData:
|
|||||||
|
|
||||||
|
|
||||||
class ComicPage:
|
class ComicPage:
|
||||||
def __init__(self, source, device, fill=None):
|
def __init__(self, source, options, fill=None):
|
||||||
try:
|
try:
|
||||||
self.profile_label, self.size, self.palette, self.gamma, self.panelviewsize = device
|
self.profile_label, self.size, self.palette, self.gamma, self.panelviewsize = options.profileData
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise RuntimeError('Unexpected output device %s' % device)
|
raise RuntimeError('Unexpected output device %s' % options.profileData)
|
||||||
self.origFileName = source
|
self.origFileName = source
|
||||||
self.filename = os.path.basename(self.origFileName)
|
self.filename = os.path.basename(self.origFileName)
|
||||||
self.image = Image.open(source)
|
self.image = Image.open(source)
|
||||||
self.image = self.image.convert('RGB')
|
self.image = self.image.convert('RGB')
|
||||||
self.color = self.isImageColor()
|
|
||||||
self.rotated = None
|
self.rotated = None
|
||||||
self.border = None
|
self.border = None
|
||||||
self.noHPV = None
|
self.noHPV = None
|
||||||
@@ -119,17 +118,22 @@ class ComicPage:
|
|||||||
self.noPV = None
|
self.noPV = None
|
||||||
self.purge = False
|
self.purge = False
|
||||||
self.hq = False
|
self.hq = False
|
||||||
|
self.opt = options
|
||||||
if fill:
|
if fill:
|
||||||
self.fill = fill
|
self.fill = fill
|
||||||
else:
|
else:
|
||||||
self.fill = None
|
self.fill = None
|
||||||
|
if options.webtoon:
|
||||||
|
self.color = True
|
||||||
|
else:
|
||||||
|
self.color = self.isImageColor()
|
||||||
|
|
||||||
def saveToDir(self, targetdir, forcepng, color):
|
def saveToDir(self, targetdir):
|
||||||
try:
|
try:
|
||||||
if not self.purge:
|
if not self.purge:
|
||||||
flags = []
|
flags = []
|
||||||
filename = os.path.join(targetdir, os.path.splitext(self.filename)[0]) + '-KCC'
|
filename = os.path.join(targetdir, os.path.splitext(self.filename)[0]) + '-KCC'
|
||||||
if not color and not forcepng:
|
if not self.opt.forcecolor and not self.opt.forcepng:
|
||||||
self.image = self.image.convert('L')
|
self.image = self.image.convert('L')
|
||||||
if self.rotated:
|
if self.rotated:
|
||||||
flags.append('Rotated')
|
flags.append('Rotated')
|
||||||
@@ -144,21 +148,22 @@ class ComicPage:
|
|||||||
if self.noVPV:
|
if self.noVPV:
|
||||||
flags.append('NoVerticalPanelView')
|
flags.append('NoVerticalPanelView')
|
||||||
if self.border:
|
if self.border:
|
||||||
flags.append("Margins-" + str(self.border[0]) + "-" + str(self.border[1]) + "-"
|
flags.append('Margins-' + str(self.border[0]) + '-' + str(self.border[1]) + '-'
|
||||||
+ str(self.border[2]) + "-" + str(self.border[3]))
|
+ str(self.border[2]) + '-' + str(self.border[3]))
|
||||||
if forcepng:
|
if self.opt.forcepng:
|
||||||
filename += ".png"
|
filename += '.png'
|
||||||
self.image.save(filename, "PNG", optimize=1)
|
self.image.save(filename, 'PNG', optimize=1)
|
||||||
else:
|
else:
|
||||||
filename += ".jpg"
|
filename += '.jpg'
|
||||||
self.image.save(filename, "JPEG", optimize=1)
|
self.image.save(filename, 'JPEG', optimize=1, quality=80)
|
||||||
return [md5Checksum(filename), flags]
|
return [md5Checksum(filename), flags]
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
raise RuntimeError('Cannot write image in directory %s: %s' % (targetdir, e))
|
raise RuntimeError('Cannot write image in directory %s: %s' % (targetdir, e))
|
||||||
|
|
||||||
def optimizeImage(self, gamma):
|
def optimizeImage(self):
|
||||||
|
gamma = self.opt.gamma
|
||||||
if gamma < 0.1:
|
if gamma < 0.1:
|
||||||
gamma = self.gamma
|
gamma = self.gamma
|
||||||
if self.gamma != 1.0 and self.color:
|
if self.gamma != 1.0 and self.color:
|
||||||
@@ -215,7 +220,12 @@ class ComicPage:
|
|||||||
self.noHPV = True
|
self.noHPV = True
|
||||||
self.noVPV = True
|
self.noVPV = True
|
||||||
|
|
||||||
def resizeImage(self, upscale=False, stretch=False, bordersColor=None, qualityMode=0):
|
def resizeImage(self, qualityMode=None):
|
||||||
|
upscale = self.opt.upscale
|
||||||
|
stretch = self.opt.stretch
|
||||||
|
bordersColor = self.opt.bordersColor
|
||||||
|
if qualityMode is None:
|
||||||
|
qualityMode = self.opt.quality
|
||||||
if bordersColor:
|
if bordersColor:
|
||||||
fill = bordersColor
|
fill = bordersColor
|
||||||
else:
|
else:
|
||||||
@@ -243,7 +253,7 @@ class ComicPage:
|
|||||||
if self.image.size[0] <= size[0] and self.image.size[1] <= size[1]:
|
if self.image.size[0] <= size[0] and self.image.size[1] <= size[1]:
|
||||||
method = Image.BICUBIC
|
method = Image.BICUBIC
|
||||||
else:
|
else:
|
||||||
method = Image.ANTIALIAS
|
method = Image.LANCZOS
|
||||||
self.image = self.image.resize(size, method)
|
self.image = self.image.resize(size, method)
|
||||||
return self.image
|
return self.image
|
||||||
# If image is smaller than target resolution and upscale is off - Just expand it by adding margins
|
# If image is smaller than target resolution and upscale is off - Just expand it by adding margins
|
||||||
@@ -269,17 +279,17 @@ class ComicPage:
|
|||||||
if self.image.size[0] <= size[0] and self.image.size[1] <= size[1]:
|
if self.image.size[0] <= size[0] and self.image.size[1] <= size[1]:
|
||||||
method = Image.BICUBIC
|
method = Image.BICUBIC
|
||||||
else:
|
else:
|
||||||
method = Image.ANTIALIAS
|
method = Image.LANCZOS
|
||||||
self.image = ImageOps.fit(self.image, size, method=method, centering=(0.5, 0.5))
|
self.image = ImageOps.fit(self.image, size, method=method, centering=(0.5, 0.5))
|
||||||
return self.image
|
return self.image
|
||||||
|
|
||||||
def splitPage(self, targetdir, righttoleft=False, rotate=False):
|
def splitPage(self, targetdir):
|
||||||
width, height = self.image.size
|
width, height = self.image.size
|
||||||
dstwidth, dstheight = self.size
|
dstwidth, dstheight = self.size
|
||||||
# Only split if origin is not oriented the same as target
|
# Only split if origin is not oriented the same as target
|
||||||
if (width > height) != (dstwidth > dstheight):
|
if (width > height) != (dstwidth > dstheight):
|
||||||
if rotate:
|
if self.opt.rotate:
|
||||||
self.image = self.image.rotate(90)
|
self.image = self.image.rotate(90, Image.BICUBIC, True)
|
||||||
self.rotated = True
|
self.rotated = True
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
@@ -292,18 +302,18 @@ class ComicPage:
|
|||||||
# Source is portrait and target is landscape, so split by the height
|
# Source is portrait and target is landscape, so split by the height
|
||||||
leftbox = (0, 0, width, int(height / 2))
|
leftbox = (0, 0, width, int(height / 2))
|
||||||
rightbox = (0, int(height / 2), width, height)
|
rightbox = (0, int(height / 2), width, height)
|
||||||
filename = os.path.splitext(self.filename)
|
filename = os.path.splitext(self.filename)[0]
|
||||||
fileone = targetdir + '/' + filename[0] + '-A' + filename[1]
|
fileone = targetdir + '/' + filename + '-AAA.png'
|
||||||
filetwo = targetdir + '/' + filename[0] + '-B' + filename[1]
|
filetwo = targetdir + '/' + filename + '-BBB.png'
|
||||||
try:
|
try:
|
||||||
if righttoleft:
|
if self.opt.righttoleft:
|
||||||
pageone = self.image.crop(rightbox)
|
pageone = self.image.crop(rightbox)
|
||||||
pagetwo = self.image.crop(leftbox)
|
pagetwo = self.image.crop(leftbox)
|
||||||
else:
|
else:
|
||||||
pageone = self.image.crop(leftbox)
|
pageone = self.image.crop(leftbox)
|
||||||
pagetwo = self.image.crop(rightbox)
|
pagetwo = self.image.crop(rightbox)
|
||||||
pageone.save(fileone)
|
pageone.save(fileone, 'PNG', optimize=1)
|
||||||
pagetwo.save(filetwo)
|
pagetwo.save(filetwo, 'PNG', optimize=1)
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
raise RuntimeError('Cannot write image in directory %s: %s' % (targetdir, e))
|
raise RuntimeError('Cannot write image in directory %s: %s' % (targetdir, e))
|
||||||
return fileone, filetwo
|
return fileone, filetwo
|
||||||
@@ -417,13 +427,16 @@ class ComicPage:
|
|||||||
imageBoxB = ImageChops.invert(bw).getbbox()
|
imageBoxB = ImageChops.invert(bw).getbbox()
|
||||||
if imageBoxA is None or imageBoxB is None:
|
if imageBoxA is None or imageBoxB is None:
|
||||||
surfaceB, surfaceW = 0, 0
|
surfaceB, surfaceW = 0, 0
|
||||||
|
diff = 0
|
||||||
else:
|
else:
|
||||||
surfaceB = (imageBoxA[2] - imageBoxA[0]) * (imageBoxA[3] - imageBoxA[1])
|
surfaceB = (imageBoxA[2] - imageBoxA[0]) * (imageBoxA[3] - imageBoxA[1])
|
||||||
surfaceW = (imageBoxB[2] - imageBoxB[0]) * (imageBoxB[3] - imageBoxB[1])
|
surfaceW = (imageBoxB[2] - imageBoxB[0]) * (imageBoxB[3] - imageBoxB[1])
|
||||||
if surfaceW < surfaceB:
|
diff = ((max(surfaceB, surfaceW) - min(surfaceB, surfaceW)) / min(surfaceB, surfaceW)) * 100
|
||||||
self.fill = 'white'
|
if diff > 0.5:
|
||||||
elif surfaceW > surfaceB:
|
if surfaceW < surfaceB:
|
||||||
self.fill = 'black'
|
self.fill = 'white'
|
||||||
|
elif surfaceW > surfaceB:
|
||||||
|
self.fill = 'black'
|
||||||
else:
|
else:
|
||||||
fill = 0
|
fill = 0
|
||||||
startY = 0
|
startY = 0
|
||||||
@@ -498,7 +511,7 @@ class Cover:
|
|||||||
|
|
||||||
def processExternal(self):
|
def processExternal(self):
|
||||||
self.image = self.image.convert('RGB')
|
self.image = self.image.convert('RGB')
|
||||||
self.image.thumbnail(self.options.profileData[1], Image.ANTIALIAS)
|
self.image.thumbnail(self.options.profileData[1], Image.LANCZOS)
|
||||||
self.save(True)
|
self.save(True)
|
||||||
|
|
||||||
def trim(self):
|
def trim(self):
|
||||||
@@ -520,6 +533,6 @@ class Cover:
|
|||||||
if os.path.splitext(source)[1].lower() == '.png':
|
if os.path.splitext(source)[1].lower() == '.png':
|
||||||
self.image.save(self.target, "PNG", optimize=1)
|
self.image.save(self.target, "PNG", optimize=1)
|
||||||
else:
|
else:
|
||||||
self.image.save(self.target, "JPEG", optimize=1)
|
self.image.save(self.target, "JPEG", optimize=1, quality=80)
|
||||||
except IOError:
|
except IOError:
|
||||||
raise RuntimeError('Failed to save cover')
|
raise RuntimeError('Failed to save cover')
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
# Copyright (c) 2013-2014 Pawel Jastrzebski <pawelj@iosphe.re>
|
# Copyright (c) 2013-2015 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||||
#
|
#
|
||||||
# Based upon the code snippet by Ned Batchelder
|
# Based upon the code snippet by Ned Batchelder
|
||||||
# (http://nedbatchelder.com/blog/200712/extracting_jpgs_from_pdfs.html)
|
# (http://nedbatchelder.com/blog/200712/extracting_jpgs_from_pdfs.html)
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
__license__ = 'ISC'
|
__license__ = 'ISC'
|
||||||
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
|
__copyright__ = '2012-2015, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# rarfile.py
|
# rarfile.py
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2013 Marko Kreen <markokr@gmail.com>
|
# Copyright (c) 2005-2014 Marko Kreen <markokr@gmail.com>
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, and/or distribute this software for any
|
# Permission to use, copy, modify, and/or distribute this software for any
|
||||||
# purpose with or without fee is hereby granted, provided that the above
|
# purpose with or without fee is hereby granted, provided that the above
|
||||||
@@ -74,7 +74,7 @@ For more details, refer to source.
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__version__ = '2.6'
|
__version__ = '2.7-kcc'
|
||||||
|
|
||||||
# export only interesting items
|
# export only interesting items
|
||||||
__all__ = ['is_rarfile', 'RarInfo', 'RarFile', 'RarExtFile']
|
__all__ = ['is_rarfile', 'RarInfo', 'RarFile', 'RarExtFile']
|
||||||
@@ -178,8 +178,25 @@ EXTRACT_ARGS = ('x', '-y', '-idq')
|
|||||||
#: args for testrar()
|
#: args for testrar()
|
||||||
TEST_ARGS = ('t', '-idq')
|
TEST_ARGS = ('t', '-idq')
|
||||||
|
|
||||||
|
#
|
||||||
|
# Allow use of tool that is not compatible with unrar.
|
||||||
|
#
|
||||||
|
# By default use 'bsdtar' which is 'tar' program that
|
||||||
|
# sits on top of libarchive.
|
||||||
|
#
|
||||||
|
# Problems with libarchive RAR backend:
|
||||||
|
# - Does not support solid archives.
|
||||||
|
# - Does not support password-protected archives.
|
||||||
|
#
|
||||||
|
|
||||||
|
ALT_TOOL = 'bsdtar'
|
||||||
|
ALT_OPEN_ARGS = ('-x', '--to-stdout', '-f')
|
||||||
|
ALT_EXTRACT_ARGS = ('-x', '-f')
|
||||||
|
ALT_TEST_ARGS = ('-t', '-f')
|
||||||
|
ALT_CHECK_ARGS = ('--help',)
|
||||||
|
|
||||||
#: whether to speed up decompression by using tmp archive
|
#: whether to speed up decompression by using tmp archive
|
||||||
USE_EXTRACT_HACK = 1
|
USE_EXTRACT_HACK = 0
|
||||||
|
|
||||||
#: limit the filesize for tmp archive usage
|
#: limit the filesize for tmp archive usage
|
||||||
HACK_SIZE_LIMIT = 20*1024*1024
|
HACK_SIZE_LIMIT = 20*1024*1024
|
||||||
@@ -278,6 +295,7 @@ RAR_M5 = 0x35
|
|||||||
##
|
##
|
||||||
|
|
||||||
RAR_ID = bytes("Rar!\x1a\x07\x00", 'ascii')
|
RAR_ID = bytes("Rar!\x1a\x07\x00", 'ascii')
|
||||||
|
RAR5_ID = bytes("Rar!\x1a\x07\x01", 'ascii')
|
||||||
ZERO = bytes("\0", 'ascii')
|
ZERO = bytes("\0", 'ascii')
|
||||||
EMPTY = bytes("", 'ascii')
|
EMPTY = bytes("", 'ascii')
|
||||||
|
|
||||||
@@ -336,6 +354,8 @@ class RarUnknownError(RarExecError):
|
|||||||
"""Unknown exit code"""
|
"""Unknown exit code"""
|
||||||
class RarSignalExit(RarExecError):
|
class RarSignalExit(RarExecError):
|
||||||
"""Unrar exited with signal"""
|
"""Unrar exited with signal"""
|
||||||
|
class RarCannotExec(RarExecError):
|
||||||
|
"""Executable not found."""
|
||||||
|
|
||||||
|
|
||||||
def is_rarfile(xfile):
|
def is_rarfile(xfile):
|
||||||
@@ -343,7 +363,10 @@ def is_rarfile(xfile):
|
|||||||
fd = XFile(xfile)
|
fd = XFile(xfile)
|
||||||
buf = fd.read(len(RAR_ID))
|
buf = fd.read(len(RAR_ID))
|
||||||
fd.close()
|
fd.close()
|
||||||
return buf == RAR_ID
|
if buf == RAR_ID or buf == RAR5_ID:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
class RarInfo(object):
|
class RarInfo(object):
|
||||||
@@ -693,10 +716,7 @@ class RarFile(object):
|
|||||||
"""Let 'unrar' test the archive.
|
"""Let 'unrar' test the archive.
|
||||||
"""
|
"""
|
||||||
cmd = [UNRAR_TOOL] + list(TEST_ARGS)
|
cmd = [UNRAR_TOOL] + list(TEST_ARGS)
|
||||||
if self._password is not None:
|
add_password_arg(cmd, self._password)
|
||||||
cmd.append('-p' + self._password)
|
|
||||||
else:
|
|
||||||
cmd.append('-p-')
|
|
||||||
cmd.append(self.rarfile)
|
cmd.append(self.rarfile)
|
||||||
p = custom_popen(cmd)
|
p = custom_popen(cmd)
|
||||||
output = p.communicate()[0]
|
output = p.communicate()[0]
|
||||||
@@ -769,7 +789,7 @@ class RarFile(object):
|
|||||||
fd = XFile(self.rarfile)
|
fd = XFile(self.rarfile)
|
||||||
self._fd = fd
|
self._fd = fd
|
||||||
id = fd.read(len(RAR_ID))
|
id = fd.read(len(RAR_ID))
|
||||||
if id != RAR_ID:
|
if id != RAR_ID and id != RAR5_ID:
|
||||||
raise NotRarFile("Not a Rar archive: "+self.rarfile)
|
raise NotRarFile("Not a Rar archive: "+self.rarfile)
|
||||||
|
|
||||||
volume = 0 # first vol (.rar) is 0
|
volume = 0 # first vol (.rar) is 0
|
||||||
@@ -1172,8 +1192,7 @@ class RarFile(object):
|
|||||||
if is_filelike(rarfile):
|
if is_filelike(rarfile):
|
||||||
raise ValueError("Cannot use unrar directly on memory buffer")
|
raise ValueError("Cannot use unrar directly on memory buffer")
|
||||||
cmd = [UNRAR_TOOL] + list(OPEN_ARGS)
|
cmd = [UNRAR_TOOL] + list(OPEN_ARGS)
|
||||||
if psw is not None:
|
add_password_arg(cmd, psw)
|
||||||
cmd.append("-p" + psw)
|
|
||||||
cmd.append(rarfile)
|
cmd.append(rarfile)
|
||||||
|
|
||||||
# not giving filename avoids encoding related problems
|
# not giving filename avoids encoding related problems
|
||||||
@@ -1205,10 +1224,7 @@ class RarFile(object):
|
|||||||
|
|
||||||
# pasoword
|
# pasoword
|
||||||
psw = psw or self._password
|
psw = psw or self._password
|
||||||
if psw is not None:
|
add_password_arg(cmd, psw)
|
||||||
cmd.append('-p' + psw)
|
|
||||||
else:
|
|
||||||
cmd.append('-p-')
|
|
||||||
|
|
||||||
# rar file
|
# rar file
|
||||||
cmd.append(self.rarfile)
|
cmd.append(self.rarfile)
|
||||||
@@ -1830,10 +1846,7 @@ def rar_decompress(vers, meth, data, declen=0, flags=0, crc=0, psw=None, salt=No
|
|||||||
tmpf.close()
|
tmpf.close()
|
||||||
|
|
||||||
cmd = [UNRAR_TOOL] + list(OPEN_ARGS)
|
cmd = [UNRAR_TOOL] + list(OPEN_ARGS)
|
||||||
if psw is not None and (flags & RAR_FILE_PASSWORD):
|
add_password_arg(cmd, psw, (flags & RAR_FILE_PASSWORD))
|
||||||
cmd.append("-p" + psw)
|
|
||||||
else:
|
|
||||||
cmd.append("-p-")
|
|
||||||
cmd.append(tmpname)
|
cmd.append(tmpname)
|
||||||
|
|
||||||
p = custom_popen(cmd)
|
p = custom_popen(cmd)
|
||||||
@@ -1902,10 +1915,27 @@ def custom_popen(cmd):
|
|||||||
except OSError:
|
except OSError:
|
||||||
ex = sys.exc_info()[1]
|
ex = sys.exc_info()[1]
|
||||||
if ex.errno == errno.ENOENT:
|
if ex.errno == errno.ENOENT:
|
||||||
raise RarExecError("Unrar not installed? (rarfile.UNRAR_TOOL=%r)" % UNRAR_TOOL)
|
raise RarCannotExec("Unrar not installed? (rarfile.UNRAR_TOOL=%r)" % UNRAR_TOOL)
|
||||||
raise
|
raise
|
||||||
return p
|
return p
|
||||||
|
|
||||||
|
def custom_check(cmd, ignore_retcode=False):
|
||||||
|
"""Run command, collect output, raise error if needed."""
|
||||||
|
p = custom_popen(cmd)
|
||||||
|
out, err = p.communicate()
|
||||||
|
if p.returncode and not ignore_retcode:
|
||||||
|
raise RarExecError("Check-run failed")
|
||||||
|
return out
|
||||||
|
|
||||||
|
def add_password_arg(cmd, psw, required=False):
|
||||||
|
"""Append password switch to commandline."""
|
||||||
|
if UNRAR_TOOL == ALT_TOOL:
|
||||||
|
return
|
||||||
|
if psw is not None:
|
||||||
|
cmd.append('-p' + psw)
|
||||||
|
else:
|
||||||
|
cmd.append('-p-')
|
||||||
|
|
||||||
def check_returncode(p, out):
|
def check_returncode(p, out):
|
||||||
"""Raise exception according to unrar exit code"""
|
"""Raise exception according to unrar exit code"""
|
||||||
|
|
||||||
@@ -1920,6 +1950,8 @@ def check_returncode(p, out):
|
|||||||
RarWarning, RarFatalError, RarCRCError, RarLockedArchiveError,
|
RarWarning, RarFatalError, RarCRCError, RarLockedArchiveError,
|
||||||
RarWriteError, RarOpenError, RarUserError, RarMemoryError,
|
RarWriteError, RarOpenError, RarUserError, RarMemoryError,
|
||||||
RarCreateError, RarNoFilesError] # codes from rar.txt
|
RarCreateError, RarNoFilesError] # codes from rar.txt
|
||||||
|
if UNRAR_TOOL == ALT_TOOL:
|
||||||
|
errmap = [None]
|
||||||
if code > 0 and code < len(errmap):
|
if code > 0 and code < len(errmap):
|
||||||
exc = errmap[code]
|
exc = errmap[code]
|
||||||
elif code == 255:
|
elif code == 255:
|
||||||
@@ -1936,3 +1968,24 @@ def check_returncode(p, out):
|
|||||||
msg = "%s [%d]" % (exc.__doc__, p.returncode)
|
msg = "%s [%d]" % (exc.__doc__, p.returncode)
|
||||||
|
|
||||||
raise exc(msg)
|
raise exc(msg)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Check if unrar works
|
||||||
|
#
|
||||||
|
|
||||||
|
try:
|
||||||
|
# does UNRAR_TOOL work?
|
||||||
|
custom_check([UNRAR_TOOL], True)
|
||||||
|
except RarCannotExec:
|
||||||
|
try:
|
||||||
|
# does ALT_TOOL work?
|
||||||
|
custom_check([ALT_TOOL] + list(ALT_CHECK_ARGS), True)
|
||||||
|
# replace config
|
||||||
|
UNRAR_TOOL = ALT_TOOL
|
||||||
|
OPEN_ARGS = ALT_OPEN_ARGS
|
||||||
|
EXTRACT_ARGS = ALT_EXTRACT_ARGS
|
||||||
|
TEST_ARGS = ALT_TEST_ARGS
|
||||||
|
except RarCannotExec:
|
||||||
|
# no usable tool, only uncompressed archives work
|
||||||
|
pass
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
# Copyright (c) 2013-2014 Pawel Jastrzebski <pawelj@iosphe.re>
|
# Copyright (c) 2013-2015 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, and/or distribute this software for
|
# Permission to use, copy, modify, and/or distribute this software for
|
||||||
# any purpose with or without fee is hereby granted, provided that the
|
# any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -17,25 +17,36 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
__license__ = 'ISC'
|
__license__ = 'ISC'
|
||||||
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
|
__copyright__ = '2012-2015, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from hashlib import md5
|
from hashlib import md5
|
||||||
|
from html.parser import HTMLParser
|
||||||
|
from distutils.version import StrictVersion
|
||||||
|
|
||||||
|
|
||||||
|
class HTMLStripper(HTMLParser):
|
||||||
|
def __init__(self):
|
||||||
|
HTMLParser.__init__(self)
|
||||||
|
self.reset()
|
||||||
|
self.strict = False
|
||||||
|
self.convert_charrefs = True
|
||||||
|
self.fed = []
|
||||||
|
|
||||||
|
def handle_data(self, d):
|
||||||
|
self.fed.append(d)
|
||||||
|
|
||||||
|
def get_data(self):
|
||||||
|
return ''.join(self.fed)
|
||||||
|
|
||||||
|
|
||||||
def getImageFileName(imgfile):
|
def getImageFileName(imgfile):
|
||||||
filename = os.path.splitext(imgfile)
|
name, ext = os.path.splitext(imgfile)
|
||||||
if filename[0].startswith('.') or\
|
ext = ext.lower()
|
||||||
(filename[1].lower() != '.png' and
|
if name.startswith('.') or (ext != '.png' and ext != '.jpg' and ext != '.jpeg' and ext != '.gif'):
|
||||||
filename[1].lower() != '.jpg' and
|
|
||||||
filename[1].lower() != '.gif' and
|
|
||||||
filename[1].lower() != '.tif' and
|
|
||||||
filename[1].lower() != '.tiff' and
|
|
||||||
filename[1].lower() != '.bmp' and
|
|
||||||
filename[1].lower() != '.jpeg'):
|
|
||||||
return None
|
return None
|
||||||
return filename
|
return [name, ext]
|
||||||
|
|
||||||
|
|
||||||
def walkLevel(some_dir, level=1):
|
def walkLevel(some_dir, level=1):
|
||||||
@@ -58,3 +69,50 @@ def md5Checksum(filePath):
|
|||||||
break
|
break
|
||||||
m.update(data)
|
m.update(data)
|
||||||
return m.hexdigest()
|
return m.hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def check7ZFile(filePath):
|
||||||
|
with open(filePath, 'rb') as fh:
|
||||||
|
header = fh.read(6)
|
||||||
|
return header == b"7z\xbc\xaf'\x1c"
|
||||||
|
|
||||||
|
|
||||||
|
# noinspection PyUnresolvedReferences
|
||||||
|
def dependencyCheck(level):
|
||||||
|
missing = []
|
||||||
|
if level > 2:
|
||||||
|
try:
|
||||||
|
from PyQt5.QtCore import qVersion as qtVersion
|
||||||
|
if StrictVersion('5.2.0') > StrictVersion(qtVersion()):
|
||||||
|
missing.append('PyQt 5.2.0+')
|
||||||
|
except ImportError:
|
||||||
|
missing.append('PyQt 5.2.0+')
|
||||||
|
if level > 1:
|
||||||
|
try:
|
||||||
|
from psutil import __version__ as psutilVersion
|
||||||
|
if StrictVersion('2.0.0') > StrictVersion(psutilVersion):
|
||||||
|
missing.append('psutil 2.0.0+')
|
||||||
|
except ImportError:
|
||||||
|
missing.append('psutil 2.0.0+')
|
||||||
|
try:
|
||||||
|
from slugify import __version__ as slugifyVersion
|
||||||
|
if StrictVersion('0.1.0') > StrictVersion(slugifyVersion):
|
||||||
|
missing.append('python-slugify 0.1.0+')
|
||||||
|
except ImportError:
|
||||||
|
missing.append('python-slugify 0.1.0+')
|
||||||
|
try:
|
||||||
|
from PIL import PILLOW_VERSION as pillowVersion
|
||||||
|
if StrictVersion('2.7.0') > StrictVersion(pillowVersion):
|
||||||
|
missing.append('Pillow 2.7.0+')
|
||||||
|
except ImportError:
|
||||||
|
missing.append('Pillow 2.7.0+')
|
||||||
|
if len(missing) > 0:
|
||||||
|
try:
|
||||||
|
import tkinter
|
||||||
|
import tkinter.messagebox
|
||||||
|
importRoot = tkinter.Tk()
|
||||||
|
importRoot.withdraw()
|
||||||
|
tkinter.messagebox.showerror('KCC - Error', 'ERROR: ' + ', '.join(missing) + ' is not installed!')
|
||||||
|
except ImportError:
|
||||||
|
print('ERROR: ' + ', '.join(missing) + ' is not installed!')
|
||||||
|
exit(1)
|
||||||
14
setup.py
14
setup.py
@@ -14,7 +14,7 @@ if version_info[0] != 3:
|
|||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
NAME = "KindleComicConverter"
|
NAME = "KindleComicConverter"
|
||||||
VERSION = "4.3"
|
VERSION = "4.4.1"
|
||||||
MAIN = "kcc.py"
|
MAIN = "kcc.py"
|
||||||
|
|
||||||
if platform == "darwin":
|
if platform == "darwin":
|
||||||
@@ -26,17 +26,14 @@ if platform == "darwin":
|
|||||||
py2app=dict(
|
py2app=dict(
|
||||||
argv_emulation=True,
|
argv_emulation=True,
|
||||||
iconfile='icons/comic2ebook.icns',
|
iconfile='icons/comic2ebook.icns',
|
||||||
includes=['PIL', 'sip', 'PyQt5', 'PyQt5.QtCore', 'PyQt5.QtGui', 'PyQt5.QtNetwork', 'PyQt5.QtWidgets',
|
includes=['sip', 'PyQt5.QtPrintSupport'],
|
||||||
'PyQt5.QtPrintSupport'],
|
|
||||||
resources=['LICENSE.txt', 'other/qt.conf', 'other/Additional-LICENSE.txt', 'other/unrar', 'other/7za'],
|
resources=['LICENSE.txt', 'other/qt.conf', 'other/Additional-LICENSE.txt', 'other/unrar', 'other/7za'],
|
||||||
plist=dict(
|
plist=dict(
|
||||||
CFBundleName=NAME,
|
CFBundleName=NAME,
|
||||||
CFBundleShortVersionString=VERSION,
|
CFBundleShortVersionString=VERSION,
|
||||||
CFBundleGetInfoString=NAME + " " + VERSION +
|
CFBundleGetInfoString=NAME + " " + VERSION +
|
||||||
", written 2012-2014 by Ciro Mattia Gonano and Pawel Jastrzebski",
|
", written 2012-2015 by Ciro Mattia Gonano and Pawel Jastrzebski",
|
||||||
CFBundleExecutable=NAME,
|
CFBundleExecutable=NAME,
|
||||||
CFBundleIdentifier='com.github.ciromattia.kcc',
|
|
||||||
CFBundleSignature='dplt',
|
|
||||||
CFBundleDocumentTypes=[
|
CFBundleDocumentTypes=[
|
||||||
dict(
|
dict(
|
||||||
CFBundleTypeExtensions=['cbz', 'cbr', 'cb7', 'zip', 'rar', '7z', 'pdf'],
|
CFBundleTypeExtensions=['cbz', 'cbr', 'cb7', 'zip', 'rar', '7z', 'pdf'],
|
||||||
@@ -47,7 +44,7 @@ if platform == "darwin":
|
|||||||
],
|
],
|
||||||
LSMinimumSystemVersion='10.8.0',
|
LSMinimumSystemVersion='10.8.0',
|
||||||
LSEnvironment=dict(
|
LSEnvironment=dict(
|
||||||
PATH='/usr/local/bin:/usr/bin:/bin'
|
PATH='./../Resources:/usr/local/bin:/usr/bin:/bin'
|
||||||
),
|
),
|
||||||
NSHumanReadableCopyright='ISC License (ISCL)'
|
NSHumanReadableCopyright='ISC License (ISCL)'
|
||||||
)
|
)
|
||||||
@@ -69,6 +66,7 @@ elif platform == "win32":
|
|||||||
'other\\7za.exe',
|
'other\\7za.exe',
|
||||||
'other\\UnRAR.exe',
|
'other\\UnRAR.exe',
|
||||||
'other\\Additional-LICENSE.txt',
|
'other\\Additional-LICENSE.txt',
|
||||||
|
'C:\Python34' + suffix + '\Lib\site-packages\PyQt5\libGLESv2.dll',
|
||||||
'C:\Python34' + suffix + '\Lib\site-packages\PyQt5\libEGL.dll'])]
|
'C:\Python34' + suffix + '\Lib\site-packages\PyQt5\libEGL.dll'])]
|
||||||
extra_options = dict(
|
extra_options = dict(
|
||||||
options={'py2exe': {"bundle_files": 1,
|
options={'py2exe': {"bundle_files": 1,
|
||||||
@@ -81,7 +79,7 @@ elif platform == "win32":
|
|||||||
windows=[{"script": MAIN,
|
windows=[{"script": MAIN,
|
||||||
"dest_base": "KCC",
|
"dest_base": "KCC",
|
||||||
"version": VERSION,
|
"version": VERSION,
|
||||||
"copyright": "Ciro Mattia Gonano, Pawel Jastrzebski © 2014",
|
"copyright": "Ciro Mattia Gonano, Pawel Jastrzebski © 2012-2015",
|
||||||
"legal_copyright": "ISC License (ISCL)",
|
"legal_copyright": "ISC License (ISCL)",
|
||||||
"product_version": VERSION,
|
"product_version": VERSION,
|
||||||
"product_name": "Kindle Comic Converter",
|
"product_name": "Kindle Comic Converter",
|
||||||
|
|||||||
Reference in New Issue
Block a user