mirror of
https://github.com/ciromattia/kcc
synced 2026-04-15 21:48:44 +00:00
Compare commits
66 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
205170efe4 | ||
|
|
fceac407ee | ||
|
|
4c5ebe5949 | ||
|
|
d12ad26e79 | ||
|
|
bd57665b55 | ||
|
|
c3b8d48813 | ||
|
|
c8933e7326 | ||
|
|
c95c64ccff | ||
|
|
c5bcd4c2e4 | ||
|
|
9e402897c5 | ||
|
|
cbf87df551 | ||
|
|
ea01492e1f | ||
|
|
82445d5d3a | ||
|
|
839bc4cc9e | ||
|
|
98c6a569bf | ||
|
|
85ad95c0d0 | ||
|
|
1d0498fdce | ||
|
|
ee390c34e9 | ||
|
|
b853615f7d | ||
|
|
5b2bb30902 | ||
|
|
da4788a6c6 | ||
|
|
3022635a71 | ||
|
|
38d3ae6a6a | ||
|
|
3f0eea44f4 | ||
|
|
5077f60881 | ||
|
|
279f70a6bd | ||
|
|
01f3596fde | ||
|
|
23d3577a06 | ||
|
|
22c75951e0 | ||
|
|
3d3fb5dc61 | ||
|
|
e4a8213a2c | ||
|
|
b2f71ae163 | ||
|
|
53256b0e34 | ||
|
|
4ebd3e046d | ||
|
|
d07d49d2e7 | ||
|
|
111bfb9302 | ||
|
|
143b2a7ff5 | ||
|
|
e7b47d28d9 | ||
|
|
97b44a89d4 | ||
|
|
27e01657b1 | ||
|
|
43638813d7 | ||
|
|
f781b6785c | ||
|
|
9168cd4109 | ||
|
|
4c49c6ffc9 | ||
|
|
4890727692 | ||
|
|
7907a45ca2 | ||
|
|
727bbba815 | ||
|
|
877da36e5a | ||
|
|
ab8effbc32 | ||
|
|
a58d98f0dc | ||
|
|
431cb73e61 | ||
|
|
0ee02f2efd | ||
|
|
8d5b2a9e88 | ||
|
|
1085673010 | ||
|
|
d327a72749 | ||
|
|
74add23c14 | ||
|
|
9b400573c8 | ||
|
|
a8c3ef7d00 | ||
|
|
a484582b70 | ||
|
|
69b956904c | ||
|
|
6e3888f295 | ||
|
|
1bfa0eb9c7 | ||
|
|
08a342c909 | ||
|
|
a28ad2b0c7 | ||
|
|
4c96de9cdf | ||
|
|
3a645abe6f |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -7,4 +7,5 @@ dist
|
||||
kindlegen*
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
UnRAR.exe
|
||||
/UnRAR.exe
|
||||
/7za.exe
|
||||
|
||||
821
KCC-Linux.ui
Normal file
821
KCC-Linux.ui
Normal file
@@ -0,0 +1,821 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>KCC</class>
|
||||
<widget class="QMainWindow" name="KCC">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>420</width>
|
||||
<height>380</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>420</width>
|
||||
<height>380</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>420</width>
|
||||
<height>380</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Kindle Comic Converter</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="KCC.qrc">
|
||||
<normaloff>:/Icon/icons/comic2ebook.png</normaloff>:/Icon/icons/comic2ebook.png</iconset>
|
||||
</property>
|
||||
<property name="locale">
|
||||
<locale language="C" country="AnyCountry"/>
|
||||
</property>
|
||||
<widget class="QWidget" name="Form">
|
||||
<widget class="QFrame" name="OptionsAdvanced">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>1</x>
|
||||
<y>254</y>
|
||||
<width>421</width>
|
||||
<height>61</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="ProcessingBox">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Disable image optimizations.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>No optimisation</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="UpscaleBox">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-weight:600; text-decoration: underline;">Unchecked - Nothing<br/></span>Images smaller than device resolution will not be resized.</p><p><span style=" font-weight:600; text-decoration: underline;">Indeterminate - Stretching<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be not preserved.</p><p><span style=" font-weight:600; text-decoration: underline;">Checked - Upscaling<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be preserved.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Stretch/Upscale</string>
|
||||
</property>
|
||||
<property name="tristate">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="WebtoonBox">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Enable auto-splitting of webtoons like <span style=" font-style:italic;">Tower of God</span> or <span style=" font-style:italic;">Noblesse</span>.<br/>Pages with a low width, high height and vertical panel flow.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Webtoon mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QCheckBox" name="NoDitheringBox">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Create PNG files instead JPEG.<br/>Quality increase is not noticeable on most of devices.<br/>Output files <span style=" font-weight:600;">might</span> be smaller.<br/><span style=" font-weight:600;">MOBI conversion will be much slower.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PNG output</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="BorderBox">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-weight:600; text-decoration: underline;">Unchecked - Autodetection<br/></span>Color of margins fill will be detected automatically.</p><p><span style=" font-weight:600; text-decoration: underline;">Indeterminate - White<br/></span>Margins will be filled with white color.</p><p><span style=" font-weight:600; text-decoration: underline;">Checked - Black<br/></span>Margins will be filled with black color.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>W/B margins</string>
|
||||
</property>
|
||||
<property name="tristate">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QCheckBox" name="NoRotateBox">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Disable splitting and rotation.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>No split/rotate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QComboBox" name="DeviceBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>200</y>
|
||||
<width>141</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Target device.</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QComboBox" name="FormatBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>260</x>
|
||||
<y>200</y>
|
||||
<width>151</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Output format.</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="ConvertButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>160</x>
|
||||
<y>200</y>
|
||||
<width>91</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Convert</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="KCC.qrc">
|
||||
<normaloff>:/Other/icons/convert.png</normaloff>:/Other/icons/convert.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="DirectoryButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>160</y>
|
||||
<width>141</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add directory</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="KCC.qrc">
|
||||
<normaloff>:/Other/icons/folder_new.png</normaloff>:/Other/icons/folder_new.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="FileButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>260</x>
|
||||
<y>160</y>
|
||||
<width>151</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add file</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="KCC.qrc">
|
||||
<normaloff>:/Other/icons/document_new.png</normaloff>:/Other/icons/document_new.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="ClearButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>160</x>
|
||||
<y>160</y>
|
||||
<width>91</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Clear list</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="KCC.qrc">
|
||||
<normaloff>:/Other/icons/clear.png</normaloff>:/Other/icons/clear.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QFrame" name="OptionsBasic">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>1</x>
|
||||
<y>230</y>
|
||||
<width>421</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<widget class="QCheckBox" name="MangaBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>9</x>
|
||||
<y>10</y>
|
||||
<width>130</width>
|
||||
<height>18</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Enable right-to-left reading.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Manga mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QCheckBox" name="QualityBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>282</x>
|
||||
<y>10</y>
|
||||
<width>135</width>
|
||||
<height>18</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600; text-decoration: underline;">Unchecked - Normal quality mode<br /></span><span style=" font-family:'MS Shell Dlg 2'; font-style:italic;">Use it when Panel View support is not needed.</span><span style=" font-family:'MS Shell Dlg 2'; font-weight:600; text-decoration: underline;"><br /></span><span style=" font-family:'MS Shell Dlg 2';">- Maximum quality when zoom is not enabled.<br />- Poor quality when zoom is enabled.<br />- Lowest file size.</span></p>
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600; text-decoration: underline;">Indeterminate - High quality mode<br /></span><span style=" font-family:'MS Shell Dlg 2'; font-style:italic;">Not zoomed image </span><span style=" font-family:'MS Shell Dlg 2'; font-weight:600; font-style:italic;">might </span><span style=" font-family:'MS Shell Dlg 2'; font-style:italic;">be a little blurry.</span><span style=" font-family:'MS Shell Dlg 2'; font-weight:600; text-decoration: underline;"><br /></span><span style=" font-family:'MS Shell Dlg 2';">- Medium/High quality when zoom is not enabled.<br />- Maximum quality when zoom is enabled.</span></p>
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600; text-decoration: underline;">Checked - Ultra quality mode<br /></span><span style=" font-family:'MS Shell Dlg 2'; font-style:italic;">Maximum possible quality.</span><span style=" font-family:'MS Shell Dlg 2'; font-weight:600; text-decoration: underline;"><br /></span><span style=" font-family:'MS Shell Dlg 2';">- Maximum quality when zoom is not enabled.<br />- Maximum quality when zoom is enabled.<br />- Very high file size.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>High/Ultra quality</string>
|
||||
</property>
|
||||
<property name="tristate">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QCheckBox" name="RotateBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>145</x>
|
||||
<y>10</y>
|
||||
<width>130</width>
|
||||
<height>18</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Disable page spliting.<br/>They will be rotated instead.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Horizontal mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
<zorder>RotateBox</zorder>
|
||||
<zorder>MangaBox</zorder>
|
||||
<zorder>QualityBox</zorder>
|
||||
</widget>
|
||||
<widget class="QListWidget" name="JobList">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>50</y>
|
||||
<width>401</width>
|
||||
<height>101</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
<pointsize>8</pointsize>
|
||||
<italic>false</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}</string>
|
||||
</property>
|
||||
<property name="showDropIndicator" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::NoSelection</enum>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>18</width>
|
||||
<height>18</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="BasicModeButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>195</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Basic</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="AdvModeButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>217</x>
|
||||
<y>10</y>
|
||||
<width>195</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Advanced</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QFrame" name="OptionsAdvancedGamma">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>305</y>
|
||||
<width>401</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<widget class="QLabel" name="GammaLabel">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>15</x>
|
||||
<y>0</y>
|
||||
<width>100</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>When converting color images setting this option to 1.0 <span style=" font-weight:600;">might</span> improve readability.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Gamma: Auto</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QSlider" name="GammaSlider">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>110</x>
|
||||
<y>10</y>
|
||||
<width>275</width>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::ClickFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>When converting color images setting this option to 1.0 <span style=" font-weight:600;">might</span> improve readability.</p></body></html></string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>500</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QProgressBar" name="ProgressBar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>401</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
<pointsize>10</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignJustify|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="format">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QFrame" name="OptionsExpert">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>1</x>
|
||||
<y>337</y>
|
||||
<width>421</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<widget class="QCheckBox" name="ColorBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>9</x>
|
||||
<y>11</y>
|
||||
<width>130</width>
|
||||
<height>18</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Do not convert images to grayscale.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Color mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QFrame" name="OptionsExpertInternal">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>105</x>
|
||||
<y>0</y>
|
||||
<width>295</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="wLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Resolution of target device.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Custom width: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="customWidth">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::ClickFocus</enum>
|
||||
</property>
|
||||
<property name="acceptDrops">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Resolution of target device.</string>
|
||||
</property>
|
||||
<property name="inputMask">
|
||||
<string>0000; </string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>4</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="hLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Resolution of target device.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Custom height: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QLineEdit" name="customHeight">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::ClickFocus</enum>
|
||||
</property>
|
||||
<property name="acceptDrops">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Resolution of target device.</string>
|
||||
</property>
|
||||
<property name="inputMask">
|
||||
<string>0000; </string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>4</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<zorder>OptionsAdvanced</zorder>
|
||||
<zorder>DeviceBox</zorder>
|
||||
<zorder>FormatBox</zorder>
|
||||
<zorder>ConvertButton</zorder>
|
||||
<zorder>DirectoryButton</zorder>
|
||||
<zorder>FileButton</zorder>
|
||||
<zorder>ClearButton</zorder>
|
||||
<zorder>OptionsBasic</zorder>
|
||||
<zorder>JobList</zorder>
|
||||
<zorder>BasicModeButton</zorder>
|
||||
<zorder>AdvModeButton</zorder>
|
||||
<zorder>OptionsAdvancedGamma</zorder>
|
||||
<zorder>OptionsExpert</zorder>
|
||||
<zorder>ProgressBar</zorder>
|
||||
</widget>
|
||||
<action name="ActionBasic">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Basic</string>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font/>
|
||||
</property>
|
||||
</action>
|
||||
<action name="ActionAdvanced">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Advanced</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>DirectoryButton</tabstop>
|
||||
<tabstop>FileButton</tabstop>
|
||||
<tabstop>ConvertButton</tabstop>
|
||||
<tabstop>ClearButton</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="KCC.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
109
KCC-OSX.ui
109
KCC-OSX.ui
@@ -47,7 +47,7 @@
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>9</x>
|
||||
<x>4</x>
|
||||
<y>253</y>
|
||||
<width>421</width>
|
||||
<height>61</height>
|
||||
@@ -55,6 +55,7 @@
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
@@ -63,7 +64,8 @@
|
||||
<widget class="QCheckBox" name="ProcessingBox">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
@@ -81,14 +83,15 @@
|
||||
<widget class="QCheckBox" name="UpscaleBox">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-weight:600; text-decoration: underline;">Unchecked - Nothing<br/></span>Images smaller than device resolution will not be resized.</p><p><span style=" font-weight:600; text-decoration: underline;">Indeterminate - Stretching<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be not preserved.</p><p><span style=" font-weight:600; text-decoration: underline;">Checked - Upscaling<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be preserved.</p></body></html></string>
|
||||
<string><html><head/><body><p><span style=" font-size:12pt; font-weight:600; text-decoration: underline;">Unchecked - Nothing<br/></span><span style=" font-size:12pt;">Images smaller than device resolution will not be resized.</span></p><p><span style=" font-size:12pt; font-weight:600; text-decoration: underline;">Indeterminate - Stretching<br/></span><span style=" font-size:12pt;">Images smaller than device resolution will be resized. Aspect ratio will be not preserved.</span></p><p><span style=" font-size:12pt; font-weight:600; text-decoration: underline;">Checked - Upscaling<br/></span><span style=" font-size:12pt;">Images smaller than device resolution will be resized. Aspect ratio will be preserved.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Stretch/Upscale</string>
|
||||
@@ -102,14 +105,15 @@
|
||||
<widget class="QCheckBox" name="WebtoonBox">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-weight:600;">EXPERIMENTAL!<br/></span>Enable auto-splitting of webtoons like <span style=" font-style:italic;">Tower of God</span> or <span style=" font-style:italic;">Noblesse</span>.<br/>Pages with a low width, high height and vertical panel flow.</p></body></html></string>
|
||||
<string><html><head/><body><p><span style=" font-size:12pt;">Enable auto-splitting of webtoons like </span><span style=" font-size:12pt; font-style:italic;">Tower of God</span><span style=" font-size:12pt;"> or </span><span style=" font-size:12pt; font-style:italic;">Noblesse</span><span style=" font-size:12pt;">.<br/>Pages with a low width, high height and vertical panel flow.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Webtoon mode</string>
|
||||
@@ -120,14 +124,15 @@
|
||||
<widget class="QCheckBox" name="NoDitheringBox">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-size:12pt;">Create PNG files instead JPEG.<br/></span><span style=" font-size:12pt; font-weight:600;">Only for non-Kindle devices!</span></p></body></html></string>
|
||||
<string><html><head/><body><p><span style=" font-size:12pt;">Create PNG files instead JPEG.<br/>Quality increase is not noticeable on most of devices.<br/>Output files </span><span style=" font-size:12pt; font-weight:600;">might</span><span style=" font-size:12pt;"> be smaller.<br/></span><span style=" font-size:12pt; font-weight:600;">MOBI conversion will be much slower.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PNG output</string>
|
||||
@@ -138,17 +143,21 @@
|
||||
<widget class="QCheckBox" name="BorderBox">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-size:12pt;">Fill space around images with black color.</span></p></body></html></string>
|
||||
<string><html><head/><body><p><span style=" font-size:12pt; font-weight:600; text-decoration: underline;">Unchecked - Autodetection<br/></span><span style=" font-size:12pt;">Color of margins fill will be detected automatically.</span></p><p><span style=" font-size:12pt; font-weight:600; text-decoration: underline;">Indeterminate - White<br/></span><span style=" font-size:12pt;">Margins will be filled with white color.</span></p><p><span style=" font-size:12pt; font-weight:600; text-decoration: underline;">Checked - Black<br/></span><span style=" font-size:12pt;">Margins will be filled with black color.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Black borders</string>
|
||||
<string>W/B margins</string>
|
||||
</property>
|
||||
<property name="tristate">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -156,7 +165,8 @@
|
||||
<widget class="QCheckBox" name="NoRotateBox">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
@@ -176,13 +186,14 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>8</x>
|
||||
<y>200</y>
|
||||
<y>201</y>
|
||||
<width>151</width>
|
||||
<height>34</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
@@ -190,20 +201,21 @@
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Target device.</string>
|
||||
<string><html><head/><body><p><span style=" font-size:12pt;">Target device.</span></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QComboBox" name="FormatBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>262</x>
|
||||
<y>200</y>
|
||||
<y>201</y>
|
||||
<width>152</width>
|
||||
<height>34</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
@@ -211,7 +223,7 @@
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Output format.</string>
|
||||
<string><html><head/><body><p><span style=" font-size:12pt;">Output format.</span></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="ConvertButton">
|
||||
@@ -225,6 +237,7 @@
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>11</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
@@ -252,6 +265,7 @@
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
@@ -277,6 +291,7 @@
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
@@ -302,6 +317,7 @@
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
@@ -319,7 +335,7 @@
|
||||
<widget class="QFrame" name="OptionsBasic">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<x>5</x>
|
||||
<y>233</y>
|
||||
<width>421</width>
|
||||
<height>41</height>
|
||||
@@ -327,7 +343,8 @@
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<widget class="QCheckBox" name="MangaBox">
|
||||
@@ -341,7 +358,8 @@
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
@@ -359,20 +377,21 @@
|
||||
<rect>
|
||||
<x>282</x>
|
||||
<y>10</y>
|
||||
<width>130</width>
|
||||
<width>135</width>
|
||||
<height>18</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600; text-decoration: underline;">Unchecked - Normal quality mode<br/></span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-style:italic;">Use it when Panel View support is not needed.</span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600; text-decoration: underline;"><br/></span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">- Maximum quality when zoom is not enabled.<br/>- Poor quality when zoom is enabled.<br/>- Lowest file size.</span></p><p><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600; text-decoration: underline;">Indeterminate - High quality mode<br/></span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-style:italic;">Not zoomed image </span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600; font-style:italic;">might </span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-style:italic;">be a little blurry.</span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600; text-decoration: underline;"><br/></span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">- Medium/High quality when zoom is not enabled.<br/>- Maximum quality when zoom is enabled.</span></p><p><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600; text-decoration: underline;">Checked - Ultra quality mode<br/></span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-style:italic;">Maximum possible quality.</span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600; text-decoration: underline;"><br/></span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">- Maximum quality when zoom is not enabled.<br/>- Maximum quality when zoom is enabled.<br/>- Very high file size.</span></p></body></html></string>
|
||||
<string><html><head/><body><p><span style="font-size:12pt; font-weight:600; text-decoration: underline;">Unchecked - Normal quality mode<br/></span><span style="font-size:12pt; font-style:italic;">Use it when Panel View support is not needed.</span><span style="font-size:12pt; font-weight:600; text-decoration: underline;"><br/></span><span style="font-size:12pt;">- Maximum quality when zoom is not enabled.<br/>- Poor quality when zoom is enabled.<br/>- Lowest file size.</span></p><p><span style="font-size:12pt; font-weight:600; text-decoration: underline;">Indeterminate - High quality mode<br/></span><span style="font-size:12pt; font-style:italic;">Not zoomed image </span><span style="font-size:12pt; font-weight:600; font-style:italic;">might </span><span style="font-size:12pt; font-style:italic;">be a little blurry.</span><span style="font-size:12pt; font-weight:600; text-decoration: underline;"><br/></span><span style="font-size:12pt;">- Medium/High quality when zoom is not enabled.<br/>- Maximum quality when zoom is enabled.</span></p><p><span style="font-size:12pt; font-weight:600; text-decoration: underline;">Checked - Ultra quality mode<br/></span><span style="font-size:12pt; font-style:italic;">Maximum possible quality.</span><span style="font-size:12pt; font-weight:600; text-decoration: underline;"><br/></span><span style="font-size:12pt;">- Maximum quality when zoom is not enabled.<br/>- Maximum quality when zoom is enabled.<br/>- Very high file size.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>High/Ultra quality</string>
|
||||
@@ -392,7 +411,8 @@
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
@@ -420,18 +440,28 @@
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}</string>
|
||||
</property>
|
||||
<property name="showDropIndicator" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::NoSelection</enum>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="BasicModeButton">
|
||||
<property name="geometry">
|
||||
@@ -444,6 +474,7 @@
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
@@ -467,6 +498,7 @@
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
@@ -485,7 +517,7 @@
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<x>5</x>
|
||||
<y>303</y>
|
||||
<width>401</width>
|
||||
<height>41</height>
|
||||
@@ -493,6 +525,7 @@
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
@@ -507,13 +540,14 @@
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-size:12pt;">When converting color images setting this option to 1.0 MIGHT improve readability.</span></p></body></html></string>
|
||||
<string><html><head/><body><p><span style=" font-size:12pt;">When converting color images setting this option to 1.0 </span><span style=" font-size:12pt; font-weight:600;">might</span><span style=" font-size:12pt;"> improve readability.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Gamma: Auto</string>
|
||||
@@ -524,10 +558,15 @@
|
||||
<rect>
|
||||
<x>110</x>
|
||||
<y>10</y>
|
||||
<width>280</width>
|
||||
<width>290</width>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::ClickFocus</enum>
|
||||
</property>
|
||||
@@ -556,6 +595,7 @@
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>10</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
@@ -577,7 +617,7 @@
|
||||
<widget class="QFrame" name="OptionsExpert">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<x>5</x>
|
||||
<y>335</y>
|
||||
<width>421</width>
|
||||
<height>41</height>
|
||||
@@ -585,6 +625,7 @@
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
@@ -599,7 +640,8 @@
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
@@ -615,17 +657,23 @@
|
||||
<widget class="QFrame" name="OptionsExpertInternal">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>90</x>
|
||||
<x>95</x>
|
||||
<y>0</y>
|
||||
<width>315</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
</font>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="wLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
@@ -655,6 +703,7 @@
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
@@ -679,6 +728,7 @@
|
||||
<widget class="QLabel" name="hLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
@@ -708,6 +758,7 @@
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Lucida Grande</family>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
|
||||
1
KCC.qrc
1
KCC.qrc
@@ -17,6 +17,7 @@
|
||||
<file>icons/warning.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="Other">
|
||||
<file>icons/list_background.png</file>
|
||||
<file>icons/clear.png</file>
|
||||
<file>icons/convert.png</file>
|
||||
<file>icons/document_new.png</file>
|
||||
|
||||
20
KCC.ui
20
KCC.ui
@@ -97,7 +97,7 @@
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-weight:600;">EXPERIMENTAL!<br/></span>Enable auto-splitting of webtoons like <span style=" font-style:italic;">Tower of God</span> or <span style=" font-style:italic;">Noblesse</span>.<br/>Pages with a low width, high height and vertical panel flow.</p></body></html></string>
|
||||
<string><html><head/><body><p>Enable auto-splitting of webtoons like <span style=" font-style:italic;">Tower of God</span> or <span style=" font-style:italic;">Noblesse</span>.<br/>Pages with a low width, high height and vertical panel flow.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Webtoon mode</string>
|
||||
@@ -110,7 +110,7 @@
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Create PNG files instead JPEG.<br/><span style=" font-weight:600;">Only for non-Kindle devices!</span></p></body></html></string>
|
||||
<string><html><head/><body><p>Create PNG files instead JPEG.<br/>Quality increase is not noticeable on most of devices.<br/>Output files <span style=" font-weight:600;">might</span> be smaller.<br/><span style=" font-weight:600;">MOBI conversion will be much slower.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PNG output</string>
|
||||
@@ -123,10 +123,13 @@
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Fill space around images with black color.</string>
|
||||
<string><html><head/><body><p><span style=" font-weight:600; text-decoration: underline;">Unchecked - Autodetection<br/></span>Color of margins fill will be detected automatically.</p><p><span style=" font-weight:600; text-decoration: underline;">Indeterminate - White<br/></span>Margins will be filled with white color.</p><p><span style=" font-weight:600; text-decoration: underline;">Checked - Black<br/></span>Margins will be filled with black color.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Black borders</string>
|
||||
<string>W/B margins</string>
|
||||
</property>
|
||||
<property name="tristate">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -385,12 +388,21 @@ p, li { white-space: pre-wrap; }
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}</string>
|
||||
</property>
|
||||
<property name="showDropIndicator" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::NoSelection</enum>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="BasicModeButton">
|
||||
<property name="geometry">
|
||||
|
||||
61
README.md
61
README.md
@@ -30,16 +30,19 @@ You can find the latest released binary at the following links:
|
||||
- Folders
|
||||
- CBZ, ZIP
|
||||
- CBR, RAR *(With `unrar` executable)*
|
||||
- CB7, 7Z *(With `7za` executable)*
|
||||
- PDF *(Extracting only contained JPG images)*
|
||||
|
||||
## OPTIONAL REQUIREMENTS
|
||||
- [KindleGen](http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1000765211) v2.9+ in a directory reachable by your _PATH_ or in _KCC_ directory *(For .mobi generation)*
|
||||
- [UnRAR](http://www.rarlab.com/download.htm) *(For CBR/RAR support)*
|
||||
- [7za](http://www.7-zip.org/download.html) *(For 7z/CB7 support)*
|
||||
|
||||
### For compiling/running from source:
|
||||
- Python 2.7 - Included in MacOS and Linux, follow the [official documentation](http://www.python.org/getit/windows/) to install on Windows.
|
||||
- PyQt4 - Please refer to official documentation for installing into your system.
|
||||
- [Pillow](http://pypi.python.org/pypi/Pillow/) - For comic optimizations. Please refer to official documentation for installing into your system.
|
||||
- [Pillow](http://pypi.python.org/pypi/Pillow/) 2.2.1+ - For comic optimizations. Please refer to official documentation for installing into your system.
|
||||
- **To build OS X release a modified QT is required:** [Patch](https://github.com/ciromattia/kcc/blob/master/other/QT-4.8.5-QListWidget.patch)
|
||||
|
||||
## USAGE
|
||||
|
||||
@@ -52,7 +55,7 @@ You can find the latest released binary at the following links:
|
||||
* Check our [wiki](https://github.com/ciromattia/kcc/wiki/Other-devices) for a list of tested Non-Kindle E-Readers.
|
||||
* The first image found will be set as the comic's cover.
|
||||
* All files/directories will be added to EPUB in alphabetical order.
|
||||
* Output MOBI file should be uploaded via USB. Other methods (e.g. via Calibre) might corrupt it.
|
||||
* Output MOBI file should be uploaded via USB. Other methods might corrupt it.
|
||||
|
||||
### GUI
|
||||
|
||||
@@ -67,12 +70,10 @@ Usage: comic2ebook.py [options] comic_file|comic_folder
|
||||
Options:
|
||||
MAIN:
|
||||
-p PROFILE, --profile=PROFILE
|
||||
Device profile (Choose one among K1, K2, K3, K4NT, K4T, KDX, KDXG, KHD, KF, KFHD, KFHD8, KFA) [Default=KHD]
|
||||
Device profile (Choose one among K1, K2, K345, KDX, KHD, KF, KFHD, KFHD8, KFHDX, KFHDX8, KFA) [Default=KHD]
|
||||
-q QUALITY, --quality=QUALITY
|
||||
Quality of Panel View. 0 - Normal 1 - High 2 - Ultra [Default=0]
|
||||
-m, --manga-style Manga style (Right-to-left reading and splitting)
|
||||
|
||||
EXPERIMENTAL:
|
||||
-w, --webtoon Webtoon processing mode
|
||||
|
||||
OUTPUT SETTINGS:
|
||||
@@ -84,9 +85,10 @@ Options:
|
||||
--batchsplit Split output into multiple files
|
||||
|
||||
PROCESSING:
|
||||
--blackborders Use black borders instead of white ones
|
||||
--blackborders Disable autodetection and force black borders
|
||||
--whiteborders Disable autodetection and force white borders
|
||||
--forcecolor Don't convert images to grayscale
|
||||
--forcepng Create PNG files instead JPEG (For non-Kindle devices)
|
||||
--forcepng Create PNG files instead JPEG
|
||||
--gamma=GAMMA Apply gamma correction to linearize the image [Default=Auto]
|
||||
--nocutpagenumbers Don't try to cut page numbering on images
|
||||
--noprocessing Don't apply image preprocessing
|
||||
@@ -129,22 +131,20 @@ This script born as a cross-platform alternative to `KindleComicParser` by **Dc5
|
||||
|
||||
The app relies and includes the following scripts/binaries:
|
||||
|
||||
- `KindleStrip` script © 2010-2012 by **Paul Durrant** and released in public domain
|
||||
([forum thread](http://www.mobileread.com/forums/showthread.php?t=96903))
|
||||
- `rarfile.py` script © 2005-2011 **Marko Kreen** <markokr@gmail.com>, released with ISC License
|
||||
- `image.py` class from **Alex Yatskov**'s [Mangle](http://foosoft.net/mangle/) with subsequent [proDOOMman](https://github.com/proDOOMman/Mangle)'s and [Birua](https://github.com/Birua/Mangle)'s patches
|
||||
- Icon is by **Nikolay Verin** ([http://ncrow.deviantart.com/](http://ncrow.deviantart.com/)) and released under [CC BY-NC-SA 3.0](http://creativecommons.org/licenses/by-nc-sa/3.0/) License
|
||||
- `KindleUnpack` script by Charles **M. Hannum, P. Durrant, K. Hendricks, S. Siebert, fandrieu, DiapDealer, nickredding**. Released with GPLv3 License.
|
||||
- `rarfile.py` script © 2005-2011 **Marko Kreen** <markokr@gmail.com>. Released with ISC License.
|
||||
- `image.py` class from **Alex Yatskov**'s [Mangle](http://foosoft.net/mangle/) with subsequent [proDOOMman](https://github.com/proDOOMman/Mangle)'s and [Birua](https://github.com/Birua/Mangle)'s patches.
|
||||
- Icon is by **Nikolay Verin** ([http://ncrow.deviantart.com/](http://ncrow.deviantart.com/)) and released under [CC BY-NC-SA 3.0](http://creativecommons.org/licenses/by-nc-sa/3.0/) License.
|
||||
|
||||
## SAMPLE FILES CREATED BY KCC
|
||||
* [Kindle Keyboard](http://kcc.vulturis.eu/Samples/Ubunchu!-K3.mobi)
|
||||
* [Kindle DX](http://kcc.vulturis.eu/Samples/Ubunchu!-KDX.mobi)
|
||||
* [Kindle DXG](http://kcc.vulturis.eu/Samples/Ubunchu!-KDXG.mobi)
|
||||
* [Kindle Non-Touch](http://kcc.vulturis.eu/Samples/Ubunchu!-K4NT.mobi)
|
||||
* [Kindle Touch](http://kcc.vulturis.eu/Samples/Ubunchu!-K4T.mobi)
|
||||
* [Kindle Paperwhite](http://kcc.vulturis.eu/Samples/Ubunchu!-KPW.mobi)
|
||||
* [Kindle](http://kcc.vulturis.eu/Samples/Ubunchu!-K345.mobi)
|
||||
* [Kindle DX/DXG](http://kcc.vulturis.eu/Samples/Ubunchu!-KDX.mobi)
|
||||
* [Kindle Fire](http://kcc.vulturis.eu/Samples/Ubunchu!-KF.mobi)
|
||||
* [Kindle Fire HD](http://kcc.vulturis.eu/Samples/Ubunchu!-KFHD.mobi)
|
||||
* [Kindle Fire HD 8.9"](http://kcc.vulturis.eu/Samples/Ubunchu!-KFHD8.mobi)
|
||||
* [Kindle Fire HDX](http://kcc.vulturis.eu/Samples/Ubunchu!-KFHDX.mobi)
|
||||
* [Kindle Fire HDX 8.9"](http://kcc.vulturis.eu/Samples/Ubunchu!-KFHDX8.mobi)
|
||||
|
||||
## CHANGELOG
|
||||
####1.00
|
||||
@@ -252,8 +252,31 @@ The app relies and includes the following scripts/binaries:
|
||||
* Added experimental parser of manga webtoons
|
||||
* Improved error handling
|
||||
|
||||
## KNOWN ISSUES
|
||||
* Removing SRCS headers sometimes fail in 32bit enviroments. Due to memory limitations.
|
||||
####3.2.1:
|
||||
* Hotfixed crash occurring on OS with Russian locale
|
||||
|
||||
####3.3:
|
||||
* Margins are now automatically omitted in Panel View mode
|
||||
* Margin color fill is now autodetected
|
||||
* Created MOBI files are not longer marked as _Personal_ on newer Kindle models
|
||||
* Layout of panels in Panel View mode is now automatically adjusted to content
|
||||
* Fixed Kindle 2/DX/DXG profiles - no more blank pages
|
||||
* All Kindle Fire profiles now support hiqh quality Panel View
|
||||
* Added support of 7z/CB7 files
|
||||
* Added Kindle Fire HDX profile
|
||||
* Support for Virtual Panel View was removed
|
||||
* Profiles for Kindle Keyboard, Touch and Non-Touch are now merged
|
||||
* Windows release is now bundled with UnRAR and 7za
|
||||
* Small GUI tweaks
|
||||
|
||||
####3.4:
|
||||
* Improved PNG output
|
||||
* Increased quality of upscaling
|
||||
* Added support of file association - KCC can now open CBZ, CBR, CB7, ZIP, RAR, 7Z and PDF files directly
|
||||
* Paths that contain UTF-8 characters are now supported
|
||||
* Migrated to new version of Pillow library
|
||||
* Merged DX and DXG profiles
|
||||
* Many other minor bug fixes and GUI tweaks
|
||||
|
||||
## COPYRIGHT
|
||||
|
||||
|
||||
BIN
icons/list_background.png
Normal file
BIN
icons/list_background.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.1 KiB |
BIN
icons/list_background.xcf
Normal file
BIN
icons/list_background.xcf
Normal file
Binary file not shown.
76
kcc.py
76
kcc.py
@@ -1,7 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2012 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||
# Copyright (c) 2012-2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||
# Copyright (c) 2013 Pawel Jastrzebski <pawelj@vulturis.eu>
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for
|
||||
# any purpose with or without fee is hereby granted, provided that the
|
||||
@@ -17,7 +18,7 @@
|
||||
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
__version__ = '3.2'
|
||||
__version__ = '3.4'
|
||||
__license__ = 'ISC'
|
||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
@@ -26,26 +27,87 @@ import sys
|
||||
import os
|
||||
try:
|
||||
# noinspection PyUnresolvedReferences
|
||||
from PyQt4 import QtGui
|
||||
from PyQt4 import QtCore, QtGui, QtNetwork
|
||||
except ImportError:
|
||||
print "ERROR: PyQT4 is not installed!"
|
||||
exit(1)
|
||||
from kcc import KCC_gui
|
||||
from multiprocessing import freeze_support
|
||||
|
||||
if sys.platform == 'darwin':
|
||||
if sys.platform.startswith('darwin'):
|
||||
# Workaround Finder-launched app PATH evaluation
|
||||
os.environ['PATH'] = '/usr/local/bin:' + os.environ['PATH']
|
||||
from kcc import KCC_ui_osx as KCC_ui
|
||||
elif sys.platform.startswith('linux'):
|
||||
from kcc import KCC_ui_linux as KCC_ui
|
||||
else:
|
||||
# Workaround for Windows file association mechanism
|
||||
if getattr(sys, 'frozen', False):
|
||||
os.chdir(os.path.dirname(os.path.abspath(sys.executable)))
|
||||
else:
|
||||
os.chdir(os.path.dirname(os.path.abspath(__file__)))
|
||||
from kcc import KCC_ui
|
||||
|
||||
|
||||
# Implementing detection of already running KCC instance and forwarding argv to it
|
||||
class QApplicationMessaging(QtGui.QApplication):
|
||||
def __init__(self, argv):
|
||||
QtGui.QApplication.__init__(self, argv)
|
||||
self._memory = QtCore.QSharedMemory(self)
|
||||
self._memory.setKey('KCC')
|
||||
if self._memory.attach():
|
||||
self._running = True
|
||||
else:
|
||||
self._running = False
|
||||
if not self._memory.create(1):
|
||||
raise RuntimeError(self._memory.errorString().toLocal8Bit().data())
|
||||
self._key = 'KCC'
|
||||
self._timeout = 1000
|
||||
self._server = QtNetwork.QLocalServer(self)
|
||||
if not self.isRunning():
|
||||
self._server.newConnection.connect(self.handleMessage)
|
||||
self._server.listen(self._key)
|
||||
|
||||
def isRunning(self):
|
||||
return self._running
|
||||
|
||||
def handleMessage(self):
|
||||
socket = self._server.nextPendingConnection()
|
||||
if socket.waitForReadyRead(self._timeout):
|
||||
self.emit(QtCore.SIGNAL('messageFromOtherInstance'), socket.readAll().data().decode('utf8'))
|
||||
|
||||
def sendMessage(self, message):
|
||||
if self.isRunning():
|
||||
socket = QtNetwork.QLocalSocket(self)
|
||||
socket.connectToServer(self._key, QtCore.QIODevice.WriteOnly)
|
||||
if not socket.waitForConnected(self._timeout):
|
||||
return False
|
||||
socket.write(message.encode('utf8'))
|
||||
if not socket.waitForBytesWritten(self._timeout):
|
||||
return False
|
||||
socket.disconnectFromServer()
|
||||
return True
|
||||
return False
|
||||
|
||||
freeze_support()
|
||||
APP = QtGui.QApplication(sys.argv)
|
||||
APP = QApplicationMessaging(sys.argv)
|
||||
if APP.isRunning():
|
||||
if len(sys.argv) > 1:
|
||||
APP.sendMessage(sys.argv[1].decode(sys.getfilesystemencoding()))
|
||||
sys.exit(0)
|
||||
else:
|
||||
messageBox = QtGui.QMessageBox()
|
||||
icon = QtGui.QIcon()
|
||||
icon.addPixmap(QtGui.QPixmap(':/Icon/icons/comic2ebook.png'), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
messageBox.setWindowIcon(icon)
|
||||
QtGui.QMessageBox.critical(messageBox, 'KCC - Error', 'KCC is already running!', QtGui.QMessageBox.Ok)
|
||||
sys.exit(1)
|
||||
KCC = QtGui.QMainWindow()
|
||||
UI = KCC_ui.Ui_KCC()
|
||||
UI.setupUi(KCC)
|
||||
GUI = KCC_gui.Ui_KCC(UI, KCC)
|
||||
GUI = KCC_gui.Ui_KCC(UI, KCC, APP)
|
||||
KCC.setWindowTitle("Kindle Comic Converter " + __version__)
|
||||
KCC.show()
|
||||
KCC.raise_()
|
||||
if len(sys.argv) > 1:
|
||||
GUI.handleMessage(sys.argv[1].decode(sys.getfilesystemencoding()))
|
||||
sys.exit(APP.exec_())
|
||||
|
||||
299
kcc/KCC_gui.py
299
kcc/KCC_gui.py
@@ -1,7 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||
# Copyright (c) 2012-2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||
# Copyright (c) 2013 Pawel Jastrzebski <pawelj@vulturis.eu>
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for
|
||||
# any purpose with or without fee is hereby granted, provided that the
|
||||
@@ -17,7 +18,7 @@
|
||||
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
__version__ = '3.2'
|
||||
__version__ = '3.4'
|
||||
__license__ = 'ISC'
|
||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
@@ -29,7 +30,7 @@ import traceback
|
||||
import urllib2
|
||||
import time
|
||||
import comic2ebook
|
||||
import kindlestrip
|
||||
import kindlesplit
|
||||
from image import ProfileData
|
||||
from subprocess import call, Popen, STDOUT, PIPE
|
||||
from PyQt4 import QtGui, QtCore
|
||||
@@ -98,6 +99,10 @@ class WorkerThread(QtCore.QThread):
|
||||
def __init__(self, parent):
|
||||
QtCore.QThread.__init__(self)
|
||||
self.parent = parent
|
||||
self.conversionAlive = False
|
||||
self.errors = False
|
||||
self.kindlegenErrorCode = 0
|
||||
self.kindlegenError = None
|
||||
|
||||
def __del__(self):
|
||||
self.wait()
|
||||
@@ -111,7 +116,6 @@ class WorkerThread(QtCore.QThread):
|
||||
self.emit(QtCore.SIGNAL("addMessage"), '<b>Conversion interrupted.</b>', 'error')
|
||||
self.emit(QtCore.SIGNAL("modeConvert"), True)
|
||||
|
||||
# noinspection PyUnboundLocalVariable
|
||||
def run(self):
|
||||
self.emit(QtCore.SIGNAL("modeConvert"), False)
|
||||
profile = ProfileData.ProfileLabels[str(GUI.DeviceBox.currentText())]
|
||||
@@ -130,12 +134,14 @@ class WorkerThread(QtCore.QThread):
|
||||
argv.append("--noprocessing")
|
||||
if GUI.NoRotateBox.isChecked():
|
||||
argv.append("--nosplitrotate")
|
||||
if GUI.BorderBox.isChecked():
|
||||
argv.append("--blackborders")
|
||||
if GUI.UpscaleBox.checkState() == 1:
|
||||
argv.append("--stretch")
|
||||
elif GUI.UpscaleBox.checkState() == 2:
|
||||
argv.append("--upscale")
|
||||
if GUI.BorderBox.checkState() == 1:
|
||||
argv.append("--whiteborders")
|
||||
elif GUI.BorderBox.checkState() == 2:
|
||||
argv.append("--blackborders")
|
||||
if GUI.NoDitheringBox.isChecked():
|
||||
argv.append("--forcepng")
|
||||
if GUI.WebtoonBox.isChecked():
|
||||
@@ -152,8 +158,9 @@ class WorkerThread(QtCore.QThread):
|
||||
if GUI.ColorBox.isChecked():
|
||||
argv.append("--forcecolor")
|
||||
for i in range(GUI.JobList.count()):
|
||||
# Make sure that we don't consider any system message as job to do
|
||||
if GUI.JobList.item(i).icon().isNull():
|
||||
currentJobs.append(str(GUI.JobList.item(i).text()))
|
||||
currentJobs.append(unicode(GUI.JobList.item(i).text()))
|
||||
GUI.JobList.clear()
|
||||
for job in currentJobs:
|
||||
time.sleep(0.5)
|
||||
@@ -193,9 +200,9 @@ class WorkerThread(QtCore.QThread):
|
||||
return
|
||||
if not self.errors:
|
||||
if str(GUI.FormatBox.currentText()) == 'CBZ':
|
||||
self.emit(QtCore.SIGNAL("addMessage"), 'Creating CBZ file... Done!', 'info', True)
|
||||
self.emit(QtCore.SIGNAL("addMessage"), 'Creating CBZ file... <b>Done!</b>', 'info', True)
|
||||
else:
|
||||
self.emit(QtCore.SIGNAL("addMessage"), 'Creating EPUB file... Done!', 'info', True)
|
||||
self.emit(QtCore.SIGNAL("addMessage"), 'Creating EPUB file... <b>Done!</b>', 'info', True)
|
||||
if str(GUI.FormatBox.currentText()) == 'MOBI':
|
||||
tomeNumber = 0
|
||||
for item in outputPath:
|
||||
@@ -209,7 +216,8 @@ class WorkerThread(QtCore.QThread):
|
||||
try:
|
||||
self.kindlegenErrorCode = 0
|
||||
if os.path.getsize(item) < 367001600:
|
||||
output = Popen('kindlegen "' + item + '"', stdout=PIPE, stderr=STDOUT, shell=True)
|
||||
output = Popen('kindlegen -locale en "' + item.encode(sys.getfilesystemencoding()) +
|
||||
'"', stdout=PIPE, stderr=STDOUT, shell=True)
|
||||
for line in output.stdout:
|
||||
# ERROR: Generic error
|
||||
if "Error(" in line:
|
||||
@@ -238,27 +246,35 @@ class WorkerThread(QtCore.QThread):
|
||||
if self.kindlegenErrorCode == 0:
|
||||
if len(outputPath) > 1:
|
||||
self.emit(QtCore.SIGNAL("addMessage"), 'Creating MOBI file (' + str(tomeNumber) + '/'
|
||||
+ str(len(outputPath)) + ')... Done!', 'info',
|
||||
True)
|
||||
+ str(len(outputPath)) + ')... <b>Done!</b>',
|
||||
'info', True)
|
||||
else:
|
||||
self.emit(QtCore.SIGNAL("addMessage"), 'Creating MOBI file... Done!', 'info', True)
|
||||
self.emit(QtCore.SIGNAL("addMessage"), 'Removing SRCS header...', 'info')
|
||||
self.emit(QtCore.SIGNAL("addMessage"), 'Creating MOBI file... <b>Done!</b>', 'info',
|
||||
True)
|
||||
self.emit(QtCore.SIGNAL("addMessage"), 'Cleaning MOBI file...', 'info')
|
||||
os.remove(item)
|
||||
mobiPath = item.replace('.epub', '.mobi')
|
||||
shutil.move(mobiPath, mobiPath + '_tostrip')
|
||||
shutil.move(mobiPath, mobiPath + '_toclean')
|
||||
try:
|
||||
kindlestrip.main((mobiPath + '_tostrip', mobiPath))
|
||||
# MOBI file produced by KindleGen is hybrid. KF8 + M7 + Source header
|
||||
# KindleSplit is removing redundant data as we need only KF8 part for new Kindle models
|
||||
if profile in ['K345', 'KHD', 'KF', 'KFHD', 'KFHD8', 'KFHDX8', 'KFA']:
|
||||
newKindle = True
|
||||
else:
|
||||
newKindle = False
|
||||
mobisplit = kindlesplit.mobi_split(mobiPath + '_toclean', newKindle)
|
||||
open(mobiPath, 'wb').write(mobisplit.getResult())
|
||||
except Exception:
|
||||
self.errors = True
|
||||
if not self.errors:
|
||||
os.remove(mobiPath + '_tostrip')
|
||||
self.emit(QtCore.SIGNAL("addMessage"), 'Removing SRCS header... Done!', 'info', True)
|
||||
os.remove(mobiPath + '_toclean')
|
||||
self.emit(QtCore.SIGNAL("addMessage"), 'Cleaning MOBI file... <b>Done!</b>', 'info',
|
||||
True)
|
||||
else:
|
||||
shutil.move(mobiPath + '_tostrip', mobiPath)
|
||||
os.remove(mobiPath + '_toclean')
|
||||
os.remove(mobiPath)
|
||||
self.emit(QtCore.SIGNAL("addMessage"),
|
||||
'KindleStrip failed to remove SRCS header!', 'warning')
|
||||
self.emit(QtCore.SIGNAL("addMessage"),
|
||||
'MOBI file will work correctly but it will be highly oversized.', 'warning')
|
||||
'KindleUnpack failed to clean MOBI file!', 'error')
|
||||
else:
|
||||
epubSize = (os.path.getsize(item))/1024/1024
|
||||
os.remove(item)
|
||||
@@ -299,18 +315,11 @@ class Ui_KCC(object):
|
||||
dnames = dirDialog.selectedFiles()
|
||||
else:
|
||||
dnames = ""
|
||||
# Lame UTF-8 security measure
|
||||
for dname in dnames:
|
||||
try:
|
||||
str(dname)
|
||||
except Exception:
|
||||
QtGui.QMessageBox.critical(MainWindow, 'KCC Error', "Path cannot contain non-ASCII characters.",
|
||||
QtGui.QMessageBox.Ok)
|
||||
return
|
||||
if str(dname) != "":
|
||||
if unicode(dname) != "":
|
||||
if sys.platform == 'win32':
|
||||
dname = dname.replace('/', '\\')
|
||||
self.lastPath = os.path.abspath(os.path.join(str(dname), os.pardir))
|
||||
self.lastPath = os.path.abspath(os.path.join(unicode(dname), os.pardir))
|
||||
GUI.JobList.addItem(dname)
|
||||
|
||||
def selectFile(self):
|
||||
@@ -318,21 +327,22 @@ class Ui_KCC(object):
|
||||
self.needClean = False
|
||||
GUI.JobList.clear()
|
||||
if self.UnRAR:
|
||||
fnames = QtGui.QFileDialog.getOpenFileNames(MainWindow, 'Select file', self.lastPath,
|
||||
'*.cbz *.cbr *.zip *.rar *.pdf')
|
||||
if self.sevenza:
|
||||
fnames = QtGui.QFileDialog.getOpenFileNames(MainWindow, 'Select file', self.lastPath,
|
||||
'*.cbz *.cbr *.cb7 *.zip *.rar *.7z *.pdf')
|
||||
else:
|
||||
fnames = QtGui.QFileDialog.getOpenFileNames(MainWindow, 'Select file', self.lastPath,
|
||||
'*.cbz *.cbr *.zip *.rar *.pdf')
|
||||
else:
|
||||
fnames = QtGui.QFileDialog.getOpenFileNames(MainWindow, 'Select file', self.lastPath,
|
||||
'*.cbz *.zip *.pdf')
|
||||
# Lame UTF-8 security measure
|
||||
if self.sevenza:
|
||||
fnames = QtGui.QFileDialog.getOpenFileNames(MainWindow, 'Select file', self.lastPath,
|
||||
'*.cbz *.cb7 *.zip *.7z *.pdf')
|
||||
else:
|
||||
fnames = QtGui.QFileDialog.getOpenFileNames(MainWindow, 'Select file', self.lastPath,
|
||||
'*.cbz *.zip *.pdf')
|
||||
for fname in fnames:
|
||||
try:
|
||||
str(fname)
|
||||
except Exception:
|
||||
QtGui.QMessageBox.critical(MainWindow, 'KCC Error', "Path cannot contain non-ASCII characters.",
|
||||
QtGui.QMessageBox.Ok)
|
||||
return
|
||||
if str(fname) != "":
|
||||
self.lastPath = os.path.abspath(os.path.join(str(fname), os.pardir))
|
||||
if unicode(fname) != "":
|
||||
self.lastPath = os.path.abspath(os.path.join(unicode(fname), os.pardir))
|
||||
GUI.JobList.addItem(fname)
|
||||
|
||||
def clearJobs(self):
|
||||
@@ -347,6 +357,9 @@ class Ui_KCC(object):
|
||||
GUI.AdvModeButton.setStyleSheet('font-weight:Normal;')
|
||||
GUI.FormatBox.setCurrentIndex(0)
|
||||
GUI.FormatBox.setEnabled(False)
|
||||
GUI.NoRotateBox.setChecked(False)
|
||||
GUI.WebtoonBox.setChecked(False)
|
||||
GUI.ProcessingBox.setChecked(False)
|
||||
GUI.OptionsAdvanced.setEnabled(False)
|
||||
GUI.OptionsAdvancedGamma.setEnabled(False)
|
||||
GUI.OptionsExpert.setEnabled(False)
|
||||
@@ -354,6 +367,7 @@ class Ui_KCC(object):
|
||||
GUI.UpscaleBox.hide()
|
||||
GUI.NoRotateBox.hide()
|
||||
GUI.MangaBox.setEnabled(True)
|
||||
self.changeFormat()
|
||||
|
||||
def modeAdvanced(self):
|
||||
self.currentMode = 2
|
||||
@@ -379,12 +393,12 @@ class Ui_KCC(object):
|
||||
MainWindow.resize(420, 380)
|
||||
GUI.OptionsExpert.setEnabled(True)
|
||||
if KFA:
|
||||
GUI.ColorBox.setCheckState(2)
|
||||
GUI.ColorBox.setChecked(True)
|
||||
GUI.FormatBox.setCurrentIndex(0)
|
||||
GUI.FormatBox.setEnabled(False)
|
||||
else:
|
||||
GUI.FormatBox.setEnabled(True)
|
||||
GUI.MangaBox.setCheckState(0)
|
||||
GUI.MangaBox.setChecked(False)
|
||||
GUI.MangaBox.setEnabled(False)
|
||||
|
||||
def modeConvert(self, enable):
|
||||
@@ -438,29 +452,70 @@ class Ui_KCC(object):
|
||||
GUI.NoRotateBox.setChecked(True)
|
||||
GUI.QualityBox.setEnabled(False)
|
||||
GUI.QualityBox.setChecked(False)
|
||||
GUI.BorderBox.setEnabled(False)
|
||||
GUI.BorderBox.setChecked(False)
|
||||
self.addMessage('If images are color setting <i>Gamma</i> to 1.0 is recommended.', 'info')
|
||||
GUI.MangaBox.setEnabled(False)
|
||||
GUI.MangaBox.setChecked(False)
|
||||
self.addMessage('If images will be too dark after conversion: Set <i>Gamma</i> to 1.0.', 'info')
|
||||
else:
|
||||
GUI.NoRotateBox.setEnabled(True)
|
||||
GUI.QualityBox.setEnabled(True)
|
||||
GUI.BorderBox.setEnabled(True)
|
||||
if not GUI.ProcessingBox.isChecked():
|
||||
GUI.NoRotateBox.setEnabled(True)
|
||||
GUI.QualityBox.setEnabled(True)
|
||||
GUI.MangaBox.setEnabled(True)
|
||||
self.changeDevice(GUI.DeviceBox.currentIndex(), False)
|
||||
self.changeFormat()
|
||||
|
||||
def toggleNoSplitRotate(self, value):
|
||||
if value:
|
||||
GUI.RotateBox.setEnabled(False)
|
||||
GUI.RotateBox.setChecked(False)
|
||||
else:
|
||||
GUI.RotateBox.setEnabled(True)
|
||||
if not GUI.ProcessingBox.isChecked():
|
||||
GUI.RotateBox.setEnabled(True)
|
||||
self.changeDevice(GUI.DeviceBox.currentIndex(), False)
|
||||
self.changeFormat()
|
||||
|
||||
def changeDevice(self, value):
|
||||
if value == 12:
|
||||
def toggleProcessingBox(self, value):
|
||||
if value:
|
||||
GUI.RotateBox.setEnabled(False)
|
||||
GUI.RotateBox.setChecked(False)
|
||||
GUI.QualityBox.setEnabled(False)
|
||||
GUI.QualityBox.setChecked(False)
|
||||
GUI.UpscaleBox.setEnabled(False)
|
||||
GUI.UpscaleBox.setChecked(False)
|
||||
GUI.NoRotateBox.setEnabled(False)
|
||||
GUI.NoRotateBox.setChecked(False)
|
||||
GUI.BorderBox.setEnabled(False)
|
||||
GUI.BorderBox.setChecked(False)
|
||||
GUI.WebtoonBox.setEnabled(False)
|
||||
GUI.WebtoonBox.setChecked(False)
|
||||
GUI.NoDitheringBox.setEnabled(False)
|
||||
GUI.NoDitheringBox.setChecked(False)
|
||||
GUI.ColorBox.setEnabled(False)
|
||||
GUI.ColorBox.setChecked(False)
|
||||
GUI.GammaSlider.setEnabled(False)
|
||||
GUI.GammaLabel.setEnabled(False)
|
||||
else:
|
||||
GUI.RotateBox.setEnabled(True)
|
||||
GUI.QualityBox.setEnabled(True)
|
||||
GUI.UpscaleBox.setEnabled(True)
|
||||
GUI.NoRotateBox.setEnabled(True)
|
||||
GUI.BorderBox.setEnabled(True)
|
||||
GUI.WebtoonBox.setEnabled(True)
|
||||
GUI.NoDitheringBox.setEnabled(True)
|
||||
GUI.ColorBox.setEnabled(True)
|
||||
GUI.GammaSlider.setEnabled(True)
|
||||
GUI.GammaLabel.setEnabled(True)
|
||||
self.changeDevice(GUI.DeviceBox.currentIndex(), False)
|
||||
self.changeFormat()
|
||||
|
||||
def changeDevice(self, value, showInfo=True):
|
||||
if value == 9:
|
||||
GUI.BasicModeButton.setEnabled(False)
|
||||
GUI.AdvModeButton.setEnabled(False)
|
||||
self.addMessage('<a href="https://github.com/ciromattia/kcc/wiki/NonKindle-devices">'
|
||||
'List of supported Non-Kindle devices</a>', 'info')
|
||||
if showInfo:
|
||||
self.addMessage('<a href="https://github.com/ciromattia/kcc/wiki/NonKindle-devices">'
|
||||
'List of supported Non-Kindle devices</a>', 'info')
|
||||
self.modeExpert()
|
||||
elif value == 11:
|
||||
elif value == 8:
|
||||
GUI.BasicModeButton.setEnabled(False)
|
||||
GUI.AdvModeButton.setEnabled(False)
|
||||
self.modeExpert(True)
|
||||
@@ -468,11 +523,23 @@ class Ui_KCC(object):
|
||||
GUI.BasicModeButton.setEnabled(True)
|
||||
GUI.AdvModeButton.setEnabled(True)
|
||||
self.modeBasic()
|
||||
if value in [0, 1, 5, 6, 7, 8, 9, 12]:
|
||||
GUI.QualityBox.setCheckState(0)
|
||||
if value in [9, 11, 12, 13]:
|
||||
GUI.QualityBox.setChecked(False)
|
||||
GUI.QualityBox.setEnabled(False)
|
||||
self.QualityBoxDisabled = True
|
||||
else:
|
||||
if not GUI.WebtoonBox.isChecked() and not GUI.ProcessingBox.isChecked() \
|
||||
and str(GUI.FormatBox.currentText()) != 'CBZ':
|
||||
GUI.QualityBox.setEnabled(True)
|
||||
self.QualityBoxDisabled = False
|
||||
|
||||
def changeFormat(self):
|
||||
if str(GUI.FormatBox.currentText()) == 'CBZ':
|
||||
GUI.QualityBox.setChecked(False)
|
||||
GUI.QualityBox.setEnabled(False)
|
||||
else:
|
||||
GUI.QualityBox.setEnabled(True)
|
||||
if not GUI.WebtoonBox.isChecked() and not GUI.ProcessingBox.isChecked() and not self.QualityBoxDisabled:
|
||||
GUI.QualityBox.setEnabled(True)
|
||||
|
||||
def stripTags(self, html):
|
||||
s = HTMLStripper()
|
||||
@@ -482,24 +549,26 @@ class Ui_KCC(object):
|
||||
def addMessage(self, message, icon=None, replace=False):
|
||||
if icon:
|
||||
icon = eval('self.icons.' + icon)
|
||||
item = QtGui.QListWidgetItem(icon, ' ' + self.stripTags(message))
|
||||
item = QtGui.QListWidgetItem(icon, ' ' + self.stripTags(message))
|
||||
else:
|
||||
item = QtGui.QListWidgetItem(' ' + self.stripTags(message))
|
||||
item = QtGui.QListWidgetItem(' ' + self.stripTags(message))
|
||||
if replace:
|
||||
GUI.JobList.takeItem(GUI.JobList.count()-1)
|
||||
# Due to lack of HTML support in QListWidgetItem we overlay text field with QLabel
|
||||
# We still fill original text field with transparent content to trigger creation of horizontal scrollbar
|
||||
item.setTextColor(QtGui.QColor('transparent'))
|
||||
label = QtGui.QLabel(message)
|
||||
label.setStyleSheet('background-image:url('');background-color:rgba(255,0,0,0.5);')
|
||||
label.setOpenExternalLinks(True)
|
||||
if sys.platform == 'darwin':
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(11)
|
||||
label.setFont(font)
|
||||
item.setTextColor(QtGui.QColor("white"))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(self.listFontSize)
|
||||
label.setFont(font)
|
||||
GUI.JobList.addItem(item)
|
||||
GUI.JobList.setItemWidget(item, label)
|
||||
GUI.JobList.scrollToBottom()
|
||||
|
||||
def showDialog(self, message):
|
||||
QtGui.QMessageBox.critical(MainWindow, 'KCC Error', message, QtGui.QMessageBox.Ok)
|
||||
QtGui.QMessageBox.critical(MainWindow, 'KCC - Error', message, QtGui.QMessageBox.Ok)
|
||||
|
||||
def updateProgressbar(self, new=False, status=False):
|
||||
if new == "status":
|
||||
@@ -544,10 +613,12 @@ class Ui_KCC(object):
|
||||
event.ignore()
|
||||
if not GUI.ConvertButton.isEnabled():
|
||||
event.ignore()
|
||||
self.settings.setValue('settingsVersion', __version__)
|
||||
self.settings.setValue('lastPath', self.lastPath)
|
||||
self.settings.setValue('lastDevice', GUI.DeviceBox.currentIndex())
|
||||
self.settings.setValue('currentFormat', GUI.FormatBox.currentIndex())
|
||||
self.settings.setValue('currentMode', self.currentMode)
|
||||
self.settings.setValue('firstStart', False)
|
||||
self.settings.setValue('options', QtCore.QVariant({'MangaBox': GUI.MangaBox.checkState(),
|
||||
'RotateBox': GUI.RotateBox.checkState(),
|
||||
'QualityBox': GUI.QualityBox.checkState(),
|
||||
@@ -563,30 +634,74 @@ class Ui_KCC(object):
|
||||
'GammaSlider': float(self.GammaValue)*100}))
|
||||
self.settings.sync()
|
||||
|
||||
def __init__(self, UI, KCC):
|
||||
def handleMessage(self, message):
|
||||
MainWindow.raise_()
|
||||
MainWindow.activateWindow()
|
||||
if not self.conversionAlive:
|
||||
if self.needClean:
|
||||
self.needClean = False
|
||||
GUI.JobList.clear()
|
||||
if self.UnRAR:
|
||||
if self.sevenza:
|
||||
formats = ['.cbz', '.cbr', '.cb7', '.zip', '.rar', '.7z', '.pdf']
|
||||
else:
|
||||
formats = ['.cbz', '.cbr', '.zip', '.rar', '.pdf']
|
||||
else:
|
||||
if self.sevenza:
|
||||
formats = ['.cbz', '.cb7', '.zip', '.7z', '.pdf']
|
||||
else:
|
||||
formats = ['.cbz', '.zip', '.pdf']
|
||||
if os.path.isdir(message):
|
||||
GUI.JobList.addItem(message)
|
||||
elif os.path.isfile(message):
|
||||
extension = os.path.splitext(message)
|
||||
if extension[1].lower() in formats:
|
||||
GUI.JobList.addItem(message)
|
||||
else:
|
||||
self.addMessage('This file type is unsupported!', 'error')
|
||||
|
||||
def __init__(self, UI, KCC, APP):
|
||||
global GUI, MainWindow
|
||||
GUI = UI
|
||||
MainWindow = KCC
|
||||
profiles = sorted(ProfileData.ProfileLabels.iterkeys())
|
||||
# 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.settings = QtCore.QSettings('KindleComicConverter', 'KindleComicConverter')
|
||||
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.lastDevice = self.settings.value('lastDevice', 10, type=int)
|
||||
self.lastDevice = self.settings.value('lastDevice', 0, type=int)
|
||||
self.currentMode = self.settings.value('currentMode', 1, type=int)
|
||||
self.currentFormat = self.settings.value('currentFormat', 0, type=int)
|
||||
self.firstStart = self.settings.value('firstStart', True, type=bool)
|
||||
self.options = self.settings.value('options', QtCore.QVariant({'GammaSlider': 0}))
|
||||
self.options = self.options.toPyObject()
|
||||
self.worker = WorkerThread(self)
|
||||
self.versionCheck = VersionThread(self)
|
||||
self.conversionAlive = False
|
||||
self.needClean = True
|
||||
self.QualityBoxDisabled = False
|
||||
self.GammaValue = 1.0
|
||||
if sys.platform.startswith('darwin'):
|
||||
self.listFontSize = 11
|
||||
elif sys.platform.startswith('linux'):
|
||||
self.listFontSize = 8
|
||||
else:
|
||||
self.listFontSize = 9
|
||||
|
||||
self.addMessage('<b>Welcome!</b>', 'info')
|
||||
self.addMessage('<b>Remember:</b> All options have additional informations in tooltips.', 'info')
|
||||
if call('kindlegen', stdout=PIPE, stderr=STDOUT, shell=True) == 0:
|
||||
if self.firstStart:
|
||||
self.addMessage('Since you are using <b>KCC</b> for first time please see few '
|
||||
'<a href="https://github.com/ciromattia/kcc#important-tips">important tips</a>.', 'info')
|
||||
if call('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, shell=True) == 0:
|
||||
self.KindleGen = True
|
||||
formats = ['MOBI', 'EPUB', 'CBZ']
|
||||
versionCheck = Popen('kindlegen', stdout=PIPE, stderr=STDOUT, shell=True)
|
||||
versionCheck = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, shell=True)
|
||||
for line in versionCheck.stdout:
|
||||
if "Amazon kindlegen" in line:
|
||||
versionCheck = line.split('V')[1].split(' ')[0]
|
||||
@@ -608,7 +723,15 @@ class Ui_KCC(object):
|
||||
self.UnRAR = False
|
||||
self.addMessage('Cannot find <a href="http://www.rarlab.com/rar_add.htm">UnRAR</a>!'
|
||||
' Processing of CBR/RAR files will be disabled.', 'warning')
|
||||
sevenzaExitCode = call('7za', stdout=PIPE, stderr=STDOUT, shell=True)
|
||||
if sevenzaExitCode == 0 or sevenzaExitCode == 7:
|
||||
self.sevenza = True
|
||||
else:
|
||||
self.sevenza = False
|
||||
self.addMessage('Cannot find <a href="http://www.7-zip.org/download.html">7za</a>!'
|
||||
' Processing of CB7/7Z files will be disabled.', 'warning')
|
||||
|
||||
APP.connect(APP, QtCore.SIGNAL('messageFromOtherInstance'), self.handleMessage)
|
||||
GUI.BasicModeButton.clicked.connect(self.modeBasic)
|
||||
GUI.AdvModeButton.clicked.connect(self.modeAdvanced)
|
||||
GUI.DirectoryButton.clicked.connect(self.selectDir)
|
||||
@@ -618,7 +741,9 @@ class Ui_KCC(object):
|
||||
GUI.GammaSlider.valueChanged.connect(self.changeGamma)
|
||||
GUI.NoRotateBox.stateChanged.connect(self.toggleNoSplitRotate)
|
||||
GUI.WebtoonBox.stateChanged.connect(self.toggleWebtoonBox)
|
||||
GUI.ProcessingBox.stateChanged.connect(self.toggleProcessingBox)
|
||||
GUI.DeviceBox.activated.connect(self.changeDevice)
|
||||
GUI.FormatBox.activated.connect(self.changeFormat)
|
||||
KCC.connect(self.worker, QtCore.SIGNAL("progressBarTick"), self.updateProgressbar)
|
||||
KCC.connect(self.worker, QtCore.SIGNAL("modeConvert"), self.modeConvert)
|
||||
KCC.connect(self.worker, QtCore.SIGNAL("addMessage"), self.addMessage)
|
||||
@@ -627,13 +752,6 @@ class Ui_KCC(object):
|
||||
KCC.connect(self.versionCheck, QtCore.SIGNAL("addMessage"), self.addMessage)
|
||||
KCC.closeEvent = self.saveSettings
|
||||
|
||||
for profile in profiles:
|
||||
if profile != "Other":
|
||||
GUI.DeviceBox.addItem(self.icons.deviceKindle, profile)
|
||||
else:
|
||||
GUI.DeviceBox.addItem(self.icons.deviceOther, profile)
|
||||
GUI.DeviceBox.setCurrentIndex(self.lastDevice)
|
||||
|
||||
for f in formats:
|
||||
GUI.FormatBox.addItem(eval('self.icons.' + f + 'Format'), f)
|
||||
if self.currentFormat > GUI.FormatBox.count():
|
||||
@@ -641,7 +759,6 @@ class Ui_KCC(object):
|
||||
self.currentFormat = 0
|
||||
else:
|
||||
GUI.FormatBox.setCurrentIndex(self.currentFormat)
|
||||
|
||||
for option in self.options:
|
||||
if str(option) == "customWidth":
|
||||
GUI.customWidth.setText(str(self.options[option]))
|
||||
@@ -650,17 +767,29 @@ class Ui_KCC(object):
|
||||
elif str(option) == "GammaSlider":
|
||||
GUI.GammaSlider.setValue(int(self.options[option]))
|
||||
self.changeGamma(int(self.options[option]))
|
||||
elif str(option) == "StretchBox" or str(option) == "WebstripBox":
|
||||
pass
|
||||
else:
|
||||
eval('GUI.' + str(option)).setCheckState(self.options[option])
|
||||
for profile in ProfileData.ProfileLabelsGUI:
|
||||
if profile == "Other":
|
||||
GUI.DeviceBox.addItem(self.icons.deviceOther, profile)
|
||||
elif profile == "Separator":
|
||||
GUI.DeviceBox.insertSeparator(GUI.DeviceBox.count()+1)
|
||||
else:
|
||||
GUI.DeviceBox.addItem(self.icons.deviceKindle, profile)
|
||||
if self.lastDevice > GUI.DeviceBox.count():
|
||||
GUI.DeviceBox.setCurrentIndex(0)
|
||||
self.lastDevice = 0
|
||||
else:
|
||||
GUI.DeviceBox.setCurrentIndex(self.lastDevice)
|
||||
|
||||
if self.currentMode == 1:
|
||||
self.modeBasic()
|
||||
elif self.currentMode == 2:
|
||||
self.modeAdvanced()
|
||||
elif self.currentMode == 3:
|
||||
self.modeExpert()
|
||||
self.changeDevice(self.lastDevice)
|
||||
self.changeFormat()
|
||||
self.versionCheck.start()
|
||||
self.hideProgressBar()
|
||||
self.changeDevice(self.lastDevice)
|
||||
self.worker.sync()
|
||||
|
||||
610
kcc/KCC_rc.py
610
kcc/KCC_rc.py
@@ -2,8 +2,8 @@
|
||||
|
||||
# Resource object code
|
||||
#
|
||||
# Created: Pt 21. cze 18:23:49 2013
|
||||
# by: The Resource Compiler for PyQt (Qt v4.8.4)
|
||||
# Created: N 6. paź 13:26:15 2013
|
||||
# by: The Resource Compiler for PyQt (Qt v4.8.5)
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
@@ -1147,6 +1147,588 @@ qt_resource_data = "\
|
||||
\x8a\x6c\x56\x98\x9d\x8c\x34\x25\xf0\xff\x24\xff\x01\x04\xe4\x96\
|
||||
\x06\x80\x39\xb3\x6b\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\
|
||||
\x82\
|
||||
\x00\x00\x24\x35\
|
||||
\x89\
|
||||
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
|
||||
\x00\x00\x79\x00\x00\x00\x60\x08\x06\x00\x00\x00\x39\x23\xdd\x1a\
|
||||
\x00\x00\x20\x00\x49\x44\x41\x54\x78\xda\xed\x9d\xd9\x72\xe3\x48\
|
||||
\x92\xae\x3f\xf7\x88\x00\x48\x51\xca\xac\xaa\xae\xde\xe6\xe6\xbc\
|
||||
\xff\x23\xcd\xe5\x8c\x9d\x63\xd3\xdd\xb5\xe4\x22\x89\x24\x80\x08\
|
||||
\xf7\x73\x11\x01\x10\xa4\xa8\xcc\xac\x9e\xee\x92\x6a\x81\x19\x93\
|
||||
\x4c\x6e\xa0\xf0\x87\x6f\xbf\x2f\x21\xee\xfe\x9f\xfc\x7e\xfc\xaa\
|
||||
\x0f\xfd\xfd\x12\xfc\xfa\x8f\xf8\x5b\xfb\x83\xdd\x3d\x02\x5b\xdc\
|
||||
\x6f\x01\x41\x78\x00\x79\x14\x91\xf2\x3b\xc8\xaf\x0b\x28\x01\x10\
|
||||
\x11\xff\xc2\xf7\xa7\x19\x58\x87\x2d\x78\x00\x01\x1c\x9c\x5b\xf0\
|
||||
\x02\xf2\x01\xe4\xdd\xaf\x11\xec\xf8\x0b\x03\x37\xb9\x97\x3f\xe0\
|
||||
\xbe\xa5\x42\x64\x20\x23\x22\x47\x11\x39\x88\xe8\x71\xf5\x5e\x05\
|
||||
\x76\xe0\x77\xee\xdc\x00\x2a\xcb\x6b\xe0\x6e\x88\x0a\x52\xc1\x0e\
|
||||
\xee\xfe\x0d\xf8\x1d\xc8\xf7\x22\x7a\xff\x6b\x02\x59\x7e\x09\x8e\
|
||||
\x97\xbb\x8b\xbb\x7d\x05\xfe\x8d\x95\x12\xcc\x1c\x55\x41\x55\x4f\
|
||||
\x02\xe9\x4e\x05\x5b\xef\x45\x24\xe0\xdc\x39\x24\x58\xde\x82\x99\
|
||||
\xe1\x56\xc0\x0a\xe2\x8e\x89\x20\x21\xa2\x21\xd4\xf7\x34\xbd\x20\
|
||||
\x22\xef\x54\xf5\xbb\xdf\x41\xfe\xd9\x00\xb6\x1b\x37\xfb\x56\x84\
|
||||
\xcd\xe1\x70\xe0\xfe\xe1\x80\x51\x10\x01\x45\xe9\x62\xc7\xe6\xa6\
|
||||
\xa7\x4b\x1d\x88\x34\x48\xcf\x16\x48\x05\xb7\x64\xd4\x0d\xa1\xbd\
|
||||
\xad\xaa\x6a\x8a\x3b\x26\x01\x4d\x09\x15\x5d\x9e\x47\xe4\x5e\x55\
|
||||
\xff\xf6\xa5\x26\xe1\x77\x75\xfd\xcf\x49\x6f\x70\x2f\xdf\xe0\xfe\
|
||||
\xb5\xbb\xf3\xe1\xe3\x3d\x87\x69\x20\x86\x44\x6f\x37\xc4\x9c\x08\
|
||||
\x12\xd0\xe8\xa8\x2a\xa2\xba\x48\x22\x38\x66\x5e\xa5\x1b\xaa\xc4\
|
||||
\x9b\x20\xf3\x1b\xdc\xab\xca\x6e\x4b\x22\x94\x91\x5c\x26\x2c\x6d\
|
||||
\x08\x21\x00\x8e\x9b\xdf\x81\x8b\x6a\xf8\x9f\x5f\x3a\xd0\xaf\x12\
|
||||
\x64\x37\xbb\x33\x2f\xdf\xaa\x48\x1a\xc6\x89\x0f\x8f\xf7\x98\x39\
|
||||
\x37\xf6\x86\x34\xf6\xc4\x18\x88\x77\x82\x6e\xbd\xfe\x05\xde\x54\
|
||||
\xad\x43\xb1\x32\xab\xdc\x06\x98\x80\x80\xd5\x2f\xc6\x01\x97\x08\
|
||||
\x31\x22\xaa\xed\x7c\x85\x30\xee\xc9\xc7\x7b\x4a\xba\x21\xa5\x84\
|
||||
\xbb\x53\x8a\xdd\xba\xfb\x9f\x62\x4c\x7f\xff\x1d\xe4\x7f\xa5\x63\
|
||||
\x65\xe5\x5b\xf0\x3b\x01\xee\xef\x1f\x78\x1c\x0e\x44\xef\xd8\xe5\
|
||||
\x3b\x62\x8c\x84\xaf\x9c\xb0\x75\x24\x34\x60\x6d\x56\xc9\x05\xb7\
|
||||
\x8c\x68\x20\x84\x6e\x91\x68\x00\x2b\x05\xcf\x23\x8e\x43\xda\x20\
|
||||
\x21\x2e\x2f\x3b\x40\x48\x98\x26\x62\x1e\x18\x8f\x1f\x19\x6c\x47\
|
||||
\xd7\xf5\x0d\xe8\xf2\x16\x64\x8c\x31\xbe\xfb\x1d\xe4\xff\xe5\x61\
|
||||
\x56\xde\xb8\xdb\xb7\x22\xc4\x92\x0b\x1f\xde\xdf\x33\x92\xe9\xd8\
|
||||
\xb0\xe3\x0d\xf1\xad\x10\x6e\xbc\xd2\x37\x2e\x78\x03\xb7\x94\x0c\
|
||||
\x5e\x10\x29\xa8\x56\x05\x3c\xab\x69\x77\xa3\xe4\x11\x2b\x46\x08\
|
||||
\x09\xd1\x00\x1a\xea\xeb\x4e\x05\xbd\x71\x42\x96\x27\xb0\x42\x12\
|
||||
\x38\x1e\x3e\x32\xf8\x1b\x52\x97\xc0\x9d\x9c\xa7\x6f\x55\xe5\xa0\
|
||||
\x1a\x8e\xbf\x3b\x5e\xff\x24\x39\xe1\x56\xfe\xe8\xf8\x9d\x08\x1c\
|
||||
\x0e\x47\x1e\xdf\x8d\x78\x32\xd2\x26\xb2\x0b\xb7\x74\xdb\x00\xc1\
|
||||
\x71\x3b\x85\x40\x15\xdc\x8c\x88\x31\x9b\x4c\x6f\x3a\xbb\x85\xd1\
|
||||
\x40\x01\x8c\x52\x0c\xb8\x21\x76\x5b\x7c\xf9\x92\xd9\xbf\x12\xf2\
|
||||
\x74\x44\x0e\xef\x11\x7c\xd1\xfd\x8f\x59\xe9\x6e\xbf\x26\x06\xc5\
|
||||
\x01\x15\x19\xfa\x7e\xf3\xdf\xbf\x44\xfb\xfc\xa2\x92\xec\x66\xb7\
|
||||
\xe6\xe5\x8f\x02\x09\x8c\x8f\xef\xf7\xe4\xfb\x48\xd7\x6f\x49\x6f\
|
||||
\x9d\x4d\xda\xa0\xda\x24\xb3\x61\x93\x73\xa1\x94\x81\x18\x1c\x91\
|
||||
\x2a\x8b\x55\x32\xbd\x49\xa6\x2f\x8e\xd7\x34\x81\x8a\x83\x16\x44\
|
||||
\xe7\xf8\xf8\xe4\x9c\x39\x42\x3e\xee\x91\xe1\x03\x78\x69\x72\x5d\
|
||||
\x1d\xb6\x8d\x4c\xec\x1f\x3e\xb0\xbd\x7b\x8b\x88\x60\xee\xfd\x38\
|
||||
\x4d\x7f\x0a\x1a\x0e\xee\x9e\x10\x54\x44\x72\x50\x3d\x88\xc8\xf1\
|
||||
\x77\x49\xbe\x1a\xf7\x96\x6f\xdd\xec\x6b\x55\x61\x18\x27\x3e\xfe\
|
||||
\x78\xa0\xb3\x1d\xdb\xbb\x8e\xb8\x73\x34\x48\x03\xa4\x02\x66\x56\
|
||||
\x70\x07\x55\xa9\x36\xd6\x07\x82\x56\x47\x6a\xf6\xba\x7c\xf1\xc0\
|
||||
\xea\xf3\xe3\xe8\xd8\x08\xc1\x1d\x8d\x11\xd9\xdc\x22\x1a\x16\x69\
|
||||
\x2e\xfb\xf7\xe8\x74\x40\x04\x5c\x04\x44\x91\x10\x91\x90\x90\x90\
|
||||
\x70\x8d\x84\xb8\xa9\xde\xbb\x54\xa9\x07\x69\x21\xd8\xd9\xf1\x01\
|
||||
\xf8\xc7\x6b\x95\xf2\x9f\x1d\x64\x77\xef\xcc\xf2\x9f\x81\xad\x08\
|
||||
\x3c\xde\xef\x39\x3e\x18\xbb\xed\x2d\xfd\x5d\x40\xe2\xec\x0d\x55\
|
||||
\xf2\xa2\x94\x02\xcc\x9e\x32\x4c\xd3\x84\xaa\xe2\xee\xe4\xe9\x81\
|
||||
\x14\xed\x04\x30\xe7\x12\x2d\xe2\x94\xe2\x4c\x03\xe8\xe4\x04\x1c\
|
||||
\x57\xc1\x51\xbc\xbb\x25\x94\x23\x1a\x13\x12\x3b\x34\x26\x34\x44\
|
||||
\x44\x03\x22\x0d\xd4\x93\xd0\xaf\xec\xf7\xb3\xc7\x3b\x11\xf9\xee\
|
||||
\x37\x0f\xb2\x59\x79\xe3\x66\x7f\x14\x21\x94\x52\x78\x78\x38\xa0\
|
||||
\x96\xd8\xbd\xd9\xa2\x69\x96\x48\xa9\xe0\xe6\xaa\x3e\x43\x08\xa8\
|
||||
\xb6\xd8\xb5\x5d\xf0\xe3\x70\xac\xc4\x85\xc0\x34\x7c\xa0\xeb\xca\
|
||||
\xac\xff\x2f\x00\x37\x1a\xcb\xcd\x94\x13\x5a\x3a\xba\xd4\xa1\xa9\
|
||||
\x47\x62\x42\x35\xa0\x8d\xec\x94\x15\x79\x72\x75\x71\xc2\x5a\xd7\
|
||||
\x5f\xbf\x98\x22\xff\x25\x22\xc3\x6f\x12\xe4\xb5\x7a\x46\x84\x92\
|
||||
\x0b\xc3\x30\x92\x52\x4f\xd7\xcf\x81\xae\x60\x6e\xe4\x9c\x71\xaf\
|
||||
\xe0\x86\x10\x9b\x8d\x5c\x4b\x92\x60\x65\xe2\xb0\x7f\x47\xec\xde\
|
||||
\xe0\xee\x4c\xc3\x3b\x36\x7d\x59\x00\x76\x14\x21\x21\xda\xa1\xda\
|
||||
\xa1\xda\x37\xef\x5a\x9b\xca\x6d\x54\xe7\x05\x68\x7e\x8e\xe8\x8c\
|
||||
\x1c\x2d\x1b\xf2\x84\x49\x9b\xbd\xf4\x13\xc8\x7c\x50\xd5\xbf\xff\
|
||||
\xe6\x40\x6e\xde\xf3\x9f\xdd\x6d\x37\x5f\x3a\x37\x47\x43\xbd\xe0\
|
||||
\xee\x60\xe6\xe4\x69\xa4\x58\x21\xa5\x9e\x10\xe3\xb9\x9a\x5c\x81\
|
||||
\xec\x2e\x94\xfc\x0e\xe1\x81\xe3\x31\x10\xbb\xaf\xc9\x39\xa3\x3c\
|
||||
\x92\xba\x0e\x91\x1e\x0d\x3d\x41\x53\xb3\xa5\x72\x0d\x46\x4e\x82\
|
||||
\x79\x8e\x92\xb0\xd2\xd3\x0e\x66\x05\x2b\x85\x3c\x4d\x4c\xd3\x44\
|
||||
\x1e\x47\x50\xe5\x66\xb7\xa3\xeb\xfb\xcb\x85\x62\xaa\xfa\x5f\x22\
|
||||
\x32\xfd\x66\x40\x76\xb7\xad\x59\xf9\x0b\x35\xd5\x87\xb7\xab\x37\
|
||||
\x5f\xf8\x52\x8c\x71\x1c\x70\x3b\xa0\x32\x12\xbb\xaf\x88\xf1\x06\
|
||||
\x3b\x0b\x73\x56\x36\xda\x21\x4f\x1f\x10\x3e\x36\x07\x2a\x61\x7e\
|
||||
\x47\xd7\x6d\x2a\xc3\xb5\x52\xbf\x4f\x00\xbd\x54\xb7\x17\x80\xba\
|
||||
\x19\x56\x0a\x25\x67\xa6\x71\x62\x1a\x07\xa6\x71\x24\x4f\x13\x65\
|
||||
\x9a\x30\x3f\xe9\x12\x07\x82\x2a\x7f\xfc\x8f\xff\xa0\xdf\x6c\xce\
|
||||
\x80\x16\x91\x1f\x54\xf5\x87\xdf\x44\x08\x55\xed\x6f\xf9\x93\x83\
|
||||
\xce\x24\xb1\x48\xbd\xce\xe3\x34\x31\x8d\x07\xb0\x03\xaa\x85\x18\
|
||||
\x1a\x6b\x55\x0c\x0b\x97\x12\xdc\x54\xa3\x19\xd3\xb8\x07\x31\xba\
|
||||
\xfe\x5b\x44\x66\x69\x9d\xbd\x5d\x59\xc2\xa7\xa7\xa0\x56\x30\x17\
|
||||
\x1a\xd3\xbd\x02\x3a\x4d\x94\x61\x20\x8f\x03\x65\x1c\xb0\x69\xc2\
|
||||
\xcd\x18\x8b\x93\xdb\x37\x0a\x95\x7f\xd1\x8b\x05\x63\x66\xec\x3f\
|
||||
\x7e\x20\xf5\x3d\x72\xbe\x90\xee\xdc\xfd\xc7\xd7\xe4\x69\xc7\x7f\
|
||||
\x83\xf4\xf6\x66\xf6\x95\x9b\xbd\x05\xa7\xc5\x1e\x14\x33\x86\xe1\
|
||||
\xc8\x70\x3c\x80\x1d\x89\x6a\x04\x55\xbc\x40\x1e\x85\x21\x43\xec\
|
||||
\x3f\x82\x2a\x2a\x5d\xb5\xad\x7e\xb2\x7f\x82\xb3\xd9\xee\xd0\x90\
|
||||
\x50\x79\x1a\xc6\x9c\xc2\xa7\x95\xa4\x36\xe7\xcc\xcd\xab\x84\x0e\
|
||||
\x03\xe3\xf1\xc8\x74\x3c\x32\x8d\x23\x9d\x67\xd4\x1a\x90\x02\x41\
|
||||
\x2a\x98\xdb\x24\x1c\x0a\x64\x7b\xde\x09\x0b\x80\x1f\xf7\x4c\xc3\
|
||||
\x40\xb7\xd9\x80\xfb\xbc\xcc\x3a\x87\x1b\x81\xc7\x5f\x15\xc8\x35\
|
||||
\x63\x64\x3b\x37\x7b\x63\x6e\x37\x32\x8b\x2d\x30\x8d\x13\xc3\xf1\
|
||||
\x80\x8f\x7b\xd4\x33\x37\x0a\xa1\x49\x9f\x60\x14\x83\xa3\x43\xea\
|
||||
\x8d\x18\xab\x44\x15\xd9\x81\xee\x08\x21\x35\x15\xac\x4d\x62\x9f\
|
||||
\x3a\x3f\x17\xee\x6d\xb3\xf3\x4d\x52\x87\x81\x3c\x1c\x19\x8e\x47\
|
||||
\x8e\xfb\x03\x6e\xb6\x38\x5d\x02\xc4\x28\xf4\xb1\x2e\x26\xb9\x30\
|
||||
\xd6\xbb\x28\x3c\x66\x21\x9b\x73\x69\xd5\x65\x4e\x80\x58\x61\x7c\
|
||||
\x7c\xa8\x20\x9f\xff\xae\x3b\x44\x7e\xf9\x20\x57\x8f\xd9\xb7\xee\
|
||||
\xe5\xce\xcd\x77\x40\x9c\x93\xb5\x53\x2e\x8c\xc7\x23\x8f\xfb\x03\
|
||||
\xa1\x1c\x79\x9b\x0a\x31\x54\xe0\xe7\xf5\xee\x02\xe6\xce\x61\x72\
|
||||
\x3c\x08\x94\x44\xd6\xb7\xa4\x6e\xbb\x02\xf7\x1a\xb0\x4f\x9d\xa5\
|
||||
\xd9\x0e\x94\x71\x24\x1f\x0f\xe4\xc3\x9e\x32\x1c\x60\x2a\x08\xd0\
|
||||
\x29\x68\x50\x06\x83\x33\xc5\xee\xa0\xba\x44\x6e\x67\x96\x5c\xcc\
|
||||
\xb9\x89\xc2\xe3\x24\xd8\xda\xe6\xb6\xf7\xa8\x40\x14\x21\xef\x1f\
|
||||
\x29\x6f\xbf\x22\xc4\x78\x5a\x74\xee\x3b\x77\x0f\xaf\xa5\x94\x28\
|
||||
\xfe\x13\xea\xb8\xab\x74\xa4\xdd\xe1\xf4\x33\xb0\xb9\x94\xea\xac\
|
||||
\x1c\xf7\xe8\x74\x24\x92\xe9\x8a\x10\x83\x10\x82\xb4\x54\x1f\x78\
|
||||
\x93\x5e\x11\x20\x44\x6e\x76\x1b\x88\x3b\x24\xf6\x68\x08\x8b\x2a\
|
||||
\x5e\x83\xfb\xac\xc4\x9a\x55\x69\x3d\x3c\x92\xf7\x7b\x6c\x3c\x22\
|
||||
\xc5\xd1\x06\xac\x68\x3b\x8f\x43\xa7\x4e\xea\x23\xfb\xb1\x34\xf5\
|
||||
\x3f\x2f\x18\x01\x39\x07\x71\x7e\xa0\xee\xdc\x44\xe5\x71\xf2\xa7\
|
||||
\x92\x5c\xf9\x6c\x98\x26\xa6\xe3\x91\x70\x7b\xbb\x7e\x4f\x70\xd8\
|
||||
\x0a\x3c\xfc\x62\x40\xae\xb5\x55\xb6\x73\xb3\x5b\x77\xdf\xd2\x28\
|
||||
\x86\xca\x0f\x8f\x4c\xc3\x11\xc6\x03\xd1\x47\x76\x0a\x21\xd6\x4b\
|
||||
\xd5\x05\x23\xbb\x90\xad\x39\x3e\x18\xfb\x12\xb0\xb8\x61\xd3\xdf\
|
||||
\x10\xbb\x0d\x1a\x62\x55\xc7\xb2\x8a\x49\x39\xf7\xaa\x2f\x55\x71\
|
||||
\x1e\x47\x86\xc7\x47\x38\x3c\xe2\xc3\x01\xb1\x59\xb2\x40\x02\x57\
|
||||
\x01\x73\x73\x92\x64\x6e\xfb\xc0\xe3\x60\x98\x7b\xf5\x98\x45\x4f\
|
||||
\xc5\x04\x57\x6c\x6f\xc4\xd8\x46\x61\x9f\x7d\x01\x77\x4e\x6c\xa8\
|
||||
\x80\x3a\x4c\x87\x47\xfa\xdd\xed\xb9\x5a\x77\xbf\x45\xe4\xf5\x83\
|
||||
\xec\xee\x92\xa7\xe9\x4f\xee\xf6\xf6\xa4\x3a\xbd\xad\x66\x61\xca\
|
||||
\x13\x0f\xef\x7f\x64\xc7\xc8\x36\x09\x26\xd2\x12\xf7\x8e\x69\x62\
|
||||
\x8c\x37\x78\xec\x49\x31\x34\x02\x2a\xb3\x89\x89\x10\xbb\x85\x0f\
|
||||
\x56\x39\xa9\x64\xff\x84\xd4\xe6\x69\x62\xd8\xef\x19\xee\xef\x99\
|
||||
\x0e\x07\xdc\x9d\xad\xc0\x26\x56\x2f\x48\x3e\x17\x2b\xb6\x13\x44\
|
||||
\x2b\x67\x40\x9f\x2d\x86\x8b\xe0\x6b\x7e\xbe\x53\xa7\x04\x61\x2c\
|
||||
\x67\xa1\x12\x60\x04\x85\xe9\x78\xa0\xe4\x4c\x4c\x91\x95\xb7\xb8\
|
||||
\x75\x77\x79\x0d\x5e\x76\xfc\x0c\x4d\xe7\x1a\xc2\xbb\x52\x38\x4c\
|
||||
\x53\xbe\x43\xb8\x09\x41\xa5\x66\x65\x8c\x94\x12\x6f\xbf\xfd\x33\
|
||||
\xfb\x87\x8f\x94\xe1\x9e\x6d\x74\x0a\x01\xdb\x7e\x85\xf6\x3b\x36\
|
||||
\x2d\x19\xe0\xee\x75\xe5\xeb\x66\x91\x00\x59\x83\xfb\x44\x92\x04\
|
||||
\xb4\xaa\xe3\x71\xbf\xe7\xf0\xf1\x9e\x71\xff\x88\x97\xb2\x84\x33\
|
||||
\x02\xe4\xf6\x31\x5d\xa9\xd1\xcf\x6b\x25\x08\x56\xd8\x75\x81\x87\
|
||||
\xd1\x30\xaa\x57\x7d\xe6\x98\x5f\x61\xc0\x36\x01\x8a\x09\x65\x2e\
|
||||
\x29\x6a\x22\x2d\x02\xe4\x4c\x1e\x0e\xc4\xf4\x66\xfd\xa9\x04\x6c\
|
||||
\x80\xc3\xab\x57\xd7\x21\x84\x31\x84\x30\xd2\x75\x1f\x73\xce\xfd\
|
||||
\x38\x8e\xdf\x88\x70\x1b\x82\xca\x0c\xde\xcd\xdd\x5b\x86\xd8\xf1\
|
||||
\xe1\xe1\x3d\xdb\xb7\x7f\x20\xf6\x37\x98\x15\x4a\xc9\xa8\x0a\x61\
|
||||
\xf1\x8e\xf5\xcc\xde\x5e\x93\x5a\x80\x32\x4d\x4c\x8f\xf7\x94\xfd\
|
||||
\x23\x5e\x32\x62\x4e\x72\xa3\xac\xec\xe1\x0c\xc2\x68\xb0\x0d\x17\
|
||||
\xdc\x87\x70\x55\x42\xd7\xa2\x1a\x29\x6c\xa3\xe2\x73\x56\x69\xed\
|
||||
\x7c\xf9\x13\x53\x8d\xb8\xb3\x89\xc2\xe3\xd4\xec\xb1\x0a\xd2\xbc\
|
||||
\xf2\xe0\x90\x0f\x7b\xfc\xf6\x0e\x95\x75\xd1\x82\xdf\x88\xc8\xe1\
|
||||
\x17\x61\x93\x97\x37\xc7\x38\x84\x10\xfe\x36\x8e\xc3\xff\xc9\xb9\
|
||||
\x74\x21\x68\xcb\xd1\x7a\x65\x7e\xf4\x1b\xb2\x55\x49\x51\x11\x34\
|
||||
\x68\x55\xc7\x8d\x5e\x7c\x36\x09\x20\x8a\xbb\x91\xf7\x7b\xa6\x87\
|
||||
\x8f\xd8\xfe\x11\x29\x46\xd4\x2a\x31\x1a\x14\xb6\x91\xec\xc2\x30\
|
||||
\x19\x39\x9f\x9c\xa7\xb1\x54\x27\x2b\xc8\x97\xff\x1d\xb3\x4f\xd7\
|
||||
\x89\xe1\x21\x41\x29\x67\x2b\x62\xf1\xf9\x2e\x24\x3c\x89\xd3\x05\
|
||||
\x61\x28\xde\x24\xd9\x9b\xc9\x81\x69\x38\x62\xb9\xa0\x31\x2c\x96\
|
||||
\xbb\xd5\x7b\xff\xf0\x8b\x02\xd9\xdd\xd5\xad\xfc\x35\xa5\xd0\xb9\
|
||||
\x19\xc7\xc3\xb1\xf2\xb7\x38\x66\xd0\x77\x3d\x2a\x8a\xa8\x2c\xe0\
|
||||
\xea\xb3\xf6\xb6\xaa\xeb\x52\x32\xd3\xe3\x47\xa6\x87\x8f\xf8\xf1\
|
||||
\x48\x58\x42\x9e\x95\x64\x15\x43\x8a\x91\x54\x48\x5d\xa0\xf4\x1d\
|
||||
\xc3\x64\x4c\x63\xa6\xb8\x33\x14\x61\x17\x7f\xba\xe9\x13\x40\x2d\
|
||||
\x5f\x55\xf5\x7e\x01\xf8\xfc\xff\x5e\x9d\xc9\xea\x6f\x9f\x25\x3d\
|
||||
\x08\xe4\x3c\x91\xc7\x81\x98\x76\x27\xb5\xe0\xde\xbb\x7b\x14\x91\
|
||||
\xfc\x8b\x00\xd9\xdd\xc5\xad\xfc\xd5\xf1\x9d\x15\xe3\xc3\xfb\x1f\
|
||||
\xe9\x52\xc2\xba\x1e\x11\x6d\x29\xc1\x6b\xe0\x3e\xf5\x92\x01\xf2\
|
||||
\x38\xb2\xbf\xbf\xe7\x78\x7f\x4f\x9f\x27\xfa\x00\x41\x59\xd5\x45\
|
||||
\x3f\x55\xbf\xee\x8e\x8c\x99\x20\x99\x5d\x0c\x94\x5d\xc7\x71\x32\
|
||||
\xc6\x31\x33\x39\x74\x72\x55\x6b\x7f\x86\x7f\x75\xae\xb1\xdd\x72\
|
||||
\xc5\x09\x73\xaa\x07\xdf\x07\x39\xef\x14\x14\xd0\x02\xf9\x78\x80\
|
||||
\xdd\xee\xf4\x59\x11\x75\xf7\x8d\xbc\xb0\x97\x1d\x7f\x12\xc0\x6e\
|
||||
\x3b\x73\xf8\xf1\xbb\xef\x89\x29\xb2\xb9\x7d\x5b\x9d\x90\x06\x6a\
|
||||
\xf5\x98\xab\xdd\xbd\x96\x10\x00\x18\x8f\x47\xf6\x1f\x3e\x70\x7c\
|
||||
\x78\x00\x33\x02\x50\x44\x10\xf1\x53\x1f\xcb\xa7\x80\x9a\x01\xcf\
|
||||
\x85\x20\x85\xdb\x10\x18\x6f\x3a\x72\x2e\xad\xe6\xeb\x0a\x3d\xf5\
|
||||
\xc5\xd9\x9a\xeb\x60\x3f\xf1\xb6\x03\xc8\x45\x6c\xad\x02\x79\x38\
|
||||
\x62\x66\xcb\x02\x6f\xef\xdf\xf0\xc2\xf1\x72\xfc\x42\x80\xff\xe2\
|
||||
\x6e\xb7\x06\x7c\xfc\xfe\x7b\x42\xce\xf4\x6f\xbe\x22\x97\x42\x10\
|
||||
\xad\xd5\x52\xb1\xd2\x8f\x6b\xb5\x3c\xc7\x93\xb8\x33\xec\xf7\x3c\
|
||||
\x7e\xf8\xc0\xf0\xf8\x88\xb8\x13\xa4\x49\x7d\x3b\xcf\x3e\x57\x95\
|
||||
\x1b\xf5\x33\x61\xd0\xe5\xef\xcb\x85\x4e\x0b\x29\x26\x30\x85\x46\
|
||||
\x5d\x7e\xb9\x28\x7f\x81\xe8\x5f\x58\x02\xc5\xa0\x54\xd6\x6e\x61\
|
||||
\xc0\x14\x7c\x1a\x28\xd3\x44\x58\xa5\x20\x6b\x83\xdd\x2b\xb7\xc9\
|
||||
\x2d\x17\x7c\xe7\x0e\x1f\x3f\xbe\xe3\xb8\x7f\xe0\xe6\xcd\x37\x4c\
|
||||
\xb9\xda\xb2\x0c\xc4\x18\x48\x5d\x3a\x2b\xaa\x9b\x45\xea\xf8\xf8\
|
||||
\xc8\xc3\xfb\xf7\x8c\xfb\x7d\xe5\x8b\x67\x89\xbf\x88\x6b\x1c\x78\
|
||||
\x2c\xc2\xad\x38\x51\x7e\x82\x10\xce\xce\x51\x9e\xbe\xe8\x03\xd7\
|
||||
\x04\xfd\x4a\x00\x57\x9f\x6b\x0b\x54\x2e\xcc\x00\xfe\x14\x79\x11\
|
||||
\x10\x33\xf2\x78\x4a\x58\xb4\xef\xea\x5e\x9a\xe2\xfc\x24\xc8\x56\
|
||||
\xf2\x9f\xcd\xca\x1b\x10\x3e\x7e\xfc\xc8\xe1\xdd\x07\x74\x13\xc8\
|
||||
\x2d\x36\xb4\xa5\xfc\xb1\x3b\x79\xcd\xf3\x0a\x36\xe3\xdd\x77\xdf\
|
||||
\x71\xb8\xbf\x27\x34\x70\xc3\x4a\x72\x2f\xe2\xf1\x25\x74\x79\xcc\
|
||||
\xc2\x6d\x72\xc2\x35\xdd\xf9\x49\x91\x3e\xc5\xad\x73\xc2\xc1\x3f\
|
||||
\x15\x4e\xad\xde\x7b\x15\x69\x40\xbb\x88\xe7\x82\x15\xbb\x1a\x9b\
|
||||
\x9d\x35\xc9\x51\x0b\x06\xcb\x70\xc4\xfd\xcd\xc2\xce\xb5\x84\x55\
|
||||
\xf7\x92\xf1\x72\xfc\x04\xc0\x7f\x32\x2b\x6f\x1d\x61\xff\xf8\xc8\
|
||||
\xf8\xe3\x3b\x7a\x87\x71\x04\xeb\x6a\x35\xa4\x79\x05\x33\x14\xc3\
|
||||
\xcc\x4f\xa5\x35\x22\x1c\x1e\x1e\x78\xbc\xbf\xa7\x6f\x6a\x59\xbf\
|
||||
\x40\xb2\x66\x89\xa9\xaa\xbb\x91\x14\x5f\x2a\x9d\x2b\x2f\x58\xe4\
|
||||
\x5c\x22\xe5\x9a\x79\x96\xf3\x73\x3e\x75\xaf\xeb\x2a\xd0\x14\x30\
|
||||
\xf3\xab\x8b\x60\xa1\xbe\x57\xe7\x2d\xe3\x80\x59\x4d\xa3\xae\xf8\
|
||||
\x80\xcd\x4b\xc6\xcb\xfa\x0c\xc0\xdf\x9a\x95\xaf\x1c\x38\x1c\x0f\
|
||||
\x7c\x7c\xf7\x23\x8a\x63\x02\x5a\x0c\x2f\x65\x21\x25\x44\x84\x62\
|
||||
\x05\x6b\xb6\x70\xf1\xb5\xdc\x49\x02\x29\x06\x62\xd0\x96\x2e\xd4\
|
||||
\x53\x9d\xd5\x59\x68\x75\xee\xa3\x15\x87\x7d\x91\x33\x60\xe4\x13\
|
||||
\xb7\x9f\xa2\x8e\xfd\x13\x9e\xf4\x39\x78\xf3\x82\x75\x74\xe5\x28\
|
||||
\x7c\xea\x73\xd5\x2e\x4f\x94\x9c\x2f\xb3\x67\xfd\xab\xb2\xc9\x66\
|
||||
\xe5\x6b\xb3\xf2\x4d\xad\x5b\x9e\xd8\x7f\xfc\x81\xbe\x2b\x8c\x08\
|
||||
\x31\xd7\x32\x0f\x3b\xec\xf1\x7e\x03\xa9\x6b\x9f\xb1\xea\x84\xb5\
|
||||
\xb2\x59\x77\xe8\x37\x3d\x6f\xb6\x89\xa4\x61\x59\xed\xac\x8b\xe8\
|
||||
\x56\x00\x9b\xb7\xda\xea\xa6\x11\xcc\x9c\xa9\x38\x8f\x54\x67\x4c\
|
||||
\x3e\x69\x38\xaf\x3c\x27\x27\xb7\x60\xb9\xe7\xe9\x73\x4f\xc4\xdc\
|
||||
\xaf\xb3\x26\x21\x80\x9b\x56\xb5\x7d\x75\x15\xc9\xc9\x2e\x97\x42\
|
||||
\x99\x46\xe8\xfb\xd7\x09\xb2\x59\x79\x6b\x25\xff\x71\x66\xb1\xf6\
|
||||
\x8f\x0f\xad\x89\x0c\xfa\x8d\x33\x0e\x42\x9c\x84\x50\x0a\xb6\x7f\
|
||||
\xc4\x6f\x6b\x31\xba\x5b\xad\xb2\xec\xbb\xb4\xf4\xfe\x6a\x4c\x04\
|
||||
\x04\xc6\xe3\x52\xa1\xb1\x96\xbc\x99\xbf\x9e\x13\x10\x04\xc1\x53\
|
||||
\xc0\x11\x0c\xa1\x98\x33\x4d\xc6\xe0\x99\x8d\xd8\x75\x3b\xfc\x89\
|
||||
\xe7\xd6\xf6\xd6\xd7\x4e\x1a\x4f\xc1\x5f\x33\x5c\x2d\xc0\xbd\xd0\
|
||||
\xe5\x10\x92\x60\x26\xd7\xcf\xbf\xf0\xd8\x82\xe0\x94\x61\xc0\x6f\
|
||||
\xef\xd6\x3f\x24\xbd\xa4\xf3\x15\x57\x00\xdf\xb9\x95\x3f\xcf\x04\
|
||||
\x86\xb9\xb3\xdb\xdd\x32\x76\x7d\xad\xec\x28\x07\x62\x57\x30\x1a\
|
||||
\xd0\x38\xa5\x14\x3c\xa6\x4a\x6e\xb4\x52\xda\xe5\x82\x69\x40\x37\
|
||||
\x5b\xfc\x7e\x44\xf4\x7a\xa2\xa0\x7e\xc0\x9e\xd4\x00\x44\x11\x92\
|
||||
\x2a\x7d\x17\x30\xe9\xf0\x3c\x21\x56\x7e\x62\xd0\x2b\x48\x17\xf1\
|
||||
\x9c\x61\x76\x9c\x56\x26\x62\x0d\xbe\x5f\xb1\xb3\x7e\xa1\x2d\x44\
|
||||
\x9c\x90\x94\x32\xd9\xb9\x20\x07\xc5\xed\x54\x5b\xa6\x80\x4d\x03\
|
||||
\xee\x8e\x4a\xab\x21\x37\xd3\xa0\xda\xbd\x94\x5d\x5e\x2e\x7f\xce\
|
||||
\x25\x4d\xb9\x14\x6b\x75\x4d\x22\x95\xe4\xe8\xfb\x9e\xbb\x37\x6f\
|
||||
\xd9\xde\x7d\x8b\xc6\x3b\xbc\x53\xc6\x50\x59\x22\x2d\x79\xc9\x26\
|
||||
\x95\x52\x5a\x6f\xf0\x49\x25\xeb\xe6\xe6\xa9\xd0\x35\x71\x3e\x0d\
|
||||
\x05\x90\x53\x75\x47\x7b\xd2\xbd\xb6\x9b\x32\x8d\xe8\x38\x20\x6e\
|
||||
\xd7\x01\xbe\x66\xb0\x57\x14\xaa\x28\xe8\xcd\x06\xd9\x6e\x20\x84\
|
||||
\x67\x0b\xe7\x9f\xc9\xc0\x21\x6b\xb5\x50\xd7\x2d\x12\xe4\x5c\xab\
|
||||
\x8b\x20\x7a\xfa\x21\xaa\x60\xd3\x88\x95\x82\xb9\x53\x4e\x71\x7b\
|
||||
\xf7\xe2\xea\xba\xeb\xba\x1f\xcd\xec\x43\x29\xe5\x26\xe7\xe9\x4f\
|
||||
\x40\x98\xd5\x0f\x40\x8a\x91\x74\xfb\x86\x69\xba\x61\xaf\x0f\x1c\
|
||||
\x1e\xf6\xf4\x39\xd7\x84\xbb\x9c\xba\x1e\x52\x8c\x4b\x89\x8e\xf6\
|
||||
\x1b\x4a\x8c\xb5\xb3\x41\x9e\x89\x53\x9e\x73\x97\x5d\xaa\xd6\xf4\
|
||||
\x73\xd7\x58\x3e\xa7\xb2\x57\xa7\xb1\x31\x13\xb0\x3a\x85\xe0\xa6\
|
||||
\xc7\xb3\x61\xe3\xb4\x10\x26\xf2\x49\xfb\x2e\x4f\xdc\x71\xc1\x09\
|
||||
\x51\x30\x5b\x31\x7a\xf3\xda\x2c\xab\x70\x30\x67\xf2\x34\x11\xcf\
|
||||
\xab\x5b\x5e\x0c\x64\x3d\xf7\x0e\xb5\x84\x10\xb2\x4a\x4d\x23\x96\
|
||||
\x52\x6a\xf8\xc0\x89\x87\x8e\x31\x70\x77\xfb\x86\xcd\x57\x5f\x33\
|
||||
\x6a\xc0\x4b\x81\xd6\x9b\x34\xcd\x2a\xbb\xe9\x3b\x89\x11\xe9\x37\
|
||||
\xa7\x76\xd1\x4b\xbf\x58\xae\xdd\x9e\x91\xd2\xf3\x70\xf8\x93\xb7\
|
||||
\x85\x00\xb7\xb9\x73\xc6\x90\x3c\xa2\xea\x84\x9b\x1e\xe9\xbb\x56\
|
||||
\x6f\x56\x1b\xdd\xbc\xfd\x16\x9f\x35\x09\xb5\x46\x5c\xae\xac\x3e\
|
||||
\x95\xda\x8c\x77\xf2\xbb\x64\x69\x84\xf3\x39\x4f\xee\x4e\x99\xa6\
|
||||
\x4b\xf3\xf4\x3a\x40\x76\x77\x2d\x39\xff\xc5\x71\x5d\x17\xc0\x97\
|
||||
\x32\xb7\x75\x2e\x1d\xbc\x74\x5d\x62\xf3\xe6\x0e\x54\x96\x50\xaa\
|
||||
\xda\x65\x5b\x01\x23\xe8\x76\xc7\xb5\x9a\x80\xe7\xcd\xab\x9c\x8c\
|
||||
\xe2\x19\x72\x9f\x0b\xa4\x9e\x06\x56\xb5\x3e\xda\x4f\xc1\xac\x15\
|
||||
\xa4\x8c\x84\x28\x15\xec\x55\xf1\x9d\x5f\x04\xdd\xa2\xf2\x6c\xac\
|
||||
\x56\xb3\x89\x33\xb0\x55\x45\xcf\xaf\x97\xb9\x8c\xd7\xf2\xd9\xca\
|
||||
\x74\x3c\xb9\xbb\xbc\xa8\xba\x9e\xc3\x27\xc4\x93\xca\xa9\x02\x02\
|
||||
\xbc\x36\x71\x97\x82\x6a\x38\xd9\x1f\x07\x15\x25\x28\xb5\xec\xa7\
|
||||
\xa9\xec\x5c\x0a\xbd\xce\xf5\xf4\x8e\xf4\x5b\x46\x94\xcd\xb5\xec\
|
||||
\xd2\x73\x0e\x72\x0c\x27\x00\x6a\x8c\x55\xcb\x69\xe7\x3e\xe4\xa5\
|
||||
\x86\x56\xae\xc6\xb8\x67\x9e\x75\x01\x8f\xb3\x27\xcf\x02\x80\x88\
|
||||
\xa0\x9b\x88\xe4\x40\x19\xa6\xa7\xfa\x5a\xae\x50\x28\xd2\x64\x57\
|
||||
\x6a\x58\x35\xd9\xc9\xa3\x16\xa9\xd1\x40\xed\xe3\xaa\xe7\x58\xf7\
|
||||
\x42\xd7\x41\x25\x84\xc6\x04\xbf\x64\x9c\x2c\x8f\x66\xa8\xbb\xdf\
|
||||
\x8a\x48\x9a\x5b\x44\xe7\x58\xb8\x94\x42\x68\x85\x77\x97\xe1\x0a\
|
||||
\xb5\x51\x9b\x3c\x65\xfa\x94\x5a\x4d\x95\x13\x52\x22\xc7\x0d\x8f\
|
||||
\xc3\x81\x5d\x1f\xce\x52\x78\xd5\xf4\xfa\x53\xa0\x8a\x81\x16\xb4\
|
||||
\x0b\x8b\xb2\x71\xd1\x25\xd8\x75\xf3\xfa\x1e\xab\xc4\xcc\xa5\xaa\
|
||||
\x58\x00\x6e\x46\xdd\x0d\x24\xf2\x24\x96\x92\x32\x21\x21\xc0\xb6\
|
||||
\xab\x40\xb7\x32\x52\xc7\x4f\xed\x36\x67\x71\xf1\xc9\x78\x87\x00\
|
||||
\xb9\xd4\xff\x9b\x17\x8a\xf9\x62\x2a\x42\x0c\x58\x1e\xea\x40\xb8\
|
||||
\x53\xca\x55\xdd\x6b\x15\xef\x8b\x82\x1c\x42\x38\x86\x10\x8e\xee\
|
||||
\xfe\xc3\x34\x4d\x77\xa5\xe4\xaf\x54\x75\x09\xe4\x4b\x31\xa6\x69\
|
||||
\x22\x04\x6d\xed\xa4\xcb\xe8\xc2\x25\xdb\x34\x35\x4e\x5b\x5b\x41\
|
||||
\xb3\x88\xd0\xef\x76\x3c\xec\xf7\x90\x85\x6d\x70\x92\xae\xe5\xe6\
|
||||
\x3a\x11\xed\x63\xc6\xac\xa0\x51\x16\xb7\xa7\xaa\xcd\x5a\x94\x50\
|
||||
\x93\xcf\x01\xf7\xae\x02\xdf\x98\xb8\x05\x7c\xab\x92\x37\xab\x6c\
|
||||
\x45\xcf\xeb\x79\xe6\x73\x9b\xa1\xe2\xc8\x36\x51\x86\x82\x4d\xf9\
|
||||
\x44\x5f\x51\xae\xf3\xa7\xee\x20\xb5\xab\x63\x26\x73\x44\xc1\x33\
|
||||
\x68\x10\x34\x40\xc9\x23\x6e\x56\x17\xd1\xe9\xaf\xea\xe0\xe7\x9f\
|
||||
\x4a\x10\x9f\x09\x1f\xac\xeb\xba\x0f\xee\xe9\xe3\x34\x8d\x6f\xa7\
|
||||
\x29\x7f\x1d\x02\x09\x11\xa4\x50\xc3\xa5\x62\x2d\x9b\xd4\x88\xf8\
|
||||
\xa0\xe0\xb2\xbc\x16\x54\xab\x23\xe3\xd0\xef\x76\x3c\xfe\xf0\x03\
|
||||
\x66\xce\xde\x85\x4d\x70\xfa\xf0\x19\xf7\xba\xa9\x5a\x13\x16\xa0\
|
||||
\x5b\xe6\xa3\xad\x90\xb2\xba\xee\x8a\x44\x85\x94\x70\xa4\x4a\xfa\
|
||||
\x54\xb0\x5c\xc0\x0c\x2b\x8e\x39\x57\xf3\xd5\x73\x19\xa7\x58\x26\
|
||||
\xf4\x01\x24\x52\xc6\xb2\xd2\xd6\xab\x94\x98\x7b\x2d\x4c\xb4\x5a\
|
||||
\x9c\xa8\x0a\x22\x7a\xc6\x0f\xc4\x14\x10\x2f\xcd\xe9\x2b\x4d\x77\
|
||||
\x2f\x2a\x26\xbe\xb8\x4d\xbe\x02\xb6\x77\x5d\xff\x3e\xc6\x74\x3f\
|
||||
\x8e\xe3\xd7\x3e\x4d\x5f\x13\xaa\x3c\x58\x31\x72\xc9\x8b\x84\xcd\
|
||||
\xad\x31\xd6\xa4\xb9\x4b\x71\x71\x7f\x62\x4a\x74\x37\x5b\xca\xf1\
|
||||
\x08\xa2\x1c\x4a\x5d\xfd\xdb\x2f\xf8\x93\x3d\xb7\xbc\x6d\x90\x67\
|
||||
\xd8\xe9\x06\x7c\xb1\x45\xe2\x45\x05\xba\x80\xf6\xb1\xf6\x41\x8d\
|
||||
\xcd\x3e\x2a\x57\x72\x86\x27\x03\x22\x56\x08\x5d\x65\xdd\x50\x59\
|
||||
\xe6\x94\x54\x95\x6f\xd5\xa9\x5c\x0f\x7a\xd3\xf3\xc5\xa6\x41\x6a\
|
||||
\x88\x35\x39\xe2\xe0\x25\x43\xea\x57\x6d\xb7\x75\x0c\xe4\xab\xcb\
|
||||
\x27\xcf\xa1\xd5\x66\xb3\xf9\x3e\xc6\xf8\x30\x0c\xc3\x1f\x69\x89\
|
||||
\x70\x2f\xbe\xa4\xe1\x24\xc4\x93\xca\x9e\x26\x6c\xd3\x2f\x15\x12\
|
||||
\x88\xb0\x7b\x73\x47\xf1\x11\x49\x09\xb3\xea\x85\x8e\x5e\xe8\x96\
|
||||
\x00\xf3\xf9\x84\x7d\x99\xbc\xf6\x4f\xa9\x5c\x2d\x25\x7a\x9a\x61\
|
||||
\x71\x60\x6a\xda\x5d\xd1\x3e\x54\x9b\x5e\xc6\x2b\xcc\xcc\xf9\x63\
|
||||
\x71\x23\x75\x8a\x63\xb8\xe5\x3a\xad\xc0\xfd\x09\x23\xc6\xaa\x19\
|
||||
\x6f\xf6\xbe\x53\x1f\xc0\x4e\xa0\x7b\xc9\x97\x46\x28\xbe\x5a\x90\
|
||||
\x97\x37\xc7\x78\x0c\x21\xfc\xdf\x71\x1c\xbf\x3a\x0e\xc3\xb7\x82\
|
||||
\x48\xf6\x4c\x2e\x19\x4a\x46\x63\x9d\x7b\x55\x55\x76\x21\xa4\xd3\
|
||||
\xc2\x0d\xdd\x86\x52\x0a\xca\x40\x50\xa5\x53\x6d\x17\xde\x96\xca\
|
||||
\xcb\xe7\x89\x11\xb0\xd1\xd0\x5e\x9f\xf4\x46\x7d\x3e\xf7\xe8\xe0\
|
||||
\xd3\x8a\xbd\x7a\x6e\x31\xb5\x81\x32\x6e\x67\x69\xb1\x2f\xe5\xc8\
|
||||
\x6a\xd5\xa6\x9d\x27\x31\x2c\x5f\x2e\xd8\xf4\xea\x41\x9e\x55\x78\
|
||||
\x8c\x71\x48\xe3\xc1\x07\x5c\xe6\x46\x2f\x33\x5b\x32\x4d\xee\xce\
|
||||
\x38\xe5\xa5\xd3\x5f\xaa\xb1\x82\x7e\x83\x0d\x07\x82\x08\x6e\x65\
|
||||
\x95\x18\x90\xcf\x82\xe6\x0e\x36\x39\xa1\xfb\x29\xfc\x35\x57\x92\
|
||||
\xc5\xbe\x54\xa2\xcc\x33\x46\x96\x99\x8d\xfe\xe9\xa4\xb7\x3f\x53\
|
||||
\xfc\xe5\x4b\x08\x6a\xe7\xb9\xf1\x92\xcf\x06\xca\x54\x0f\xfb\xe7\
|
||||
\x4f\x54\xfc\x64\x90\x4b\xce\xb7\xc3\xe1\xe1\xaf\xe3\xfe\x83\x4c\
|
||||
\x06\xdd\x66\x47\x48\x11\xa6\xbc\x74\x4a\x98\x3b\x39\x67\x4a\x8a\
|
||||
\xa7\x6b\xa4\x8a\x6e\x77\x94\xc3\x1e\x72\x59\xc8\x2d\x39\xfd\xf3\
|
||||
\x2c\xde\x73\x36\xcf\x8b\x60\xd9\xd1\x24\x57\x00\xb9\x48\x33\xcc\
|
||||
\xe1\xd6\x02\x9e\xaf\x00\x7d\x26\xcd\x28\xeb\xb0\xf6\xfc\x2b\xaf\
|
||||
\xe6\xa4\x3f\xc5\xd4\x4a\x93\x64\x3f\x33\xff\xc1\x6b\x2d\xc4\xeb\
|
||||
\x05\xb9\xe4\x7c\x3b\x8e\xc7\xbf\x4e\xd3\x20\xa6\xd5\x8b\x1c\x3f\
|
||||
\xdc\x13\xb7\x37\x84\x18\xeb\xf4\x2c\x0d\x95\xd6\x2b\x65\xa9\x90\
|
||||
\x98\xed\xa4\xf4\x5b\x08\x4a\x29\x76\x9d\xc1\x94\x4f\x24\xf1\xe7\
|
||||
\xfb\x22\xa4\x46\x38\xf8\x25\xa8\x3f\x49\x25\x3d\x73\xbf\x06\x4f\
|
||||
\x9e\x7e\xb5\x24\xc5\xb3\x2d\xc2\x7f\x29\xd9\x67\xc0\x5b\x59\xf1\
|
||||
\xf6\x8d\x2b\x75\x57\x44\x5e\xa7\xba\x36\xb3\xdb\x5c\xca\x5f\x1d\
|
||||
\x91\xd0\xdd\x50\x07\xdd\x15\x4c\x47\xf2\xf1\x88\x63\xc4\xae\x5f\
|
||||
\xd0\x32\x77\x4a\x9e\xbd\xd5\x1a\x53\x12\x12\xba\xb9\xa1\x3c\x3c\
|
||||
\x3c\xe1\xa3\xd7\xf5\x52\xfe\x09\xa4\xcd\x9d\x69\x04\xdd\x7c\x4e\
|
||||
\x45\x7f\xe1\xe1\x57\x4a\x8c\xfc\x3a\x68\x0e\x68\x0a\x08\x86\x8f\
|
||||
\x9c\x75\x58\x5c\xeb\xf8\xf1\x05\xe4\x53\x1f\x8f\xbf\xc0\x14\x44\
|
||||
\xfd\x42\x80\x6f\xc6\x71\xfc\x4b\xce\x59\xea\x1c\xe9\x56\x34\xaf\
|
||||
\x82\xf4\x3d\xe1\xf6\x0e\x17\xc8\x8b\xf7\xda\x0a\xe8\x4b\x79\x92\
|
||||
\xde\x93\xed\xed\x93\x86\x6f\xd5\x1a\x0b\x4b\x54\x24\x48\xdb\x36\
|
||||
\xe0\x29\x77\x3d\x87\xad\x56\x6a\x71\xe6\xb3\xb5\x40\x17\xf7\x9f\
|
||||
\x4c\x68\x7c\x29\xc0\xf3\xc9\xb5\xb1\x67\x72\xde\xbc\x7e\xc5\x51\
|
||||
\x6f\x4e\xdc\x79\xfe\x19\xf7\xf0\xea\x1c\x2f\xb3\xd2\x7f\xf8\xf0\
|
||||
\xe1\xaf\xe3\x30\x6a\xf6\x8c\xab\x11\x2d\xd2\xc5\x84\xa6\x54\x1d\
|
||||
\x2b\x85\x18\x3a\x4a\x99\xb0\x32\xa1\xb1\x3b\x79\xd9\x66\x84\x36\
|
||||
\x84\x54\xdc\x90\x6e\x8b\xa6\x84\x4d\xd3\x49\x8b\x35\xc6\x2c\xa4\
|
||||
\x88\x84\xf5\xe0\x34\x59\xb8\x6b\xb3\x79\x42\x8f\x81\xb5\x29\x7b\
|
||||
\xa1\xb5\xd3\x7c\xc2\x59\x7b\x12\x0e\x3f\x2f\xd0\xd5\x84\xc4\x80\
|
||||
\x4d\xe5\x5c\x55\xb7\x7b\x0d\x8d\x35\x6b\x40\xfb\x74\xae\xce\xfd\
|
||||
\x8a\x7a\x77\x2b\x48\xe8\xd6\x92\xfc\xfa\x40\x1e\x8e\xc3\x9b\xc3\
|
||||
\xe1\x10\x70\x27\xfb\x84\x7b\xa1\xf8\x44\x79\x38\x62\xdb\x9e\xae\
|
||||
\xef\xe9\x3c\xa0\xa2\xb8\x04\xac\x18\xda\x12\x02\x6e\x46\xc9\x79\
|
||||
\x35\x7f\xba\x8a\xad\xdc\xdc\xc1\xfb\x1f\x4f\x15\x18\x0e\x65\x32\
|
||||
\xca\x34\x36\xa9\x66\xf9\x0e\x04\x24\x6a\x9b\xc0\xa7\x40\x6a\x83\
|
||||
\x5e\xea\xbc\x4d\xbd\xe2\xc3\xac\x29\x6a\x49\xf5\xfd\x94\xd2\x2a\
|
||||
\x38\x2e\xd4\xfa\xba\x2e\xcc\x40\x12\x68\x1f\x29\x43\x3e\xb7\xd1\
|
||||
\x56\x7f\x07\xde\xe2\xe0\x08\x4c\x17\xfe\x82\x5f\xa9\x36\x69\x71\
|
||||
\xb3\xbf\x20\xeb\xf5\xd9\x13\x16\x2b\xb1\x6a\xe0\x7a\xa1\x5d\xad\
|
||||
\x0e\x31\x0d\x4a\x11\x18\xf7\x7b\xa6\xbe\xa3\x8b\x89\x60\xd2\x36\
|
||||
\xf3\xb0\xa5\x7e\x2b\x97\x42\x32\x47\x54\x16\x69\xd6\xed\x0e\xbb\
|
||||
\x7f\x57\x49\x0b\x79\x42\x25\xe3\x23\x94\x0c\x21\x3a\x1a\xc1\xa5\
|
||||
\x54\xaa\x10\x40\x26\x44\x84\x98\x1a\xe8\xc5\x9e\x8f\x69\xbd\x4a\
|
||||
\x92\xf6\x09\x24\xe1\xc5\xf1\x5c\xf0\x9c\x4f\x80\x5f\xa0\x62\x53\
|
||||
\x21\xdc\x28\xea\x81\x32\x94\x33\xa0\x2b\xeb\xd6\xc8\x1f\xad\x39\
|
||||
\x25\xcf\xe7\x0e\xda\xbc\x30\xbd\xf8\x72\x7e\x59\xd5\x8a\xbd\x84\
|
||||
\x24\x7f\xd6\x26\x8b\x88\xcd\x7d\x4e\x41\x42\xe3\x74\x85\x90\x9c\
|
||||
\x98\x33\xd6\x25\x8a\xc2\xb4\x3f\x30\x6a\xb5\xd3\xb6\x94\x05\xb5\
|
||||
\xec\x95\x95\x75\x88\x0a\x31\x21\x9b\x9b\x73\x47\x6b\xa5\x56\xbd\
|
||||
\x49\x55\x1e\x61\x3a\xb6\x48\x64\x5d\xde\xe3\x5e\x93\x11\x79\xaa\
|
||||
\x8f\x9f\xf3\xb5\x04\x3c\x1b\xe5\x50\x07\xc2\x49\x98\xd0\x5e\x08\
|
||||
\xbb\x9e\x70\xb3\x41\x5a\x88\x37\x73\x1f\xde\x04\xcf\xb2\xa1\xbd\
|
||||
\xa3\x9d\x9e\xaa\x3c\x43\xa8\xb3\x23\x56\x8d\x51\x1a\xcf\x6d\x3e\
|
||||
\x80\x74\xe9\x8c\x24\x77\x2b\x97\xdd\x22\xfa\xea\x40\x56\x0d\x93\
|
||||
\x86\x9a\x47\x0e\x1a\x16\xf0\xc4\x21\x6e\x1c\x35\x23\x1d\x32\x65\
|
||||
\x93\x28\x41\xe8\x53\x44\x99\x73\xbe\xb5\x4f\xaa\xf6\x13\x9f\x87\
|
||||
\x3b\xba\x7b\xf3\xf4\xec\x97\xdd\x65\x33\xd8\x03\x4c\x87\xda\x46\
|
||||
\xfc\x49\xd6\xea\xb9\xd0\xcb\xc0\x8e\x73\x72\x63\x04\x1f\x90\x30\
|
||||
\x11\x36\x4a\xb8\xdd\x10\x36\x5d\x2d\xc8\x9b\xd3\xd7\x53\x35\xe8\
|
||||
\xa1\xaf\xd2\x6b\x8b\x57\x7d\x6e\x1a\x24\x9c\xf3\xe1\x12\x23\x12\
|
||||
\x1a\xcf\x7d\xa6\xae\xcf\x82\xbd\xd7\x07\x72\x8c\xf1\x18\x96\xf9\
|
||||
\x1e\x01\x45\x91\xe0\x58\x16\x34\x38\x89\xcc\xb4\x49\x44\x0d\xbc\
|
||||
\x95\x48\x9f\x12\x9b\xbe\xcb\xd4\x81\x19\x08\xb2\xc4\xcc\xa7\xc5\
|
||||
\x6c\x48\xb7\x41\xbb\xcd\xb9\x34\x5f\xab\x7f\x96\x93\x1a\x9f\x8e\
|
||||
\x30\x1e\xdb\x75\x7b\xa6\xba\xe4\x6a\x31\x49\xbb\xd6\x65\x58\x8f\
|
||||
\x13\xa8\x80\x0b\x03\xda\x19\x71\x97\x88\xbb\x1e\x49\x81\x32\xcd\
|
||||
\x53\xf2\x8d\xb8\xa9\x05\x8d\x12\x75\x55\xc6\xc4\x69\x0e\xdd\x3c\
|
||||
\x22\x2a\x04\xb4\x9b\xbd\xb1\x73\xc7\xeb\xe2\x87\xbd\x52\x90\x63\
|
||||
\xcc\x2a\x75\x24\x44\x20\xb5\x9a\xe9\xba\xe2\x43\x6f\x6c\x11\xde\
|
||||
\x84\x44\x08\x01\xd1\xf0\x78\x73\x73\xfb\xdf\x7d\x8a\xef\x59\xd1\
|
||||
\x9c\xa5\xe4\x0b\xd6\x48\x90\xdd\x9b\x27\x66\xf1\x49\x6f\x92\x9f\
|
||||
\x87\x2a\x56\x60\x38\xc0\x38\xb4\xe8\x44\xae\x00\x7b\xf9\x7d\xb3\
|
||||
\xbd\x9f\x2a\x35\xfa\x24\x41\xe1\x05\x7c\x44\xc3\x44\xba\x09\xc4\
|
||||
\x9b\x0e\xb7\x9a\x2f\x17\x71\xe2\x2e\x20\x92\x9f\x9c\xc0\x9b\x34\
|
||||
\x8b\x2a\xa1\x4f\x08\xc3\xb9\x77\x2d\x4f\x1d\x2f\xe7\x15\xaa\x6b\
|
||||
\x11\xb1\x94\xba\x83\xb4\xe9\x3f\x51\x3b\x70\x25\x24\x27\xe7\x40\
|
||||
\xf4\x1d\xbb\x6e\x83\x88\x7a\x4c\xdd\xf7\x9b\xcd\xf6\xff\xa9\x6a\
|
||||
\xde\x6e\x36\xef\x05\x6c\xa9\x15\x6b\x23\x20\x7c\x95\x17\x96\xcd\
|
||||
\x0d\x92\xd2\xd3\x8b\xe7\xab\xf6\x99\x75\x1a\xd9\x5b\xa1\xa5\xc3\
|
||||
\x34\xc0\xf1\x00\x39\x3f\x95\x68\xbf\xf0\x76\xd7\x8f\xf3\xb0\x38\
|
||||
\xc8\xd7\x93\x14\x3e\x12\x62\x46\xa2\xb4\xf3\x0b\x42\x6e\xdb\x17\
|
||||
\xcc\xc3\xe6\x64\xa9\x79\xd3\x00\x61\x9b\x10\x4e\xfe\xc1\x99\x97\
|
||||
\xbd\x48\xff\x3c\x87\xfb\xe7\x97\xe4\x2f\x72\xe7\xbb\xae\xbb\x9f\
|
||||
\xc6\xe1\xce\xc5\x11\x57\x82\x75\x38\x13\xbb\xcd\x0d\x29\x26\x44\
|
||||
\x75\xec\x37\x9b\xbf\x87\x10\x97\xe2\xf1\x10\xc2\xd4\xc5\xf0\x71\
|
||||
\xc8\xe5\x2b\xda\xb4\x20\xb3\x5a\x3e\xe4\xf3\xa5\x12\x45\x6f\xee\
|
||||
\xc8\x2d\x9c\x5a\x06\xa1\x2e\x19\xca\x15\x9f\x3d\xd7\x37\xb7\x3a\
|
||||
\x6f\x55\x2a\x19\x23\x0e\x65\x7c\x2a\xc5\xfe\x0c\x2d\xea\x30\x1d\
|
||||
\x9c\xb4\x93\x4f\x53\x66\x9e\x2f\x48\x8c\xcb\xc7\xb2\x10\x24\xe2\
|
||||
\xe3\x69\xf0\x1b\xab\xfe\xec\x36\xb7\xfb\x62\x05\xca\xab\x04\x39\
|
||||
\xc6\xb8\xd7\x10\xb2\x9b\x45\xc4\x49\xd2\x03\x9b\xba\x09\x57\x8c\
|
||||
\x1f\xfb\x7e\xf3\x9d\xa8\x3e\x91\x8f\x4d\xdf\xbf\x1b\xcb\xfe\x2d\
|
||||
\x22\xe2\x56\x1d\xb0\xf5\x1f\xed\x6e\xc8\xf6\x16\x79\x78\x8f\x17\
|
||||
\xab\x49\xf7\x4d\x7c\xda\x3b\x25\xeb\x5a\x51\x6b\xa1\x58\x9b\x4c\
|
||||
\x6f\x57\xe2\x63\x7f\x06\xe8\x59\xb2\x0b\xe4\xc1\x89\xbd\x3e\xc9\
|
||||
\x24\x3d\x4b\x7d\x3e\xf9\xee\xd3\xf6\x44\x97\xe6\xa6\xfd\x34\x34\
|
||||
\x04\xe2\xed\x1f\x30\x3b\xcb\x44\xbd\xce\x54\x63\x2d\x07\xea\x3f\
|
||||
\x8e\xc3\xf1\x9b\xd9\x4e\xa9\x6a\xe9\xfa\xcd\xf7\x5d\xd7\x7f\x78\
|
||||
\xee\x73\x21\x84\x29\x85\x78\x3f\x7a\x7e\x23\x52\x37\x08\x31\xb3\
|
||||
\x65\x22\x81\x00\x84\x88\xde\xdc\x51\x3e\x7e\xa0\x64\xc7\x8f\x13\
|
||||
\xda\x5d\x61\x09\xe5\x69\x56\xea\x93\xec\x15\xb3\x53\x74\xa2\xd5\
|
||||
\xd6\x8c\x54\x1e\x40\xd4\xcf\x4b\x8b\xae\x7c\x89\xfb\x75\xb0\xbd\
|
||||
\x39\x03\xa7\xfb\x96\xc2\x34\xd0\x10\x89\xbb\x5b\x74\xfb\x16\x13\
|
||||
\x5d\x06\xb7\xfe\xb4\xd8\xe0\x05\x12\x14\x29\xa5\x0f\xd3\x38\x7c\
|
||||
\x8d\x20\x41\xe3\xa1\xdf\x6c\xfe\x11\x42\xfc\xec\x7e\x0b\x9b\x2e\
|
||||
\xbd\x9b\x4a\xb9\x73\x11\x71\xaf\x15\x9f\xb5\xc8\x6f\xbe\x8e\x56\
|
||||
\x41\x7e\xfc\x58\xe9\xcb\xe6\xdf\xcc\x24\xd9\xb5\xde\x62\xe7\xfa\
|
||||
\x93\x22\xad\x42\xa5\xd1\xad\xab\x93\x9c\x27\x12\x5a\xc5\xa7\xb9\
|
||||
\xd7\xb0\xc8\x3f\x1d\x83\xf9\xea\x9f\x27\xaa\x7b\xb6\xbb\x12\x90\
|
||||
\xb8\x21\x6e\x6e\x91\xb8\xc5\x44\xc9\x66\xe7\xe3\x2d\x5e\xe8\xf8\
|
||||
\x62\x90\x43\x08\x53\xea\xba\xf7\x80\xf4\xfd\xe6\xbb\x2f\x1d\x27\
|
||||
\x18\x63\x1c\xa2\xea\x63\x76\xbf\xad\x5b\x0b\x14\x62\x88\x4b\x29\
|
||||
\x8f\xbb\xd7\x4d\x3f\xb6\xb7\x94\x87\x7b\x44\x5b\x41\x85\x57\xa0\
|
||||
\x5d\x9e\xf2\xcf\x72\x2d\xc9\xdb\x00\xb4\x9c\x91\x92\x2b\x15\x1a\
|
||||
\xe5\x62\x9c\x40\xe3\x29\x84\xda\x45\x89\x2e\x65\xbb\x9f\x0c\xb4\
|
||||
\x17\x8c\xe5\x29\xe8\x2e\xe8\xe6\x1b\x08\x3b\x90\xb8\x34\xe6\x5f\
|
||||
\xa6\x8c\x57\x4e\xbe\xbf\x5a\x90\x01\x36\x9b\xed\x3f\xb5\x25\xce\
|
||||
\xa6\xeb\xde\x3d\x1c\x0e\xb7\xb4\xf1\xc7\xa5\x14\xa2\xc6\x33\x74\
|
||||
\x74\xf7\x06\xdb\x3f\x2c\x35\x53\x56\xa3\x1a\x42\xb7\xea\x20\xf5\
|
||||
\xcf\xab\x6a\xbc\x95\x78\x0d\x46\x99\x40\xa3\xd6\x26\xf2\xb9\x8c\
|
||||
\x68\xed\xdd\x63\xcd\x7b\x96\xe7\xaf\xfc\x6c\x7b\x2f\xc4\xd7\xe7\
|
||||
\x1c\x79\x77\x07\xf1\xeb\xca\xea\xb9\x3d\xb7\x46\x4e\x4c\x48\xd0\
|
||||
\x9f\x7d\x12\xd0\xcf\xe2\xce\xa7\x14\x0f\x21\xe8\x41\x9e\x49\x41\
|
||||
\xba\x3b\x92\x3a\x74\xbb\x3b\x6b\x70\xab\x0e\xd2\xb9\xc6\x3b\x73\
|
||||
\x6e\xae\xdd\x56\x5c\xb3\x1b\x94\xd1\xc8\xc7\x8c\x15\x3f\x77\x9e\
|
||||
\x5c\x56\xf6\x94\x55\xe1\x88\x2f\xf3\x40\xab\x53\xd5\x42\x29\x17\
|
||||
\x56\x0d\x1d\x4b\x78\xe5\x84\xb6\x67\x86\x3f\x0d\xe1\x56\xf6\x44\
|
||||
\x44\x86\x18\xc3\xf7\x29\xc6\x7f\xbc\x6a\x49\xfe\xdf\x1c\x7d\x4a\
|
||||
\xef\x1e\x8b\x6d\xeb\x8e\x6d\x75\xff\xc4\x78\xe6\x69\x57\x69\x2e\
|
||||
\x87\x87\xf3\x1c\xb2\x41\x3e\x56\x89\xd6\xf8\x34\xd8\xf9\x94\xd4\
|
||||
\x2c\x17\xbc\x80\x1d\x0a\x9a\x14\x4d\xfa\x94\x29\x69\x14\x2c\xa2\
|
||||
\x88\xd4\xda\x6b\xf7\x82\x97\xb1\xc5\x41\xa9\x15\x00\xb4\xa4\xc3\
|
||||
\x5c\x04\xe0\xf9\xbc\xe8\xcf\x59\x72\xe1\x6e\x4e\xb1\x4c\x97\xba\
|
||||
\xf7\x21\xe8\xbd\x8a\x1c\x5f\x6a\x62\xee\xcf\x06\x72\x97\xd2\xe3\
|
||||
\xfe\x70\x1c\x5d\xa4\xc3\x8c\x52\x32\x21\xe8\x09\x2c\x77\x48\x3d\
|
||||
\x61\xbb\x23\x3f\x3e\x3e\x19\xba\x96\x07\x08\x06\x9a\x9e\x8e\x42\
|
||||
\xe4\xb9\x18\x79\x9d\x0f\x76\xb0\xc1\x08\xc5\x09\x9b\x54\xcb\x94\
|
||||
\x34\xd6\x9c\xa1\xa6\x7a\x2f\x01\xe7\xd4\x19\x22\xf9\x1e\x1b\xdf\
|
||||
\x57\x55\xa2\xa1\xd6\x80\xbb\xb5\x0d\x4b\x7c\xd1\x04\xb2\x62\xea\
|
||||
\x86\x61\x20\xb7\x0d\x4b\xdc\xcd\x6f\xfe\xf0\xed\x0f\x7a\x25\xbc\
|
||||
\xfc\x55\x82\x2c\x22\x1e\x83\xde\x8f\xa5\xfc\x01\x58\xf8\xec\xb3\
|
||||
\x70\x0a\x47\x6f\xdf\x22\x87\x7d\x4d\x05\x36\x30\x35\xb6\xb6\x18\
|
||||
\x9f\x19\xa4\xcf\x04\xb7\x52\x89\x16\x82\xa2\x12\xea\x7e\xc9\x9a\
|
||||
\x2a\xa8\x6d\x1f\xc6\x9a\x3c\x91\x93\x8a\xf7\x0b\xbd\x0d\x10\xee\
|
||||
\x70\x39\x80\x4d\x35\xb5\xd8\x80\xa6\x49\xec\xcc\x7e\xcd\x5d\x9d\
|
||||
\x53\x1e\x79\xf7\xfd\x77\xb5\x99\xa0\xeb\xda\x76\x83\xa6\x75\x28\
|
||||
\xe3\x6f\x00\x64\x80\xbe\xeb\x1e\x8e\x0f\x0f\xdf\xa8\xaa\x98\xd5\
|
||||
\x8a\xce\xae\xeb\x4e\xaa\xce\x1d\x62\x47\x7c\xfb\x0d\xf9\xc3\xbb\
|
||||
\xda\xdf\x04\xad\xb7\xaa\x10\x52\xeb\x23\xf6\x36\xc0\xb4\x95\x86\
|
||||
\x88\x84\xf6\x38\x56\x40\x25\x2c\x37\x3f\x6b\x04\x5f\xed\x3a\x63\
|
||||
\x6d\x87\xed\x15\xe9\x72\x2d\x4e\x96\xf4\x16\x3b\x7e\x7f\xf2\xee\
|
||||
\xe7\x1e\x30\x37\x4e\x93\xb7\x1b\x37\x5e\x6a\xc6\x29\x86\x50\x47\
|
||||
\x3c\xa9\xca\x4b\xc4\xc5\x2f\x0a\x72\xd7\x75\x03\xc5\x06\xd7\x5a\
|
||||
\x86\x97\x73\x26\xc6\x53\x97\xa4\x53\x37\xf8\x90\xed\x1d\xa9\xdb\
|
||||
\xd4\x94\x13\x2c\x9b\x49\xd4\xfa\xaf\x56\xf3\xb3\x0c\x22\x59\x73\
|
||||
\xc9\xac\xb6\x1a\xf2\x15\xd9\x7d\x9d\x87\xf0\x0b\x70\x9f\xcc\xf9\
|
||||
\x72\x83\xd0\x43\xdc\xd5\x7c\xb4\xc8\x2a\xf4\x9b\xb3\x50\x61\x55\
|
||||
\x88\xd8\x86\xb7\x87\xd0\x76\xb0\xd3\xd7\x80\xf1\xcf\x5f\x39\x98\
|
||||
\x52\xdc\x0f\xd3\xb4\x89\xa9\xc3\x4a\x61\x9a\x26\xfa\xd5\x38\xa4\
|
||||
\x59\xd2\x24\x44\xb8\xb9\xbb\x9a\xb8\x38\x8f\x85\x3e\x45\x36\x9c\
|
||||
\x26\x00\x5c\x7f\x55\x16\xa2\xc4\xdd\x29\x56\xda\x46\xa0\x4e\x9f\
|
||||
\xba\x85\x50\x91\xb4\xc3\x87\xf1\x2c\xd9\x50\x17\x56\x73\xd4\x5a\
|
||||
\xbc\xec\x5e\xab\x66\xea\xcc\xb2\x40\x50\xf5\x57\xbf\x3d\xc1\xbf\
|
||||
\x45\x65\xf7\xfd\xfe\xf1\xf1\xe1\x1b\xdc\x49\x7d\x4f\x29\x75\x48\
|
||||
\x79\x8c\xe1\x34\x8a\x62\x61\xa6\xbe\x84\x2d\x92\xcf\x3e\xbd\x6e\
|
||||
\x91\x39\xed\xc9\x5c\x3d\xfc\x92\x27\x2c\x4f\x8c\xe3\x88\x38\x14\
|
||||
\x0d\xd5\x69\xda\xed\xd8\x6e\xdb\x16\x7d\x12\x21\x74\x78\x3e\x70\
|
||||
\x3e\x68\x53\x97\xae\xc6\xfa\xdd\x15\xe4\x18\x23\x31\x84\x53\x1f\
|
||||
\xf7\x6f\x0d\xe4\xae\xeb\x06\xd5\x50\xf2\x34\x05\x55\x45\x43\x58\
|
||||
\xa8\xce\xba\xeb\xf9\x59\x74\xf9\x93\x70\x3d\xe3\x98\xe7\x38\xb7\
|
||||
\x6d\x04\xe6\x56\xea\xb8\xe4\x92\x19\xa7\x09\xa5\xf6\x33\x4f\xb9\
|
||||
\xd0\x29\x4c\xd9\xe8\xa2\x42\xbf\xc3\x81\xe3\xf1\x48\xdf\x77\x6d\
|
||||
\x06\x99\x20\xda\xe3\x1c\x97\x92\xcc\x39\x5c\x5a\xb6\xaf\xf1\x3a\
|
||||
\x81\x4c\x55\xdb\x76\x0c\x6d\x4b\x86\xdf\x22\xc8\x21\x84\x92\x52\
|
||||
\x1a\xc6\x71\xbc\xb1\x92\xc9\xd3\x48\x88\x89\x52\x32\x5d\xd7\xd7\
|
||||
\xb2\xd7\x95\xfc\x5d\x6e\xab\xb9\x70\xcf\xab\x1b\xf3\xf6\x3f\xad\
|
||||
\x6f\xb8\x7a\xee\x35\xae\x1d\xf7\x23\x58\x21\xc6\xc2\x34\x19\x5d\
|
||||
\x12\x72\x76\x52\x14\x82\x0a\xd6\xa6\xe4\x77\xa2\x35\x5b\xec\x05\
|
||||
\x0d\x89\x52\x0a\xd3\x94\xe9\xfb\xae\x9e\x43\x3b\x60\xde\x45\xbd\
|
||||
\xa9\x71\x49\x88\xe8\x6a\x90\x6c\x05\x59\x9b\x14\x2f\x73\x47\x7e\
|
||||
\x6b\x20\x03\xa4\xae\x3b\x4e\xd3\x74\x33\x27\x91\xad\x6d\x1c\x36\
|
||||
\x1c\x0e\xf4\x9b\xcd\x69\x57\xd6\x9c\x51\xb7\x53\x86\x67\x06\x39\
|
||||
\xa4\xd6\xfc\x6e\x97\x7b\x6e\xe2\x6e\x8c\xc3\x80\xa8\x92\x52\x9d\
|
||||
\x16\xa8\x8d\xad\xda\x6c\x6a\x19\xd3\x94\x6b\x3e\xda\x81\x2e\xb5\
|
||||
\x10\x3d\x55\x1f\xcd\x6c\x42\x62\x87\x99\x30\x4d\x53\xf3\xfe\x1b\
|
||||
\x59\xa2\xa9\xa5\xaf\x2a\x03\x26\x21\xb6\x46\xfb\x16\x3f\xe3\x6d\
|
||||
\xf7\xd7\x65\xdb\x41\xbf\x32\xde\xe0\xb7\x01\x72\x97\xd2\xf1\xa0\
|
||||
\x95\x0f\x9e\xeb\xc0\x54\xab\xda\x2e\x79\x5a\x40\x1e\x8e\x07\x92\
|
||||
\x4f\xcd\x4b\x3d\xa9\xe9\x92\x27\x4c\x62\xdb\x48\x3b\xd4\x42\x7e\
|
||||
\xab\xc3\xe2\xdc\x0b\x22\x86\x48\xdd\x64\x5b\x74\x24\x98\x62\x06\
|
||||
\x31\xb5\x72\xde\xd2\x30\x5b\xdd\xa6\xa9\x6a\xde\x32\x14\x62\x5f\
|
||||
\x73\xc1\xf5\xfb\x2a\xf9\x51\x9b\xdb\xc3\x92\xa8\x10\x1c\x0d\x9b\
|
||||
\x55\x93\x5f\xa1\x2a\x21\x39\xed\xdb\xfc\x4a\x76\x5e\x7d\x11\xcf\
|
||||
\x20\xc6\x38\xaa\x68\xed\xb4\x99\x8b\x04\x75\xae\xf8\xd0\x05\xbc\
|
||||
\x10\x53\xdb\xdf\xa2\xdd\xda\x6b\x49\x1d\xcb\x03\xd3\x74\xac\x17\
|
||||
\xd9\x06\x82\x0d\x94\x32\x11\x54\x08\x41\xdb\x84\x9e\xaa\x3a\x83\
|
||||
\x46\xd4\x75\xa9\x86\xdd\x6e\xa0\xdf\x56\x09\x1e\x1a\x37\x3e\x4e\
|
||||
\x70\xcc\xa1\x5e\x10\xb3\xb6\x51\x77\xdd\x2d\x76\xd1\xb8\xda\x2d\
|
||||
\xe1\x9a\x68\x87\xc6\x74\x9a\x22\x6a\x57\xb0\x8c\x00\x00\x03\xf0\
|
||||
\x49\x44\x41\x54\x60\xe3\x92\x5c\x59\x2a\x58\x3e\x4d\xd9\xfc\xba\
|
||||
\x25\x39\xc6\x38\xa9\x6a\x31\xb7\x38\xef\x86\x5e\xc1\xb6\x26\xd5\
|
||||
\x95\x36\x0c\x21\x40\xa9\xb6\xf3\x6c\x90\x8c\x0a\x9d\x43\x26\x90\
|
||||
\xf3\x48\x14\x63\xd3\x45\x6c\x2c\xb8\xd4\xfd\x21\x73\xa9\x5e\x6e\
|
||||
\x08\x01\x35\x25\xc6\x1d\x5e\x06\x42\xff\x58\x27\xde\x4e\x09\xb3\
|
||||
\x89\x61\xb3\x65\x34\x47\x98\x50\x55\x36\x1d\x14\x75\x24\xd4\x46\
|
||||
\x3d\x5f\x0d\xab\x13\x6d\x35\xb8\x6e\xc4\x6e\xd3\x0a\x2f\xab\xb4\
|
||||
\x4f\x93\x03\x89\xed\x26\xad\x27\x2c\xbc\x0a\x49\x7e\x11\x90\x45\
|
||||
\xc4\x43\x08\x63\x29\x73\x77\x46\x5d\xfd\xb3\x9a\x8b\xed\x02\xc7\
|
||||
\xe8\x94\xac\x2b\x90\x4f\x03\xd4\x36\x1a\x78\x1c\x8d\x18\x94\x3a\
|
||||
\x14\x50\xb8\xe9\x23\xfb\xc9\x88\x31\x90\x8b\xd5\x1a\xb2\xa0\xc8\
|
||||
\x58\x77\x95\xb3\xdc\x31\x3e\x08\xe2\x82\x58\x62\xe4\x80\x25\x6f\
|
||||
\x33\x46\x12\x9a\x33\x87\x11\x24\x18\x7d\xd7\xd4\xf3\x6a\x34\xbd\
|
||||
\x68\xf3\xb4\x25\x10\xfa\x9b\xb6\xbf\x72\x5d\x84\x6f\xdf\xbc\x5d\
|
||||
\xf5\x76\xf9\xe2\x3a\xce\xea\xfc\x37\x07\x72\x3b\xa6\xd9\x1e\xbb\
|
||||
\xac\xc7\x17\xd2\xf8\x6c\x27\xc6\x48\x41\x88\xad\x61\xee\xac\x7f\
|
||||
\x4d\x21\xea\xa9\xdb\x70\x3f\x64\xfa\x54\x7b\xb1\xc6\x71\xb6\x8d\
|
||||
\x42\xea\x22\x63\x9e\xea\x0e\xeb\x0a\x41\xbb\x6a\x1a\x54\xb8\xd3\
|
||||
\xdb\x85\x77\x06\x27\x17\xc3\xac\xde\x64\xde\x22\xe6\x6c\x71\x56\
|
||||
\xf2\x23\x6d\xb6\x8b\x14\xcf\x9b\x7f\xb1\xda\xd4\x7b\xa6\x4a\xdd\
|
||||
\x4d\xcd\x5c\x5e\x3a\x5e\xfe\x97\x83\x6c\x4f\x86\x42\x5f\x66\x88\
|
||||
\x5c\x42\x08\xa6\xaa\x79\x1e\x88\x36\x03\x2c\x32\xdb\xbb\xb6\xb1\
|
||||
\x56\xa8\xdc\xf3\x7e\x2c\xa7\x89\x3c\xe8\x22\xd5\xf3\x30\x9a\x38\
|
||||
\x8f\x9a\x0a\x81\x5d\x27\xcd\xc3\xad\x61\xcc\xcd\xcd\x0d\x37\xbb\
|
||||
\x93\x83\x77\xc6\x53\xcf\x71\xb4\x55\x72\xc4\xc9\x4b\x2d\x98\xcc\
|
||||
\x2b\x49\xce\x09\x95\x74\xfb\x55\x75\x12\xad\x86\x52\x15\xe4\x2b\
|
||||
\x9b\x88\x02\xa8\xa8\x4d\x16\x79\x81\x29\x7c\xff\x36\x90\x67\x80\
|
||||
\xe7\x19\x92\xeb\x59\x92\x97\x8f\x55\x35\xcf\xec\x91\x2c\x65\xb6\
|
||||
\x73\xfc\x59\x75\x72\x10\xd8\xee\xee\x28\xe6\xcb\xf6\x06\xb3\xa3\
|
||||
\x76\x02\xed\x0a\x79\x72\x51\x32\x74\x39\xd2\xf8\xd9\xcc\x15\xb3\
|
||||
\xc3\x34\xff\x0e\x3d\x15\x11\xae\x1e\x94\xa6\xa6\x55\x85\x5a\x74\
|
||||
\x72\x6a\xb8\x6b\x71\xbb\x1b\xb8\xa2\xe6\xad\x1f\xd9\xcc\x44\x55\
|
||||
\x7f\xf9\xf9\x64\x55\x75\x33\x13\x11\xf1\x4b\x50\xe7\xdb\xea\x39\
|
||||
\x9f\xc7\x3a\xca\x4a\x1d\xce\x20\xcf\xec\x61\xdf\x6f\x58\x3b\xa9\
|
||||
\x7e\x95\xf4\xba\x04\x9b\x65\xe2\xae\x5c\x7b\x7d\xd5\x18\x5d\xb5\
|
||||
\xbd\xd5\xd9\xea\x5a\x7b\xbb\x7c\x55\xef\x2d\x57\xba\xcc\xe7\xd1\
|
||||
\x51\xe3\x70\x3c\x8c\xa5\x1c\x10\x31\x11\x0c\xc4\x44\xa4\x88\x88\
|
||||
\xa9\xaa\xb9\x98\xa5\x94\xca\x4b\x02\xfc\x6f\x51\xd7\xf3\x1f\x53\
|
||||
\xed\x5a\x05\x7b\xbe\x77\x77\x31\x33\x6d\xef\x2b\x64\x1e\x05\x51\
|
||||
\x0d\xba\x9d\x73\xb4\x56\x5a\xd5\x95\x5c\x01\x92\xa7\x40\x2e\x0a\
|
||||
\xff\x62\x93\xed\xb3\x21\x2f\x6d\x51\x15\xb3\x3a\x94\x1f\x37\x37\
|
||||
\xf7\x62\x56\xcc\xcc\xdc\xbd\x0d\x30\x32\x37\x33\x17\x11\x03\x6e\
|
||||
\x15\xe9\xd7\xf5\xc0\xa7\x19\xec\x8a\x95\x32\x74\x29\xfd\x4f\xba\
|
||||
\xb9\x79\x51\x55\xfc\xa2\x8e\xd7\x6a\xe5\xfa\x5a\x95\xab\xaa\x35\
|
||||
\x75\x6d\x7d\xdf\xff\x7d\x1c\xc7\x7e\x9a\xa6\x37\x22\xd2\x07\xad\
|
||||
\x1b\x7d\xce\xce\xd7\x55\x3b\x77\xd2\x04\xed\x86\xb9\x9b\x15\x2b\
|
||||
\x66\xb5\xd8\xaa\xe0\x5e\x8a\x79\x01\x9a\x54\x49\x69\x52\x66\xaa\
|
||||
\x6a\x22\xea\x1a\xc4\x63\x52\x9b\x35\x8d\x99\xa9\xbb\x4b\xce\x39\
|
||||
\x94\x52\x82\x8b\xc8\x32\x59\xf7\x6c\xf6\xb6\x02\x64\xc1\xff\x96\
|
||||
\x52\xf7\xea\x01\xfe\x59\xbd\xeb\x6b\xa0\xbb\xbb\x6c\x36\x9b\x43\
|
||||
\xdf\xf7\xc7\x61\x18\x36\xa5\x94\x2e\x84\x28\x08\xdf\x20\x22\xa5\
|
||||
\x14\xb3\x62\xc5\xa1\xb8\x7b\x29\xa5\x14\x90\xd2\xe6\x60\x15\x11\
|
||||
\x29\x2a\x62\xa2\x6a\x21\x24\x4b\x0d\x34\x11\x79\x36\xc5\x77\x4d\
|
||||
\x6d\xce\x26\x26\xe7\x1c\x01\x4a\x29\x29\x75\x5d\x37\xdb\xe5\xb5\
|
||||
\x77\xed\x6e\xb9\xe4\xfc\xb7\xcd\x66\x33\xf0\x0b\x39\x5e\x2c\x84\
|
||||
\x6a\x17\x7b\x01\x7c\xbb\xdd\xee\x81\xbd\x99\xe9\x34\x4d\x07\xb3\
|
||||
\xe2\x22\x62\x21\x26\x9b\x41\x9b\x81\xfb\x57\xdb\xb7\xf6\x7d\x16\
|
||||
\x42\x98\xed\x67\xc9\x53\xce\xa9\xeb\xe2\x89\x76\x55\xf2\x34\x8d\
|
||||
\xb8\xfd\xa3\xfd\x56\x7e\x07\xf9\x9f\x93\x72\x54\xb5\xc4\x18\x0f\
|
||||
\x2f\xf4\x1b\x96\x5a\xac\x71\x1c\x7f\x28\x79\xfa\x2a\xa6\x9b\x1e\
|
||||
\xe0\xb0\xdf\x3f\xc4\xa0\xef\xfa\xbe\x1f\xf8\x85\x1d\xe2\xee\xff\
|
||||
\xc9\xef\xc7\xd9\x51\x4a\xd1\xd9\x4e\x8f\xe3\x74\x13\x82\x4e\x5d\
|
||||
\xd7\x1d\x45\xc4\x5f\xd2\x4b\xfe\x1d\xe4\xdf\x8f\x67\x8f\xff\x0f\
|
||||
\x43\x93\xec\x91\x11\x6b\x72\x1d\x00\x00\x00\x00\x49\x45\x4e\x44\
|
||||
\xae\x42\x60\x82\
|
||||
\x00\x00\x09\x53\
|
||||
\x89\
|
||||
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
|
||||
@@ -7827,6 +8409,11 @@ qt_resource_name = "\
|
||||
\x0c\xbc\x3d\x27\
|
||||
\x00\x64\
|
||||
\x00\x6f\x00\x63\x00\x75\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x5f\x00\x6e\x00\x65\x00\x77\x00\x2e\x00\x70\x00\x6e\x00\x67\
|
||||
\x00\x13\
|
||||
\x0b\x2e\x10\x07\
|
||||
\x00\x6c\
|
||||
\x00\x69\x00\x73\x00\x74\x00\x5f\x00\x62\x00\x61\x00\x63\x00\x6b\x00\x67\x00\x72\x00\x6f\x00\x75\x00\x6e\x00\x64\x00\x2e\x00\x70\
|
||||
\x00\x6e\x00\x67\
|
||||
\x00\x0e\
|
||||
\x08\x9f\xcb\x47\
|
||||
\x00\x66\
|
||||
@@ -7859,29 +8446,30 @@ qt_resource_name = "\
|
||||
|
||||
qt_resource_struct = "\
|
||||
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x05\x00\x00\x00\x01\
|
||||
\x00\x00\x00\x28\x00\x02\x00\x00\x00\x01\x00\x00\x00\x16\
|
||||
\x00\x00\x00\x28\x00\x02\x00\x00\x00\x01\x00\x00\x00\x17\
|
||||
\x00\x00\x00\x36\x00\x02\x00\x00\x00\x01\x00\x00\x00\x11\
|
||||
\x00\x00\x00\x46\x00\x02\x00\x00\x00\x01\x00\x00\x00\x0d\
|
||||
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x0a\
|
||||
\x00\x00\x00\x14\x00\x02\x00\x00\x00\x01\x00\x00\x00\x06\
|
||||
\x00\x00\x00\x58\x00\x02\x00\x00\x00\x03\x00\x00\x00\x07\
|
||||
\x00\x00\x01\x68\x00\x00\x00\x00\x00\x01\x00\x01\x89\x6e\
|
||||
\x00\x00\x01\x52\x00\x00\x00\x00\x00\x01\x00\x01\x6d\x1f\
|
||||
\x00\x00\x01\x7e\x00\x00\x00\x00\x00\x01\x00\x01\xa8\xaa\
|
||||
\x00\x00\x01\x94\x00\x00\x00\x00\x00\x01\x00\x01\xad\xa7\
|
||||
\x00\x00\x01\x7e\x00\x00\x00\x00\x00\x01\x00\x01\x91\x58\
|
||||
\x00\x00\x01\xaa\x00\x00\x00\x00\x00\x01\x00\x01\xcc\xe3\
|
||||
\x00\x00\x00\x58\x00\x02\x00\x00\x00\x02\x00\x00\x00\x0b\
|
||||
\x00\x00\x01\x92\x00\x00\x00\x00\x00\x01\x00\x01\xd2\xa5\
|
||||
\x00\x00\x01\xac\x00\x00\x00\x00\x00\x01\x00\x01\xdd\xac\
|
||||
\x00\x00\x01\xbe\x00\x00\x00\x00\x00\x01\x00\x01\xf6\xde\
|
||||
\x00\x00\x01\xd8\x00\x00\x00\x00\x00\x01\x00\x02\x01\xe5\
|
||||
\x00\x00\x00\x58\x00\x02\x00\x00\x00\x03\x00\x00\x00\x0e\
|
||||
\x00\x00\x00\x7e\x00\x00\x00\x00\x00\x01\x00\x00\x09\x5d\
|
||||
\x00\x00\x00\x68\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
|
||||
\x00\x00\x00\x9a\x00\x00\x00\x00\x00\x01\x00\x00\x1e\x9a\
|
||||
\x00\x00\x00\x58\x00\x02\x00\x00\x00\x04\x00\x00\x00\x12\
|
||||
\x00\x00\x00\x58\x00\x02\x00\x00\x00\x05\x00\x00\x00\x12\
|
||||
\x00\x00\x01\x38\x00\x00\x00\x00\x00\x01\x00\x00\x6a\x71\
|
||||
\x00\x00\x01\x0c\x00\x00\x00\x00\x00\x01\x00\x00\x46\x38\
|
||||
\x00\x00\x00\xce\x00\x00\x00\x00\x00\x01\x00\x00\x37\xa3\
|
||||
\x00\x00\x00\xb2\x00\x00\x00\x00\x00\x01\x00\x00\x2b\x3a\
|
||||
\x00\x00\x00\xe6\x00\x00\x00\x00\x00\x01\x00\x00\x3c\x02\
|
||||
\x00\x00\x00\x58\x00\x02\x00\x00\x00\x01\x00\x00\x00\x17\
|
||||
\x00\x00\x01\x2e\x00\x00\x00\x00\x00\x01\x00\x00\x4f\x8f\
|
||||
\x00\x00\x00\x58\x00\x02\x00\x00\x00\x01\x00\x00\x00\x18\
|
||||
\x00\x00\x01\x5a\x00\x00\x00\x00\x00\x01\x00\x00\x73\xc8\
|
||||
"
|
||||
|
||||
def qInitResources():
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
# Form implementation generated from reading ui file 'KCC.ui'
|
||||
#
|
||||
# Created: Wed Aug 14 08:39:46 2013
|
||||
# by: PyQt4 UI code generator 4.10.2
|
||||
# Created: Sat Oct 12 11:28:00 2013
|
||||
# by: PyQt4 UI code generator 4.10.3
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
@@ -68,6 +68,7 @@ class Ui_KCC(object):
|
||||
self.gridLayout.addWidget(self.NoDitheringBox, 3, 2, 1, 1)
|
||||
self.BorderBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
self.BorderBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.BorderBox.setTristate(True)
|
||||
self.BorderBox.setObjectName(_fromUtf8("BorderBox"))
|
||||
self.gridLayout.addWidget(self.BorderBox, 3, 0, 1, 1)
|
||||
self.NoRotateBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
@@ -152,8 +153,11 @@ class Ui_KCC(object):
|
||||
self.JobList = QtGui.QListWidget(self.Form)
|
||||
self.JobList.setGeometry(QtCore.QRect(10, 50, 401, 101))
|
||||
self.JobList.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.JobList.setStyleSheet(_fromUtf8("QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}"))
|
||||
self.JobList.setProperty("showDropIndicator", False)
|
||||
self.JobList.setSelectionMode(QtGui.QAbstractItemView.NoSelection)
|
||||
self.JobList.setVerticalScrollMode(QtGui.QAbstractItemView.ScrollPerPixel)
|
||||
self.JobList.setHorizontalScrollMode(QtGui.QAbstractItemView.ScrollPerPixel)
|
||||
self.JobList.setObjectName(_fromUtf8("JobList"))
|
||||
self.BasicModeButton = QtGui.QPushButton(self.Form)
|
||||
self.BasicModeButton.setGeometry(QtCore.QRect(10, 10, 195, 32))
|
||||
@@ -266,12 +270,12 @@ class Ui_KCC(object):
|
||||
self.ProcessingBox.setText(_translate("KCC", "No optimisation", None))
|
||||
self.UpscaleBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Nothing<br/></span>Images smaller than device resolution will not be resized.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - Stretching<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be not preserved.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Upscaling<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be preserved.</p></body></html>", None))
|
||||
self.UpscaleBox.setText(_translate("KCC", "Stretch/Upscale", None))
|
||||
self.WebtoonBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600;\">EXPERIMENTAL!<br/></span>Enable auto-splitting of webtoons like <span style=\" font-style:italic;\">Tower of God</span> or <span style=\" font-style:italic;\">Noblesse</span>.<br/>Pages with a low width, high height and vertical panel flow.</p></body></html>", None))
|
||||
self.WebtoonBox.setToolTip(_translate("KCC", "<html><head/><body><p>Enable auto-splitting of webtoons like <span style=\" font-style:italic;\">Tower of God</span> or <span style=\" font-style:italic;\">Noblesse</span>.<br/>Pages with a low width, high height and vertical panel flow.</p></body></html>", None))
|
||||
self.WebtoonBox.setText(_translate("KCC", "Webtoon mode", None))
|
||||
self.NoDitheringBox.setToolTip(_translate("KCC", "<html><head/><body><p>Create PNG files instead JPEG.<br/><span style=\" font-weight:600;\">Only for non-Kindle devices!</span></p></body></html>", None))
|
||||
self.NoDitheringBox.setToolTip(_translate("KCC", "<html><head/><body><p>Create PNG files instead JPEG.<br/>Quality increase is not noticeable on most of devices.<br/>Output files <span style=\" font-weight:600;\">might</span> be smaller.<br/><span style=\" font-weight:600;\">MOBI conversion will be much slower.</span></p></body></html>", None))
|
||||
self.NoDitheringBox.setText(_translate("KCC", "PNG output", None))
|
||||
self.BorderBox.setToolTip(_translate("KCC", "Fill space around images with black color.", None))
|
||||
self.BorderBox.setText(_translate("KCC", "Black borders", None))
|
||||
self.BorderBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Autodetection<br/></span>Color of margins fill will be detected automatically.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - White<br/></span>Margins will be filled with white color.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Black<br/></span>Margins will be filled with black color.</p></body></html>", None))
|
||||
self.BorderBox.setText(_translate("KCC", "W/B margins", None))
|
||||
self.NoRotateBox.setToolTip(_translate("KCC", "<html><head/><body><p>Disable splitting and rotation.</p></body></html>", None))
|
||||
self.NoRotateBox.setText(_translate("KCC", "No split/rotate", None))
|
||||
self.DeviceBox.setToolTip(_translate("KCC", "Target device.", None))
|
||||
|
||||
386
kcc/KCC_ui_linux.py
Normal file
386
kcc/KCC_ui_linux.py
Normal file
@@ -0,0 +1,386 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'KCC-Linux.ui'
|
||||
#
|
||||
# Created: Sat Oct 12 11:28:11 2013
|
||||
# by: PyQt4 UI code generator 4.10.3
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
try:
|
||||
_fromUtf8 = QtCore.QString.fromUtf8
|
||||
except AttributeError:
|
||||
def _fromUtf8(s):
|
||||
return s
|
||||
|
||||
try:
|
||||
_encoding = QtGui.QApplication.UnicodeUTF8
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
||||
except AttributeError:
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig)
|
||||
|
||||
class Ui_KCC(object):
|
||||
def setupUi(self, KCC):
|
||||
KCC.setObjectName(_fromUtf8("KCC"))
|
||||
KCC.resize(420, 380)
|
||||
KCC.setMinimumSize(QtCore.QSize(420, 380))
|
||||
KCC.setMaximumSize(QtCore.QSize(420, 380))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(9)
|
||||
KCC.setFont(font)
|
||||
KCC.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
icon = QtGui.QIcon()
|
||||
icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/Icon/icons/comic2ebook.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
KCC.setWindowIcon(icon)
|
||||
KCC.setLocale(QtCore.QLocale(QtCore.QLocale.C, QtCore.QLocale.AnyCountry))
|
||||
self.Form = QtGui.QWidget(KCC)
|
||||
self.Form.setObjectName(_fromUtf8("Form"))
|
||||
self.OptionsAdvanced = QtGui.QFrame(self.Form)
|
||||
self.OptionsAdvanced.setEnabled(True)
|
||||
self.OptionsAdvanced.setGeometry(QtCore.QRect(1, 254, 421, 61))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
font.setPointSize(9)
|
||||
self.OptionsAdvanced.setFont(font)
|
||||
self.OptionsAdvanced.setObjectName(_fromUtf8("OptionsAdvanced"))
|
||||
self.gridLayout = QtGui.QGridLayout(self.OptionsAdvanced)
|
||||
self.gridLayout.setContentsMargins(9, -1, -1, -1)
|
||||
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
|
||||
self.ProcessingBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.ProcessingBox.setFont(font)
|
||||
self.ProcessingBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.ProcessingBox.setObjectName(_fromUtf8("ProcessingBox"))
|
||||
self.gridLayout.addWidget(self.ProcessingBox, 1, 0, 1, 1)
|
||||
self.UpscaleBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.UpscaleBox.setFont(font)
|
||||
self.UpscaleBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.UpscaleBox.setTristate(True)
|
||||
self.UpscaleBox.setObjectName(_fromUtf8("UpscaleBox"))
|
||||
self.gridLayout.addWidget(self.UpscaleBox, 1, 1, 1, 1)
|
||||
self.WebtoonBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.WebtoonBox.setFont(font)
|
||||
self.WebtoonBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.WebtoonBox.setObjectName(_fromUtf8("WebtoonBox"))
|
||||
self.gridLayout.addWidget(self.WebtoonBox, 3, 1, 1, 1)
|
||||
self.NoDitheringBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.NoDitheringBox.setFont(font)
|
||||
self.NoDitheringBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.NoDitheringBox.setObjectName(_fromUtf8("NoDitheringBox"))
|
||||
self.gridLayout.addWidget(self.NoDitheringBox, 3, 2, 1, 1)
|
||||
self.BorderBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.BorderBox.setFont(font)
|
||||
self.BorderBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.BorderBox.setTristate(True)
|
||||
self.BorderBox.setObjectName(_fromUtf8("BorderBox"))
|
||||
self.gridLayout.addWidget(self.BorderBox, 3, 0, 1, 1)
|
||||
self.NoRotateBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.NoRotateBox.setFont(font)
|
||||
self.NoRotateBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.NoRotateBox.setObjectName(_fromUtf8("NoRotateBox"))
|
||||
self.gridLayout.addWidget(self.NoRotateBox, 1, 2, 1, 1)
|
||||
self.DeviceBox = QtGui.QComboBox(self.Form)
|
||||
self.DeviceBox.setGeometry(QtCore.QRect(10, 200, 141, 31))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
font.setPointSize(8)
|
||||
self.DeviceBox.setFont(font)
|
||||
self.DeviceBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.DeviceBox.setObjectName(_fromUtf8("DeviceBox"))
|
||||
self.FormatBox = QtGui.QComboBox(self.Form)
|
||||
self.FormatBox.setGeometry(QtCore.QRect(260, 200, 151, 31))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
font.setPointSize(8)
|
||||
self.FormatBox.setFont(font)
|
||||
self.FormatBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.FormatBox.setObjectName(_fromUtf8("FormatBox"))
|
||||
self.ConvertButton = QtGui.QPushButton(self.Form)
|
||||
self.ConvertButton.setGeometry(QtCore.QRect(160, 200, 91, 32))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
font.setPointSize(9)
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
self.ConvertButton.setFont(font)
|
||||
self.ConvertButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
icon1 = QtGui.QIcon()
|
||||
icon1.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/convert.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
self.ConvertButton.setIcon(icon1)
|
||||
self.ConvertButton.setObjectName(_fromUtf8("ConvertButton"))
|
||||
self.DirectoryButton = QtGui.QPushButton(self.Form)
|
||||
self.DirectoryButton.setGeometry(QtCore.QRect(10, 160, 141, 32))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
font.setPointSize(8)
|
||||
self.DirectoryButton.setFont(font)
|
||||
self.DirectoryButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
icon2 = QtGui.QIcon()
|
||||
icon2.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/folder_new.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
self.DirectoryButton.setIcon(icon2)
|
||||
self.DirectoryButton.setObjectName(_fromUtf8("DirectoryButton"))
|
||||
self.FileButton = QtGui.QPushButton(self.Form)
|
||||
self.FileButton.setGeometry(QtCore.QRect(260, 160, 151, 32))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
font.setPointSize(8)
|
||||
self.FileButton.setFont(font)
|
||||
self.FileButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
icon3 = QtGui.QIcon()
|
||||
icon3.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/document_new.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
self.FileButton.setIcon(icon3)
|
||||
self.FileButton.setObjectName(_fromUtf8("FileButton"))
|
||||
self.ClearButton = QtGui.QPushButton(self.Form)
|
||||
self.ClearButton.setGeometry(QtCore.QRect(160, 160, 91, 32))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
font.setPointSize(8)
|
||||
self.ClearButton.setFont(font)
|
||||
self.ClearButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
icon4 = QtGui.QIcon()
|
||||
icon4.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/clear.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
self.ClearButton.setIcon(icon4)
|
||||
self.ClearButton.setObjectName(_fromUtf8("ClearButton"))
|
||||
self.OptionsBasic = QtGui.QFrame(self.Form)
|
||||
self.OptionsBasic.setGeometry(QtCore.QRect(1, 230, 421, 41))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
font.setPointSize(9)
|
||||
self.OptionsBasic.setFont(font)
|
||||
self.OptionsBasic.setObjectName(_fromUtf8("OptionsBasic"))
|
||||
self.MangaBox = QtGui.QCheckBox(self.OptionsBasic)
|
||||
self.MangaBox.setGeometry(QtCore.QRect(9, 10, 130, 18))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.MangaBox.setFont(font)
|
||||
self.MangaBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.MangaBox.setObjectName(_fromUtf8("MangaBox"))
|
||||
self.QualityBox = QtGui.QCheckBox(self.OptionsBasic)
|
||||
self.QualityBox.setGeometry(QtCore.QRect(282, 10, 135, 18))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.QualityBox.setFont(font)
|
||||
self.QualityBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.QualityBox.setTristate(True)
|
||||
self.QualityBox.setObjectName(_fromUtf8("QualityBox"))
|
||||
self.RotateBox = QtGui.QCheckBox(self.OptionsBasic)
|
||||
self.RotateBox.setGeometry(QtCore.QRect(145, 10, 130, 18))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.RotateBox.setFont(font)
|
||||
self.RotateBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.RotateBox.setObjectName(_fromUtf8("RotateBox"))
|
||||
self.JobList = QtGui.QListWidget(self.Form)
|
||||
self.JobList.setGeometry(QtCore.QRect(10, 50, 401, 101))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
font.setPointSize(8)
|
||||
font.setItalic(False)
|
||||
self.JobList.setFont(font)
|
||||
self.JobList.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.JobList.setStyleSheet(_fromUtf8("QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}"))
|
||||
self.JobList.setProperty("showDropIndicator", False)
|
||||
self.JobList.setSelectionMode(QtGui.QAbstractItemView.NoSelection)
|
||||
self.JobList.setIconSize(QtCore.QSize(18, 18))
|
||||
self.JobList.setVerticalScrollMode(QtGui.QAbstractItemView.ScrollPerPixel)
|
||||
self.JobList.setHorizontalScrollMode(QtGui.QAbstractItemView.ScrollPerPixel)
|
||||
self.JobList.setObjectName(_fromUtf8("JobList"))
|
||||
self.BasicModeButton = QtGui.QPushButton(self.Form)
|
||||
self.BasicModeButton.setGeometry(QtCore.QRect(10, 10, 195, 32))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
font.setPointSize(9)
|
||||
self.BasicModeButton.setFont(font)
|
||||
self.BasicModeButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.BasicModeButton.setObjectName(_fromUtf8("BasicModeButton"))
|
||||
self.AdvModeButton = QtGui.QPushButton(self.Form)
|
||||
self.AdvModeButton.setGeometry(QtCore.QRect(217, 10, 195, 32))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
font.setPointSize(9)
|
||||
self.AdvModeButton.setFont(font)
|
||||
self.AdvModeButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.AdvModeButton.setObjectName(_fromUtf8("AdvModeButton"))
|
||||
self.OptionsAdvancedGamma = QtGui.QFrame(self.Form)
|
||||
self.OptionsAdvancedGamma.setEnabled(True)
|
||||
self.OptionsAdvancedGamma.setGeometry(QtCore.QRect(10, 305, 401, 41))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
font.setPointSize(9)
|
||||
self.OptionsAdvancedGamma.setFont(font)
|
||||
self.OptionsAdvancedGamma.setObjectName(_fromUtf8("OptionsAdvancedGamma"))
|
||||
self.GammaLabel = QtGui.QLabel(self.OptionsAdvancedGamma)
|
||||
self.GammaLabel.setGeometry(QtCore.QRect(15, 0, 100, 40))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.GammaLabel.setFont(font)
|
||||
self.GammaLabel.setObjectName(_fromUtf8("GammaLabel"))
|
||||
self.GammaSlider = QtGui.QSlider(self.OptionsAdvancedGamma)
|
||||
self.GammaSlider.setGeometry(QtCore.QRect(110, 10, 275, 22))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.GammaSlider.setFont(font)
|
||||
self.GammaSlider.setFocusPolicy(QtCore.Qt.ClickFocus)
|
||||
self.GammaSlider.setMaximum(500)
|
||||
self.GammaSlider.setSingleStep(5)
|
||||
self.GammaSlider.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.GammaSlider.setObjectName(_fromUtf8("GammaSlider"))
|
||||
self.ProgressBar = QtGui.QProgressBar(self.Form)
|
||||
self.ProgressBar.setGeometry(QtCore.QRect(10, 10, 401, 31))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
font.setPointSize(10)
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
self.ProgressBar.setFont(font)
|
||||
self.ProgressBar.setProperty("value", 0)
|
||||
self.ProgressBar.setAlignment(QtCore.Qt.AlignJustify|QtCore.Qt.AlignVCenter)
|
||||
self.ProgressBar.setFormat(_fromUtf8(""))
|
||||
self.ProgressBar.setObjectName(_fromUtf8("ProgressBar"))
|
||||
self.OptionsExpert = QtGui.QFrame(self.Form)
|
||||
self.OptionsExpert.setGeometry(QtCore.QRect(1, 337, 421, 41))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
font.setPointSize(9)
|
||||
self.OptionsExpert.setFont(font)
|
||||
self.OptionsExpert.setObjectName(_fromUtf8("OptionsExpert"))
|
||||
self.ColorBox = QtGui.QCheckBox(self.OptionsExpert)
|
||||
self.ColorBox.setGeometry(QtCore.QRect(9, 11, 130, 18))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.ColorBox.setFont(font)
|
||||
self.ColorBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.ColorBox.setObjectName(_fromUtf8("ColorBox"))
|
||||
self.OptionsExpertInternal = QtGui.QFrame(self.OptionsExpert)
|
||||
self.OptionsExpertInternal.setGeometry(QtCore.QRect(105, 0, 295, 40))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.OptionsExpertInternal.setFont(font)
|
||||
self.OptionsExpertInternal.setObjectName(_fromUtf8("OptionsExpertInternal"))
|
||||
self.gridLayout_2 = QtGui.QGridLayout(self.OptionsExpertInternal)
|
||||
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
|
||||
self.wLabel = QtGui.QLabel(self.OptionsExpertInternal)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.wLabel.setFont(font)
|
||||
self.wLabel.setObjectName(_fromUtf8("wLabel"))
|
||||
self.gridLayout_2.addWidget(self.wLabel, 0, 0, 1, 1)
|
||||
self.customWidth = QtGui.QLineEdit(self.OptionsExpertInternal)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.customWidth.sizePolicy().hasHeightForWidth())
|
||||
self.customWidth.setSizePolicy(sizePolicy)
|
||||
self.customWidth.setMaximumSize(QtCore.QSize(40, 16777215))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.customWidth.setFont(font)
|
||||
self.customWidth.setFocusPolicy(QtCore.Qt.ClickFocus)
|
||||
self.customWidth.setAcceptDrops(False)
|
||||
self.customWidth.setMaxLength(4)
|
||||
self.customWidth.setObjectName(_fromUtf8("customWidth"))
|
||||
self.gridLayout_2.addWidget(self.customWidth, 0, 1, 1, 1)
|
||||
self.hLabel = QtGui.QLabel(self.OptionsExpertInternal)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.hLabel.setFont(font)
|
||||
self.hLabel.setObjectName(_fromUtf8("hLabel"))
|
||||
self.gridLayout_2.addWidget(self.hLabel, 0, 2, 1, 1)
|
||||
self.customHeight = QtGui.QLineEdit(self.OptionsExpertInternal)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.customHeight.sizePolicy().hasHeightForWidth())
|
||||
self.customHeight.setSizePolicy(sizePolicy)
|
||||
self.customHeight.setMaximumSize(QtCore.QSize(40, 16777215))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||
self.customHeight.setFont(font)
|
||||
self.customHeight.setFocusPolicy(QtCore.Qt.ClickFocus)
|
||||
self.customHeight.setAcceptDrops(False)
|
||||
self.customHeight.setMaxLength(4)
|
||||
self.customHeight.setObjectName(_fromUtf8("customHeight"))
|
||||
self.gridLayout_2.addWidget(self.customHeight, 0, 3, 1, 1)
|
||||
KCC.setCentralWidget(self.Form)
|
||||
self.ActionBasic = QtGui.QAction(KCC)
|
||||
self.ActionBasic.setCheckable(True)
|
||||
self.ActionBasic.setChecked(False)
|
||||
font = QtGui.QFont()
|
||||
self.ActionBasic.setFont(font)
|
||||
self.ActionBasic.setObjectName(_fromUtf8("ActionBasic"))
|
||||
self.ActionAdvanced = QtGui.QAction(KCC)
|
||||
self.ActionAdvanced.setCheckable(True)
|
||||
self.ActionAdvanced.setObjectName(_fromUtf8("ActionAdvanced"))
|
||||
|
||||
self.retranslateUi(KCC)
|
||||
QtCore.QMetaObject.connectSlotsByName(KCC)
|
||||
KCC.setTabOrder(self.DirectoryButton, self.FileButton)
|
||||
KCC.setTabOrder(self.FileButton, self.ConvertButton)
|
||||
KCC.setTabOrder(self.ConvertButton, self.ClearButton)
|
||||
|
||||
def retranslateUi(self, KCC):
|
||||
KCC.setWindowTitle(_translate("KCC", "Kindle Comic Converter", None))
|
||||
self.ProcessingBox.setToolTip(_translate("KCC", "Disable image optimizations.", None))
|
||||
self.ProcessingBox.setText(_translate("KCC", "No optimisation", None))
|
||||
self.UpscaleBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Nothing<br/></span>Images smaller than device resolution will not be resized.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - Stretching<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be not preserved.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Upscaling<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be preserved.</p></body></html>", None))
|
||||
self.UpscaleBox.setText(_translate("KCC", "Stretch/Upscale", None))
|
||||
self.WebtoonBox.setToolTip(_translate("KCC", "<html><head/><body><p>Enable auto-splitting of webtoons like <span style=\" font-style:italic;\">Tower of God</span> or <span style=\" font-style:italic;\">Noblesse</span>.<br/>Pages with a low width, high height and vertical panel flow.</p></body></html>", None))
|
||||
self.WebtoonBox.setText(_translate("KCC", "Webtoon mode", None))
|
||||
self.NoDitheringBox.setToolTip(_translate("KCC", "<html><head/><body><p>Create PNG files instead JPEG.<br/>Quality increase is not noticeable on most of devices.<br/>Output files <span style=\" font-weight:600;\">might</span> be smaller.<br/><span style=\" font-weight:600;\">MOBI conversion will be much slower.</span></p></body></html>", None))
|
||||
self.NoDitheringBox.setText(_translate("KCC", "PNG output", None))
|
||||
self.BorderBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Autodetection<br/></span>Color of margins fill will be detected automatically.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - White<br/></span>Margins will be filled with white color.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Black<br/></span>Margins will be filled with black color.</p></body></html>", None))
|
||||
self.BorderBox.setText(_translate("KCC", "W/B margins", None))
|
||||
self.NoRotateBox.setToolTip(_translate("KCC", "<html><head/><body><p>Disable splitting and rotation.</p></body></html>", None))
|
||||
self.NoRotateBox.setText(_translate("KCC", "No split/rotate", None))
|
||||
self.DeviceBox.setToolTip(_translate("KCC", "Target device.", None))
|
||||
self.FormatBox.setToolTip(_translate("KCC", "Output format.", None))
|
||||
self.ConvertButton.setText(_translate("KCC", "Convert", None))
|
||||
self.DirectoryButton.setText(_translate("KCC", "Add directory", None))
|
||||
self.FileButton.setText(_translate("KCC", "Add file", None))
|
||||
self.ClearButton.setText(_translate("KCC", "Clear list", None))
|
||||
self.MangaBox.setToolTip(_translate("KCC", "Enable right-to-left reading.", None))
|
||||
self.MangaBox.setText(_translate("KCC", "Manga mode", None))
|
||||
self.QualityBox.setToolTip(_translate("KCC", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
|
||||
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
|
||||
"p, li { white-space: pre-wrap; }\n"
|
||||
"</style></head><body style=\" font-family:\'Sans\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
|
||||
"<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-weight:600; text-decoration: underline;\">Unchecked - Normal quality mode<br /></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-style:italic;\">Use it when Panel View support is not needed.</span><span style=\" font-family:\'MS Shell Dlg 2\'; font-weight:600; text-decoration: underline;\"><br /></span><span style=\" font-family:\'MS Shell Dlg 2\';\">- Maximum quality when zoom is not enabled.<br />- Poor quality when zoom is enabled.<br />- Lowest file size.</span></p>\n"
|
||||
"<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-weight:600; text-decoration: underline;\">Indeterminate - High quality mode<br /></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-style:italic;\">Not zoomed image </span><span style=\" font-family:\'MS Shell Dlg 2\'; font-weight:600; font-style:italic;\">might </span><span style=\" font-family:\'MS Shell Dlg 2\'; font-style:italic;\">be a little blurry.</span><span style=\" font-family:\'MS Shell Dlg 2\'; font-weight:600; text-decoration: underline;\"><br /></span><span style=\" font-family:\'MS Shell Dlg 2\';\">- Medium/High quality when zoom is not enabled.<br />- Maximum quality when zoom is enabled.</span></p>\n"
|
||||
"<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-weight:600; text-decoration: underline;\">Checked - Ultra quality mode<br /></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-style:italic;\">Maximum possible quality.</span><span style=\" font-family:\'MS Shell Dlg 2\'; font-weight:600; text-decoration: underline;\"><br /></span><span style=\" font-family:\'MS Shell Dlg 2\';\">- Maximum quality when zoom is not enabled.<br />- Maximum quality when zoom is enabled.<br />- Very high file size.</span></p></body></html>", None))
|
||||
self.QualityBox.setText(_translate("KCC", "High/Ultra quality", None))
|
||||
self.RotateBox.setToolTip(_translate("KCC", "<html><head/><body><p>Disable page spliting.<br/>They will be rotated instead.</p></body></html>", None))
|
||||
self.RotateBox.setText(_translate("KCC", "Horizontal mode", None))
|
||||
self.BasicModeButton.setText(_translate("KCC", "Basic", None))
|
||||
self.AdvModeButton.setText(_translate("KCC", "Advanced", None))
|
||||
self.GammaLabel.setToolTip(_translate("KCC", "<html><head/><body><p>When converting color images setting this option to 1.0 <span style=\" font-weight:600;\">might</span> improve readability.</p></body></html>", None))
|
||||
self.GammaLabel.setText(_translate("KCC", "Gamma: Auto", None))
|
||||
self.GammaSlider.setToolTip(_translate("KCC", "<html><head/><body><p>When converting color images setting this option to 1.0 <span style=\" font-weight:600;\">might</span> improve readability.</p></body></html>", None))
|
||||
self.ColorBox.setToolTip(_translate("KCC", "Do not convert images to grayscale.", None))
|
||||
self.ColorBox.setText(_translate("KCC", "Color mode", None))
|
||||
self.wLabel.setToolTip(_translate("KCC", "Resolution of target device.", None))
|
||||
self.wLabel.setText(_translate("KCC", "Custom width: ", None))
|
||||
self.customWidth.setToolTip(_translate("KCC", "Resolution of target device.", None))
|
||||
self.customWidth.setInputMask(_translate("KCC", "0000; ", None))
|
||||
self.hLabel.setToolTip(_translate("KCC", "Resolution of target device.", None))
|
||||
self.hLabel.setText(_translate("KCC", "Custom height: ", None))
|
||||
self.customHeight.setToolTip(_translate("KCC", "Resolution of target device.", None))
|
||||
self.customHeight.setInputMask(_translate("KCC", "0000; ", None))
|
||||
self.ActionBasic.setText(_translate("KCC", "Basic", None))
|
||||
self.ActionAdvanced.setText(_translate("KCC", "Advanced", None))
|
||||
|
||||
import KCC_rc
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
# Form implementation generated from reading ui file 'KCC-OSX.ui'
|
||||
#
|
||||
# Created: Wed Aug 14 08:39:45 2013
|
||||
# by: PyQt4 UI code generator 4.10.2
|
||||
# Created: Sat Oct 12 11:28:19 2013
|
||||
# by: PyQt4 UI code generator 4.10.3
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
@@ -41,8 +41,9 @@ class Ui_KCC(object):
|
||||
self.Form.setObjectName(_fromUtf8("Form"))
|
||||
self.OptionsAdvanced = QtGui.QFrame(self.Form)
|
||||
self.OptionsAdvanced.setEnabled(True)
|
||||
self.OptionsAdvanced.setGeometry(QtCore.QRect(9, 253, 421, 61))
|
||||
self.OptionsAdvanced.setGeometry(QtCore.QRect(4, 253, 421, 61))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(9)
|
||||
self.OptionsAdvanced.setFont(font)
|
||||
self.OptionsAdvanced.setObjectName(_fromUtf8("OptionsAdvanced"))
|
||||
@@ -50,14 +51,16 @@ class Ui_KCC(object):
|
||||
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
|
||||
self.ProcessingBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(11)
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
self.ProcessingBox.setFont(font)
|
||||
self.ProcessingBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.ProcessingBox.setObjectName(_fromUtf8("ProcessingBox"))
|
||||
self.gridLayout.addWidget(self.ProcessingBox, 1, 0, 1, 1)
|
||||
self.UpscaleBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(11)
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
self.UpscaleBox.setFont(font)
|
||||
self.UpscaleBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.UpscaleBox.setTristate(True)
|
||||
@@ -65,42 +68,49 @@ class Ui_KCC(object):
|
||||
self.gridLayout.addWidget(self.UpscaleBox, 1, 1, 1, 1)
|
||||
self.WebtoonBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(11)
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
self.WebtoonBox.setFont(font)
|
||||
self.WebtoonBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.WebtoonBox.setObjectName(_fromUtf8("WebtoonBox"))
|
||||
self.gridLayout.addWidget(self.WebtoonBox, 3, 1, 1, 1)
|
||||
self.NoDitheringBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(11)
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
self.NoDitheringBox.setFont(font)
|
||||
self.NoDitheringBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.NoDitheringBox.setObjectName(_fromUtf8("NoDitheringBox"))
|
||||
self.gridLayout.addWidget(self.NoDitheringBox, 3, 2, 1, 1)
|
||||
self.BorderBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(11)
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
self.BorderBox.setFont(font)
|
||||
self.BorderBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.BorderBox.setTristate(True)
|
||||
self.BorderBox.setObjectName(_fromUtf8("BorderBox"))
|
||||
self.gridLayout.addWidget(self.BorderBox, 3, 0, 1, 1)
|
||||
self.NoRotateBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(11)
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
self.NoRotateBox.setFont(font)
|
||||
self.NoRotateBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.NoRotateBox.setObjectName(_fromUtf8("NoRotateBox"))
|
||||
self.gridLayout.addWidget(self.NoRotateBox, 1, 2, 1, 1)
|
||||
self.DeviceBox = QtGui.QComboBox(self.Form)
|
||||
self.DeviceBox.setGeometry(QtCore.QRect(8, 200, 151, 34))
|
||||
self.DeviceBox.setGeometry(QtCore.QRect(8, 201, 151, 34))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(11)
|
||||
self.DeviceBox.setFont(font)
|
||||
self.DeviceBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.DeviceBox.setObjectName(_fromUtf8("DeviceBox"))
|
||||
self.FormatBox = QtGui.QComboBox(self.Form)
|
||||
self.FormatBox.setGeometry(QtCore.QRect(262, 200, 152, 34))
|
||||
self.FormatBox.setGeometry(QtCore.QRect(262, 201, 152, 34))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(11)
|
||||
self.FormatBox.setFont(font)
|
||||
self.FormatBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
@@ -108,6 +118,7 @@ class Ui_KCC(object):
|
||||
self.ConvertButton = QtGui.QPushButton(self.Form)
|
||||
self.ConvertButton.setGeometry(QtCore.QRect(160, 200, 101, 41))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(11)
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
@@ -120,6 +131,7 @@ class Ui_KCC(object):
|
||||
self.DirectoryButton = QtGui.QPushButton(self.Form)
|
||||
self.DirectoryButton.setGeometry(QtCore.QRect(5, 160, 156, 41))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(11)
|
||||
self.DirectoryButton.setFont(font)
|
||||
self.DirectoryButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
@@ -130,6 +142,7 @@ class Ui_KCC(object):
|
||||
self.FileButton = QtGui.QPushButton(self.Form)
|
||||
self.FileButton.setGeometry(QtCore.QRect(260, 160, 157, 41))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(11)
|
||||
self.FileButton.setFont(font)
|
||||
self.FileButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
@@ -140,6 +153,7 @@ class Ui_KCC(object):
|
||||
self.ClearButton = QtGui.QPushButton(self.Form)
|
||||
self.ClearButton.setGeometry(QtCore.QRect(160, 160, 101, 41))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(11)
|
||||
self.ClearButton.setFont(font)
|
||||
self.ClearButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
@@ -148,22 +162,25 @@ class Ui_KCC(object):
|
||||
self.ClearButton.setIcon(icon4)
|
||||
self.ClearButton.setObjectName(_fromUtf8("ClearButton"))
|
||||
self.OptionsBasic = QtGui.QFrame(self.Form)
|
||||
self.OptionsBasic.setGeometry(QtCore.QRect(10, 233, 421, 41))
|
||||
self.OptionsBasic.setGeometry(QtCore.QRect(5, 233, 421, 41))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(9)
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
self.OptionsBasic.setFont(font)
|
||||
self.OptionsBasic.setObjectName(_fromUtf8("OptionsBasic"))
|
||||
self.MangaBox = QtGui.QCheckBox(self.OptionsBasic)
|
||||
self.MangaBox.setGeometry(QtCore.QRect(9, 10, 130, 18))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(11)
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
self.MangaBox.setFont(font)
|
||||
self.MangaBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.MangaBox.setObjectName(_fromUtf8("MangaBox"))
|
||||
self.QualityBox = QtGui.QCheckBox(self.OptionsBasic)
|
||||
self.QualityBox.setGeometry(QtCore.QRect(282, 10, 130, 18))
|
||||
self.QualityBox.setGeometry(QtCore.QRect(282, 10, 135, 18))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(11)
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
self.QualityBox.setFont(font)
|
||||
self.QualityBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.QualityBox.setTristate(True)
|
||||
@@ -171,22 +188,28 @@ class Ui_KCC(object):
|
||||
self.RotateBox = QtGui.QCheckBox(self.OptionsBasic)
|
||||
self.RotateBox.setGeometry(QtCore.QRect(145, 10, 130, 18))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(11)
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
self.RotateBox.setFont(font)
|
||||
self.RotateBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.RotateBox.setObjectName(_fromUtf8("RotateBox"))
|
||||
self.JobList = QtGui.QListWidget(self.Form)
|
||||
self.JobList.setGeometry(QtCore.QRect(10, 50, 401, 101))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(11)
|
||||
self.JobList.setFont(font)
|
||||
self.JobList.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.JobList.setStyleSheet(_fromUtf8("QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}"))
|
||||
self.JobList.setProperty("showDropIndicator", False)
|
||||
self.JobList.setSelectionMode(QtGui.QAbstractItemView.NoSelection)
|
||||
self.JobList.setVerticalScrollMode(QtGui.QAbstractItemView.ScrollPerPixel)
|
||||
self.JobList.setHorizontalScrollMode(QtGui.QAbstractItemView.ScrollPerPixel)
|
||||
self.JobList.setObjectName(_fromUtf8("JobList"))
|
||||
self.BasicModeButton = QtGui.QPushButton(self.Form)
|
||||
self.BasicModeButton.setGeometry(QtCore.QRect(5, 10, 210, 41))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
@@ -196,6 +219,7 @@ class Ui_KCC(object):
|
||||
self.AdvModeButton = QtGui.QPushButton(self.Form)
|
||||
self.AdvModeButton.setGeometry(QtCore.QRect(207, 10, 210, 41))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
@@ -204,21 +228,26 @@ class Ui_KCC(object):
|
||||
self.AdvModeButton.setObjectName(_fromUtf8("AdvModeButton"))
|
||||
self.OptionsAdvancedGamma = QtGui.QFrame(self.Form)
|
||||
self.OptionsAdvancedGamma.setEnabled(True)
|
||||
self.OptionsAdvancedGamma.setGeometry(QtCore.QRect(10, 303, 401, 41))
|
||||
self.OptionsAdvancedGamma.setGeometry(QtCore.QRect(5, 303, 401, 41))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(9)
|
||||
self.OptionsAdvancedGamma.setFont(font)
|
||||
self.OptionsAdvancedGamma.setObjectName(_fromUtf8("OptionsAdvancedGamma"))
|
||||
self.GammaLabel = QtGui.QLabel(self.OptionsAdvancedGamma)
|
||||
self.GammaLabel.setGeometry(QtCore.QRect(20, 0, 100, 40))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
self.GammaLabel.setFont(font)
|
||||
self.GammaLabel.setObjectName(_fromUtf8("GammaLabel"))
|
||||
self.GammaSlider = QtGui.QSlider(self.OptionsAdvancedGamma)
|
||||
self.GammaSlider.setGeometry(QtCore.QRect(110, 10, 280, 22))
|
||||
self.GammaSlider.setGeometry(QtCore.QRect(110, 10, 290, 22))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
self.GammaSlider.setFont(font)
|
||||
self.GammaSlider.setFocusPolicy(QtCore.Qt.ClickFocus)
|
||||
self.GammaSlider.setMaximum(500)
|
||||
self.GammaSlider.setSingleStep(5)
|
||||
@@ -227,6 +256,7 @@ class Ui_KCC(object):
|
||||
self.ProgressBar = QtGui.QProgressBar(self.Form)
|
||||
self.ProgressBar.setGeometry(QtCore.QRect(10, 10, 401, 35))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(10)
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
@@ -237,25 +267,31 @@ class Ui_KCC(object):
|
||||
self.ProgressBar.setFormat(_fromUtf8(""))
|
||||
self.ProgressBar.setObjectName(_fromUtf8("ProgressBar"))
|
||||
self.OptionsExpert = QtGui.QFrame(self.Form)
|
||||
self.OptionsExpert.setGeometry(QtCore.QRect(10, 335, 421, 41))
|
||||
self.OptionsExpert.setGeometry(QtCore.QRect(5, 335, 421, 41))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(9)
|
||||
self.OptionsExpert.setFont(font)
|
||||
self.OptionsExpert.setObjectName(_fromUtf8("OptionsExpert"))
|
||||
self.ColorBox = QtGui.QCheckBox(self.OptionsExpert)
|
||||
self.ColorBox.setGeometry(QtCore.QRect(9, 11, 130, 18))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(11)
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
self.ColorBox.setFont(font)
|
||||
self.ColorBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.ColorBox.setObjectName(_fromUtf8("ColorBox"))
|
||||
self.OptionsExpertInternal = QtGui.QFrame(self.OptionsExpert)
|
||||
self.OptionsExpertInternal.setGeometry(QtCore.QRect(90, 0, 315, 40))
|
||||
self.OptionsExpertInternal.setGeometry(QtCore.QRect(95, 0, 315, 40))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
self.OptionsExpertInternal.setFont(font)
|
||||
self.OptionsExpertInternal.setObjectName(_fromUtf8("OptionsExpertInternal"))
|
||||
self.gridLayout_2 = QtGui.QGridLayout(self.OptionsExpertInternal)
|
||||
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
|
||||
self.wLabel = QtGui.QLabel(self.OptionsExpertInternal)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
@@ -270,6 +306,7 @@ class Ui_KCC(object):
|
||||
self.customWidth.setSizePolicy(sizePolicy)
|
||||
self.customWidth.setMaximumSize(QtCore.QSize(45, 16777215))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
self.customWidth.setFont(font)
|
||||
self.customWidth.setFocusPolicy(QtCore.Qt.ClickFocus)
|
||||
@@ -279,6 +316,7 @@ class Ui_KCC(object):
|
||||
self.gridLayout_2.addWidget(self.customWidth, 0, 1, 1, 1)
|
||||
self.hLabel = QtGui.QLabel(self.OptionsExpertInternal)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
@@ -293,6 +331,7 @@ class Ui_KCC(object):
|
||||
self.customHeight.setSizePolicy(sizePolicy)
|
||||
self.customHeight.setMaximumSize(QtCore.QSize(45, 16777215))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||
font.setPointSize(12)
|
||||
self.customHeight.setFont(font)
|
||||
self.customHeight.setFocusPolicy(QtCore.Qt.ClickFocus)
|
||||
@@ -322,31 +361,31 @@ class Ui_KCC(object):
|
||||
KCC.setWindowTitle(_translate("KCC", "Kindle Comic Converter", None))
|
||||
self.ProcessingBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Disable image optimizations.</span></p></body></html>", None))
|
||||
self.ProcessingBox.setText(_translate("KCC", "No optimisation", None))
|
||||
self.UpscaleBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Nothing<br/></span>Images smaller than device resolution will not be resized.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - Stretching<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be not preserved.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Upscaling<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be preserved.</p></body></html>", None))
|
||||
self.UpscaleBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt; font-weight:600; text-decoration: underline;\">Unchecked - Nothing<br/></span><span style=\" font-size:12pt;\">Images smaller than device resolution will not be resized.</span></p><p><span style=\" font-size:12pt; font-weight:600; text-decoration: underline;\">Indeterminate - Stretching<br/></span><span style=\" font-size:12pt;\">Images smaller than device resolution will be resized. Aspect ratio will be not preserved.</span></p><p><span style=\" font-size:12pt; font-weight:600; text-decoration: underline;\">Checked - Upscaling<br/></span><span style=\" font-size:12pt;\">Images smaller than device resolution will be resized. Aspect ratio will be preserved.</span></p></body></html>", None))
|
||||
self.UpscaleBox.setText(_translate("KCC", "Stretch/Upscale", None))
|
||||
self.WebtoonBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600;\">EXPERIMENTAL!<br/></span>Enable auto-splitting of webtoons like <span style=\" font-style:italic;\">Tower of God</span> or <span style=\" font-style:italic;\">Noblesse</span>.<br/>Pages with a low width, high height and vertical panel flow.</p></body></html>", None))
|
||||
self.WebtoonBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Enable auto-splitting of webtoons like </span><span style=\" font-size:12pt; font-style:italic;\">Tower of God</span><span style=\" font-size:12pt;\"> or </span><span style=\" font-size:12pt; font-style:italic;\">Noblesse</span><span style=\" font-size:12pt;\">.<br/>Pages with a low width, high height and vertical panel flow.</span></p></body></html>", None))
|
||||
self.WebtoonBox.setText(_translate("KCC", "Webtoon mode", None))
|
||||
self.NoDitheringBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Create PNG files instead JPEG.<br/></span><span style=\" font-size:12pt; font-weight:600;\">Only for non-Kindle devices!</span></p></body></html>", None))
|
||||
self.NoDitheringBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Create PNG files instead JPEG.<br/>Quality increase is not noticeable on most of devices.<br/>Output files </span><span style=\" font-size:12pt; font-weight:600;\">might</span><span style=\" font-size:12pt;\"> be smaller.<br/></span><span style=\" font-size:12pt; font-weight:600;\">MOBI conversion will be much slower.</span></p></body></html>", None))
|
||||
self.NoDitheringBox.setText(_translate("KCC", "PNG output", None))
|
||||
self.BorderBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Fill space around images with black color.</span></p></body></html>", None))
|
||||
self.BorderBox.setText(_translate("KCC", "Black borders", None))
|
||||
self.BorderBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt; font-weight:600; text-decoration: underline;\">Unchecked - Autodetection<br/></span><span style=\" font-size:12pt;\">Color of margins fill will be detected automatically.</span></p><p><span style=\" font-size:12pt; font-weight:600; text-decoration: underline;\">Indeterminate - White<br/></span><span style=\" font-size:12pt;\">Margins will be filled with white color.</span></p><p><span style=\" font-size:12pt; font-weight:600; text-decoration: underline;\">Checked - Black<br/></span><span style=\" font-size:12pt;\">Margins will be filled with black color.</span></p></body></html>", None))
|
||||
self.BorderBox.setText(_translate("KCC", "W/B margins", None))
|
||||
self.NoRotateBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Disable splitting and rotation.</span></p></body></html>", None))
|
||||
self.NoRotateBox.setText(_translate("KCC", "No split/rotate", None))
|
||||
self.DeviceBox.setToolTip(_translate("KCC", "Target device.", None))
|
||||
self.FormatBox.setToolTip(_translate("KCC", "Output format.", None))
|
||||
self.DeviceBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Target device.</span></p></body></html>", None))
|
||||
self.FormatBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Output format.</span></p></body></html>", None))
|
||||
self.ConvertButton.setText(_translate("KCC", "Convert", None))
|
||||
self.DirectoryButton.setText(_translate("KCC", "Add directory", None))
|
||||
self.FileButton.setText(_translate("KCC", "Add file", None))
|
||||
self.ClearButton.setText(_translate("KCC", "Clear list", None))
|
||||
self.MangaBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Enable right-to-left reading.</span></p></body></html>", None))
|
||||
self.MangaBox.setText(_translate("KCC", "Manga mode", None))
|
||||
self.QualityBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-weight:600; text-decoration: underline;\">Unchecked - Normal quality mode<br/></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-style:italic;\">Use it when Panel View support is not needed.</span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-weight:600; text-decoration: underline;\"><br/></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt;\">- Maximum quality when zoom is not enabled.<br/>- Poor quality when zoom is enabled.<br/>- Lowest file size.</span></p><p><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-weight:600; text-decoration: underline;\">Indeterminate - High quality mode<br/></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-style:italic;\">Not zoomed image </span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-weight:600; font-style:italic;\">might </span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-style:italic;\">be a little blurry.</span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-weight:600; text-decoration: underline;\"><br/></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt;\">- Medium/High quality when zoom is not enabled.<br/>- Maximum quality when zoom is enabled.</span></p><p><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-weight:600; text-decoration: underline;\">Checked - Ultra quality mode<br/></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-style:italic;\">Maximum possible quality.</span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-weight:600; text-decoration: underline;\"><br/></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt;\">- Maximum quality when zoom is not enabled.<br/>- Maximum quality when zoom is enabled.<br/>- Very high file size.</span></p></body></html>", None))
|
||||
self.QualityBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\"font-size:12pt; font-weight:600; text-decoration: underline;\">Unchecked - Normal quality mode<br/></span><span style=\"font-size:12pt; font-style:italic;\">Use it when Panel View support is not needed.</span><span style=\"font-size:12pt; font-weight:600; text-decoration: underline;\"><br/></span><span style=\"font-size:12pt;\">- Maximum quality when zoom is not enabled.<br/>- Poor quality when zoom is enabled.<br/>- Lowest file size.</span></p><p><span style=\"font-size:12pt; font-weight:600; text-decoration: underline;\">Indeterminate - High quality mode<br/></span><span style=\"font-size:12pt; font-style:italic;\">Not zoomed image </span><span style=\"font-size:12pt; font-weight:600; font-style:italic;\">might </span><span style=\"font-size:12pt; font-style:italic;\">be a little blurry.</span><span style=\"font-size:12pt; font-weight:600; text-decoration: underline;\"><br/></span><span style=\"font-size:12pt;\">- Medium/High quality when zoom is not enabled.<br/>- Maximum quality when zoom is enabled.</span></p><p><span style=\"font-size:12pt; font-weight:600; text-decoration: underline;\">Checked - Ultra quality mode<br/></span><span style=\"font-size:12pt; font-style:italic;\">Maximum possible quality.</span><span style=\"font-size:12pt; font-weight:600; text-decoration: underline;\"><br/></span><span style=\"font-size:12pt;\">- Maximum quality when zoom is not enabled.<br/>- Maximum quality when zoom is enabled.<br/>- Very high file size.</span></p></body></html>", None))
|
||||
self.QualityBox.setText(_translate("KCC", "High/Ultra quality", None))
|
||||
self.RotateBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Disable page spliting.<br/>They will be rotated instead.</span></p></body></html>", None))
|
||||
self.RotateBox.setText(_translate("KCC", "Horizontal mode", None))
|
||||
self.BasicModeButton.setText(_translate("KCC", "Basic", None))
|
||||
self.AdvModeButton.setText(_translate("KCC", "Advanced", None))
|
||||
self.GammaLabel.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">When converting color images setting this option to 1.0 MIGHT improve readability.</span></p></body></html>", None))
|
||||
self.GammaLabel.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">When converting color images setting this option to 1.0 </span><span style=\" font-size:12pt; font-weight:600;\">might</span><span style=\" font-size:12pt;\"> improve readability.</span></p></body></html>", None))
|
||||
self.GammaLabel.setText(_translate("KCC", "Gamma: Auto", None))
|
||||
self.GammaSlider.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">When converting color images setting this option to 1.0 </span><span style=\" font-size:12pt; font-weight:600;\">might</span><span style=\" font-size:12pt;\"> improve readability.</span></p></body></html>", None))
|
||||
self.ColorBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Do not convert images to grayscale.</span></p></body></html>", None))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
__version__ = '3.2'
|
||||
__version__ = '3.4'
|
||||
__license__ = 'ISC'
|
||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
@@ -1,4 +1,5 @@
|
||||
# Copyright (c) 2012 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||
# Copyright (c) 2012-2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||
# Copyright (c) 2013 Pawel Jastrzebski <pawelj@vulturis.eu>
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for
|
||||
# any purpose with or without fee is hereby granted, provided that the
|
||||
@@ -21,6 +22,8 @@ __docformat__ = 'restructuredtext en'
|
||||
import os
|
||||
import zipfile
|
||||
import rarfile
|
||||
import locale
|
||||
from subprocess import Popen, STDOUT, PIPE
|
||||
|
||||
|
||||
# noinspection PyBroadException
|
||||
@@ -31,6 +34,8 @@ class CBxArchive:
|
||||
self.compressor = 'zip'
|
||||
elif rarfile.is_rarfile(origFileName):
|
||||
self.compressor = 'rar'
|
||||
elif origFileName.endswith('.7z') or origFileName.endswith('.cb7'):
|
||||
self.compressor = '7z'
|
||||
else:
|
||||
self.compressor = None
|
||||
|
||||
@@ -53,7 +58,7 @@ class CBxArchive:
|
||||
cbzFile.extractall(targetdir, filelist)
|
||||
|
||||
def extractCBR(self, targetdir):
|
||||
cbrFile = rarfile.RarFile(self.origFileName)
|
||||
cbrFile = rarfile.RarFile(self.origFileName.encode(locale.getpreferredencoding()))
|
||||
filelist = []
|
||||
for f in cbrFile.namelist():
|
||||
if f.startswith('__MACOSX') or f.endswith('.DS_Store') or f.endswith('thumbs.db'):
|
||||
@@ -64,15 +69,28 @@ class CBxArchive:
|
||||
except:
|
||||
pass # the dir exists so we are going to extract the images only.
|
||||
else:
|
||||
filelist.append(f)
|
||||
filelist.append(f.encode(locale.getpreferredencoding()))
|
||||
cbrFile.extractall(targetdir, filelist)
|
||||
|
||||
def extractCB7(self, targetdir):
|
||||
output = Popen('7za x "' + self.origFileName.encode(locale.getpreferredencoding()) +
|
||||
'" -xr!__MACOSX -xr!.DS_Store -xr!thumbs.db -o"' + targetdir + '"',
|
||||
stdout=PIPE, stderr=STDOUT, shell=True)
|
||||
extracted = False
|
||||
for line in output.stdout:
|
||||
if "Everything is Ok" in line:
|
||||
extracted = True
|
||||
if not extracted:
|
||||
raise OSError
|
||||
|
||||
def extract(self, targetdir):
|
||||
print "\n" + targetdir + "\n"
|
||||
if self.compressor == 'rar':
|
||||
self.extractCBR(targetdir)
|
||||
elif self.compressor == 'zip':
|
||||
self.extractCBZ(targetdir)
|
||||
elif self.compressor == '7z':
|
||||
self.extractCB7(targetdir)
|
||||
adir = os.listdir(targetdir)
|
||||
if len(adir) == 1 and os.path.isdir(os.path.join(targetdir, adir[0])):
|
||||
import shutil
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2012 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||
# Copyright (c) 2012-2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||
# Copyright (c) 2013 Pawel Jastrzebski <pawelj@vulturis.eu>
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for
|
||||
# any purpose with or without fee is hereby granted, provided that the
|
||||
@@ -17,7 +18,7 @@
|
||||
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
__version__ = '3.2'
|
||||
__version__ = '3.4'
|
||||
__license__ = 'ISC'
|
||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
@@ -44,11 +45,18 @@ import pdfjpgextract
|
||||
def buildHTML(path, imgfile):
|
||||
filename = getImageFileName(imgfile)
|
||||
if filename is not None:
|
||||
# All files marked with this sufix need horizontal Panel View.
|
||||
if "_kccrotated" in str(filename):
|
||||
rotate = True
|
||||
if "_kccrot" in str(filename):
|
||||
rotatedPage = True
|
||||
else:
|
||||
rotate = False
|
||||
rotatedPage = False
|
||||
if "_kccnh" in str(filename):
|
||||
noHorizontalPV = True
|
||||
else:
|
||||
noHorizontalPV = False
|
||||
if "_kccnv" in str(filename):
|
||||
noVerticalPV = True
|
||||
else:
|
||||
noVerticalPV = False
|
||||
htmlpath = ''
|
||||
postfix = ''
|
||||
backref = 1
|
||||
@@ -79,88 +87,86 @@ def buildHTML(path, imgfile):
|
||||
imgfile, "\" class=\"singlePage\"/></div>\n"
|
||||
])
|
||||
if options.panelview:
|
||||
if rotate:
|
||||
if options.righttoleft:
|
||||
f.writelines(["<div id=\"BoxTL\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify=",
|
||||
"'{\"targetId\":\"BoxTL-Panel-Parent\", \"ordinal\":1}'></a></div>\n",
|
||||
"<div id=\"BoxTR\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify=",
|
||||
"'{\"targetId\":\"BoxTR-Panel-Parent\", \"ordinal\":3}'></a></div>\n",
|
||||
"<div id=\"BoxBL\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify=",
|
||||
"'{\"targetId\":\"BoxBL-Panel-Parent\", \"ordinal\":2}'></a></div>\n",
|
||||
"<div id=\"BoxBR\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify="
|
||||
"'{\"targetId\":\"BoxBR-Panel-Parent\", \"ordinal\":4}'></a></div>\n"
|
||||
])
|
||||
if not noHorizontalPV and not noVerticalPV:
|
||||
if rotatedPage:
|
||||
if options.righttoleft:
|
||||
order = [1, 3, 2, 4]
|
||||
else:
|
||||
order = [2, 4, 1, 3]
|
||||
else:
|
||||
f.writelines(["<div id=\"BoxTL\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify=",
|
||||
"'{\"targetId\":\"BoxTL-Panel-Parent\", \"ordinal\":2}'></a></div>\n",
|
||||
"<div id=\"BoxTR\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify=",
|
||||
"'{\"targetId\":\"BoxTR-Panel-Parent\", \"ordinal\":4}'></a></div>\n",
|
||||
"<div id=\"BoxBL\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify=",
|
||||
"'{\"targetId\":\"BoxBL-Panel-Parent\", \"ordinal\":1}'></a></div>\n",
|
||||
"<div id=\"BoxBR\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify="
|
||||
"'{\"targetId\":\"BoxBR-Panel-Parent\", \"ordinal\":3}'></a></div>\n"
|
||||
])
|
||||
if options.righttoleft:
|
||||
order = [2, 1, 4, 3]
|
||||
else:
|
||||
order = [1, 2, 3, 4]
|
||||
boxes = ["BoxTL", "BoxTR", "BoxBL", "BoxBR"]
|
||||
elif noHorizontalPV and not noVerticalPV:
|
||||
if rotatedPage:
|
||||
if options.righttoleft:
|
||||
order = [2, 1]
|
||||
else:
|
||||
order = [1, 2]
|
||||
else:
|
||||
order = [1, 2]
|
||||
boxes = ["BoxT", "BoxB"]
|
||||
elif not noHorizontalPV and noVerticalPV:
|
||||
if rotatedPage:
|
||||
order = [1, 2]
|
||||
else:
|
||||
if options.righttoleft:
|
||||
order = [2, 1]
|
||||
else:
|
||||
order = [1, 2]
|
||||
boxes = ["BoxL", "BoxR"]
|
||||
else:
|
||||
if options.righttoleft:
|
||||
f.writelines(["<div id=\"BoxTL\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify=",
|
||||
"'{\"targetId\":\"BoxTL-Panel-Parent\", \"ordinal\":2}'></a></div>\n",
|
||||
"<div id=\"BoxTR\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify=",
|
||||
"'{\"targetId\":\"BoxTR-Panel-Parent\", \"ordinal\":1}'></a></div>\n",
|
||||
"<div id=\"BoxBL\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify=",
|
||||
"'{\"targetId\":\"BoxBL-Panel-Parent\", \"ordinal\":4}'></a></div>\n",
|
||||
"<div id=\"BoxBR\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify="
|
||||
"'{\"targetId\":\"BoxBR-Panel-Parent\", \"ordinal\":3}'></a></div>\n"
|
||||
])
|
||||
else:
|
||||
f.writelines(["<div id=\"BoxTL\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify=",
|
||||
"'{\"targetId\":\"BoxTL-Panel-Parent\", \"ordinal\":1}'></a></div>\n",
|
||||
"<div id=\"BoxTR\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify=",
|
||||
"'{\"targetId\":\"BoxTR-Panel-Parent\", \"ordinal\":2}'></a></div>\n",
|
||||
"<div id=\"BoxBL\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify=",
|
||||
"'{\"targetId\":\"BoxBL-Panel-Parent\", \"ordinal\":3}'></a></div>\n",
|
||||
"<div id=\"BoxBR\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify="
|
||||
"'{\"targetId\":\"BoxBR-Panel-Parent\", \"ordinal\":4}'></a></div>\n"
|
||||
])
|
||||
order = [1]
|
||||
boxes = ["BoxC"]
|
||||
for i in range(0, len(boxes)):
|
||||
f.writelines(["<div id=\"" + boxes[i] + "\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify=",
|
||||
"'{\"targetId\":\"" + boxes[i] + "-Panel-Parent\", \"ordinal\":" + str(order[i]),
|
||||
"}'></a></div>\n"])
|
||||
if options.quality == 2:
|
||||
imgfilepv = string.split(imgfile, ".")
|
||||
imgfilepv[0] = imgfilepv[0].split("_kccx")[0].replace("_kccnh", "").replace("_kccnv", "")
|
||||
imgfilepv[0] += "_kcchq"
|
||||
imgfilepv = string.join(imgfilepv, ".")
|
||||
else:
|
||||
imgfilepv = imgfile
|
||||
f.writelines(["<div id=\"BoxTL-Panel-Parent\" class=\"target-mag-parent\"><div id=\"BoxTL-Panel\" class=\"",
|
||||
"target-mag\"><img src=\"", "../" * backref, "Images/", postfix, imgfilepv, "\" alt=\"",
|
||||
imgfilepv, "\"/></div></div>\n",
|
||||
"<div id=\"BoxTR-Panel-Parent\" class=\"target-mag-parent\"><div id=\"BoxTR-Panel\" class=\"",
|
||||
"target-mag\"><img src=\"", "../" * backref, "Images/", postfix, imgfilepv, "\" alt=\"",
|
||||
imgfilepv, "\"/></div></div>\n",
|
||||
"<div id=\"BoxBL-Panel-Parent\" class=\"target-mag-parent\"><div id=\"BoxBL-Panel\" class=\"",
|
||||
"target-mag\"><img src=\"", "../" * backref, "Images/", postfix, imgfilepv, "\" alt=\"",
|
||||
imgfilepv, "\"/></div></div>\n",
|
||||
"<div id=\"BoxBR-Panel-Parent\" class=\"target-mag-parent\"><div id=\"BoxBR-Panel\" class=\"",
|
||||
"target-mag\"><img src=\"", "../" * backref, "Images/", postfix, imgfilepv, "\" alt=\"",
|
||||
imgfilepv, "\"/></div></div>\n"
|
||||
])
|
||||
if "_kccx" in filename[0]:
|
||||
xy = string.split(filename[0], "_kccx")[1]
|
||||
x = string.split(xy, "_kccy")[0].lstrip("0")
|
||||
y = string.split(xy, "_kccy")[1].lstrip("0")
|
||||
if x != "":
|
||||
x = "-" + str(float(x)/100) + "%"
|
||||
else:
|
||||
x = "0%"
|
||||
if y != "":
|
||||
y = "-" + str(float(y)/100) + "%"
|
||||
else:
|
||||
y = "0%"
|
||||
else:
|
||||
x = "0%"
|
||||
y = "0%"
|
||||
boxStyles = {"BoxTL": "left:" + x + ";top:" + y + ";",
|
||||
"BoxTR": "right:" + x + ";top:" + y + ";",
|
||||
"BoxBL": "left:" + x + ";bottom:" + y + ";",
|
||||
"BoxBR": "right:" + x + ";bottom:" + y + ";",
|
||||
"BoxT": "left:-25%;top:" + y + ";",
|
||||
"BoxB": "left:-25%;bottom:" + y + ";",
|
||||
"BoxL": "left:" + x + ";top:-25%;",
|
||||
"BoxR": "right:" + x + ";top:-25%;",
|
||||
"BoxC": "right:-25%;top:-25%;"
|
||||
}
|
||||
for box in boxes:
|
||||
f.writelines(["<div id=\"" + box + "-Panel-Parent\" class=\"target-mag-parent\"><div id=\"",
|
||||
"Generic-Panel\" class=\"target-mag\"><img style=\"" + boxStyles[box] + "\" src=\"",
|
||||
"../" * backref, "Images/", postfix, imgfilepv, "\" alt=\"" + imgfilepv,
|
||||
"\"/></div></div>\n",
|
||||
])
|
||||
f.writelines(["</div>\n</body>\n</html>"])
|
||||
f.close()
|
||||
return path, imgfile
|
||||
|
||||
|
||||
def buildBlankHTML(path):
|
||||
f = open(os.path.join(path, 'blank.html'), "w")
|
||||
f.writelines(["<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" ",
|
||||
"\"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n",
|
||||
"<html xmlns=\"http://www.w3.org/1999/xhtml\">\n",
|
||||
"<head>\n",
|
||||
"<title></title>\n",
|
||||
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\n",
|
||||
"</head>\n",
|
||||
"<body>\n",
|
||||
"</body>\n",
|
||||
"</html>"])
|
||||
f.close()
|
||||
return path
|
||||
|
||||
|
||||
def buildNCX(dstdir, title, chapters):
|
||||
from uuid import uuid4
|
||||
options.uuid = str(uuid4())
|
||||
@@ -173,19 +179,22 @@ def buildNCX(dstdir, title, chapters):
|
||||
"<ncx version=\"2005-1\" xml:lang=\"en-US\" xmlns=\"http://www.daisy.org/z3986/2005/ncx/\">\n",
|
||||
"<head>\n",
|
||||
"<meta name=\"dtb:uid\" content=\"", options.uuid, "\"/>\n",
|
||||
"<meta name=\"dtb:depth\" content=\"2\"/>\n",
|
||||
"<meta name=\"dtb:depth\" content=\"1\"/>\n",
|
||||
"<meta name=\"dtb:totalPageCount\" content=\"0\"/>\n",
|
||||
"<meta name=\"dtb:maxPageNumber\" content=\"0\"/>\n",
|
||||
"<meta name=\"generated\" content=\"true\"/>\n",
|
||||
"</head>\n",
|
||||
"<docTitle><text>", title, "</text></docTitle>\n",
|
||||
"<docTitle><text>", title.encode('utf-8'), "</text></docTitle>\n",
|
||||
"<navMap>"
|
||||
])
|
||||
for chapter in chapters:
|
||||
folder = chapter[0].replace(os.path.join(dstdir, 'OEBPS'), '').lstrip('/').lstrip('\\\\')
|
||||
title = os.path.basename(folder)
|
||||
if os.path.basename(folder) != "Text":
|
||||
title = os.path.basename(folder)
|
||||
filename = getImageFileName(os.path.join(folder, chapter[1]))
|
||||
f.write("<navPoint id=\"" + folder.replace('/', '_').replace('\\', '_') + "\"><navLabel><text>" + title
|
||||
+ "</text></navLabel><content src=\"" + filename[0].replace("\\", "/") + ".html\"/></navPoint>\n")
|
||||
f.write("<navPoint id=\"" + folder.replace('/', '_').replace('\\', '_') + "\"><navLabel><text>"
|
||||
+ title.encode('utf-8') + "</text></navLabel><content src=\"" + filename[0].replace("\\", "/")
|
||||
+ ".html\"/></navPoint>\n")
|
||||
f.write("</navMap>\n</ncx>")
|
||||
f.close()
|
||||
return
|
||||
@@ -197,38 +206,33 @@ def buildOPF(dstdir, title, filelist, cover=None):
|
||||
imgres = str(deviceres[0]) + "x" + str(deviceres[1])
|
||||
if options.righttoleft:
|
||||
writingmode = "horizontal-rl"
|
||||
facing = "right"
|
||||
facing1 = "right"
|
||||
facing2 = "left"
|
||||
else:
|
||||
writingmode = "horizontal-lr"
|
||||
facing = "left"
|
||||
facing1 = "left"
|
||||
facing2 = "right"
|
||||
f = open(opffile, "w")
|
||||
f.writelines(["<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
|
||||
"<package version=\"2.0\" unique-identifier=\"BookID\" xmlns=\"http://www.idpf.org/2007/opf\">\n",
|
||||
"<metadata xmlns:dc=\"http://purl.org/dc/elements/1.1/\" ",
|
||||
"xmlns:opf=\"http://www.idpf.org/2007/opf\">\n",
|
||||
"<dc:title>", title, "</dc:title>\n",
|
||||
"<package version=\"2.0\" unique-identifier=\"BookID\" ",
|
||||
"xmlns=\"http://www.idpf.org/2007/opf\">\n",
|
||||
"<metadata xmlns:opf=\"http://www.idpf.org/2007/opf\" ",
|
||||
"xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n",
|
||||
"<dc:title>", title.encode('utf-8'), "</dc:title>\n",
|
||||
"<dc:language>en-US</dc:language>\n",
|
||||
"<dc:identifier id=\"BookID\" opf:scheme=\"UUID\">", options.uuid, "</dc:identifier>\n",
|
||||
"<dc:Creator>KCC</dc:Creator>\n",
|
||||
"<meta name=\"generator\" content=\"KindleComicConverter-" + __version__ + "\"/>\n",
|
||||
"<meta name=\"RegionMagnification\" content=\"true\"/>\n",
|
||||
"<meta name=\"region-mag\" content=\"true\"/>\n",
|
||||
"<meta name=\"cover\" content=\"cover\"/>\n",
|
||||
"<meta name=\"book-type\" content=\"comic\"/>\n",
|
||||
"<meta name=\"rendition:layout\" content=\"pre-paginated\"/>\n",
|
||||
"<meta name=\"zero-gutter\" content=\"true\"/>\n",
|
||||
"<meta name=\"zero-margin\" content=\"true\"/>\n",
|
||||
"<meta name=\"fixed-layout\" content=\"true\"/>\n"
|
||||
])
|
||||
if options.landscapemode:
|
||||
f.writelines(["<meta name=\"rendition:orientation\" content=\"auto\"/>\n",
|
||||
"<meta name=\"orientation-lock\" content=\"none\"/>\n"])
|
||||
else:
|
||||
f.writelines(["<meta name=\"rendition:orientation\" content=\"portrait\"/>\n",
|
||||
"<meta name=\"orientation-lock\" content=\"portrait\"/>\n"])
|
||||
f.writelines(["<meta name=\"original-resolution\" content=\"", imgres, "\"/>\n",
|
||||
"<meta name=\"rendition:orientation\" content=\"portrait\"/>\n",
|
||||
"<meta name=\"orientation-lock\" content=\"portrait\"/>\n",
|
||||
"<meta name=\"original-resolution\" content=\"", imgres, "\"/>\n",
|
||||
"<meta name=\"primary-writing-mode\" content=\"", writingmode, "\"/>\n",
|
||||
"<meta name=\"rendition:layout\" content=\"pre-paginated\"/>\n",
|
||||
"<meta name=\"ke-border-color\" content=\"#ffffff\"/>\n",
|
||||
"<meta name=\"ke-border-width\" content=\"0\"/>\n",
|
||||
"</metadata>\n<manifest>\n<item id=\"ncx\" href=\"toc.ncx\" ",
|
||||
"media-type=\"application/x-dtbncx+xml\"/>\n"])
|
||||
if cover is not None:
|
||||
@@ -253,44 +257,10 @@ def buildOPF(dstdir, title, filelist, cover=None):
|
||||
mt = 'image/jpeg'
|
||||
f.write("<item id=\"img_" + uniqueid + "\" href=\"" + folder + "/" + path[1] + "\" media-type=\""
|
||||
+ mt + "\"/>\n")
|
||||
if options.landscapemode and splitCount > 0:
|
||||
splitCountUsed = 1
|
||||
while splitCountUsed <= splitCount:
|
||||
f.write("<item id=\"blank-page" + str(splitCountUsed) +
|
||||
"\" href=\"Text/blank.html\" media-type=\"application/xhtml+xml\"/>\n")
|
||||
splitCountUsed += 1
|
||||
f.write("<item id=\"css\" href=\"Text/style.css\" media-type=\"text/css\"/>\n")
|
||||
f.write("</manifest>\n<spine toc=\"ncx\">\n")
|
||||
splitCountUsed = 1
|
||||
for entry in reflist:
|
||||
if "_kcca" in str(entry):
|
||||
# noinspection PyRedundantParentheses
|
||||
if ((options.righttoleft and facing == 'left') or (not options.righttoleft and facing == 'right')) and\
|
||||
options.landscapemode:
|
||||
f.write("<itemref idref=\"blank-page" + str(splitCountUsed) + "\" properties=\"layout-blank\"/>\n")
|
||||
splitCountUsed += 1
|
||||
if options.landscapemode:
|
||||
f.write("<itemref idref=\"page_" + entry + "\" properties=\"page-spread-" + facing1 + "\"/>\n")
|
||||
else:
|
||||
f.write("<itemref idref=\"page_" + entry + "\"/>\n")
|
||||
elif "_kccb" in str(entry):
|
||||
if options.landscapemode:
|
||||
f.write("<itemref idref=\"page_" + entry + "\" properties=\"page-spread-" + facing2 + "\"/>\n")
|
||||
else:
|
||||
f.write("<itemref idref=\"page_" + entry + "\"/>\n")
|
||||
if options.righttoleft:
|
||||
facing = "right"
|
||||
else:
|
||||
facing = "left"
|
||||
else:
|
||||
if options.landscapemode:
|
||||
f.write("<itemref idref=\"page_" + entry + "\" properties=\"page-spread-" + facing + "\"/>\n")
|
||||
else:
|
||||
f.write("<itemref idref=\"page_" + entry + "\"/>\n")
|
||||
if facing == 'right':
|
||||
facing = 'left'
|
||||
else:
|
||||
facing = 'right'
|
||||
f.write("<itemref idref=\"page_" + entry + "\"/>\n")
|
||||
f.write("</spine>\n<guide>\n</guide>\n</package>\n")
|
||||
f.close()
|
||||
os.mkdir(os.path.join(dstdir, 'META-INF'))
|
||||
@@ -322,24 +292,22 @@ def getImageFileName(imgfile):
|
||||
return filename
|
||||
|
||||
|
||||
def applyImgOptimization(img, isSplit, toRight, options, overrideQuality=5):
|
||||
if not options.webtoon:
|
||||
def applyImgOptimization(img, opt, overrideQuality=5):
|
||||
img.getImageFill(opt.webtoon)
|
||||
if not opt.webtoon:
|
||||
img.cropWhiteSpace(10.0)
|
||||
if options.cutpagenumbers and not options.webtoon:
|
||||
if opt.cutpagenumbers and not opt.webtoon:
|
||||
img.cutPageNumber()
|
||||
img.optimizeImage(options.gamma)
|
||||
img.optimizeImage(opt.gamma)
|
||||
if overrideQuality != 5:
|
||||
img.resizeImage(options.upscale, options.stretch, options.black_borders, isSplit, toRight,
|
||||
options.landscapemode, overrideQuality)
|
||||
img.resizeImage(opt.upscale, opt.stretch, opt.bordersColor, overrideQuality)
|
||||
else:
|
||||
img.resizeImage(options.upscale, options.stretch, options.black_borders, isSplit, toRight,
|
||||
options.landscapemode, options.quality)
|
||||
if options.forcepng and not options.forcecolor:
|
||||
img.resizeImage(opt.upscale, opt.stretch, opt.bordersColor, opt.quality)
|
||||
if opt.forcepng and not opt.forcecolor:
|
||||
img.quantizeImage()
|
||||
|
||||
|
||||
def dirImgProcess(path):
|
||||
global options, splitCount
|
||||
work = []
|
||||
pagenumber = 0
|
||||
pagenumbermodifier = 0
|
||||
@@ -364,7 +332,7 @@ def dirImgProcess(path):
|
||||
pass
|
||||
if not GUI.conversionAlive:
|
||||
pool.terminate()
|
||||
rmtree(os.path.join(path, '..', '..'))
|
||||
rmtree(os.path.join(path, '..', '..'), True)
|
||||
raise UserWarning("Conversion interrupted.")
|
||||
GUI.emit(QtCore.SIGNAL("progressBarTick"))
|
||||
pool.join()
|
||||
@@ -372,23 +340,22 @@ def dirImgProcess(path):
|
||||
try:
|
||||
splitpages = splitpages.get()
|
||||
except:
|
||||
rmtree(os.path.join(path, '..', '..'))
|
||||
rmtree(os.path.join(path, '..', '..'), True)
|
||||
raise RuntimeError("One of workers crashed. Cause: " + str(sys.exc_info()[1]))
|
||||
splitpages = filter(None, splitpages)
|
||||
splitpages.sort()
|
||||
for page in splitpages:
|
||||
if (page + pagenumbermodifier) % 2 == 0:
|
||||
splitCount += 1
|
||||
pagenumbermodifier += 1
|
||||
pagenumbermodifier += 1
|
||||
else:
|
||||
rmtree(os.path.join(path, '..', '..'))
|
||||
rmtree(os.path.join(path, '..', '..'), True)
|
||||
raise UserWarning("Source directory is empty.")
|
||||
|
||||
|
||||
def fileImgProcess_init(queue, options):
|
||||
def fileImgProcess_init(queue, opt):
|
||||
fileImgProcess.queue = queue
|
||||
fileImgProcess.options = options
|
||||
fileImgProcess.options = opt
|
||||
|
||||
|
||||
# noinspection PyUnresolvedReferences
|
||||
@@ -396,59 +363,53 @@ def fileImgProcess(work):
|
||||
afile = work[0]
|
||||
dirpath = work[1]
|
||||
pagenumber = work[2]
|
||||
options = fileImgProcess.options
|
||||
opt = fileImgProcess.options
|
||||
output = None
|
||||
if options.verbose:
|
||||
print "Optimizing " + afile + " for " + options.profile
|
||||
if opt.verbose:
|
||||
print "Optimizing " + afile + " for " + opt.profile
|
||||
else:
|
||||
print ".",
|
||||
fileImgProcess.queue.put(".")
|
||||
img = image.ComicPage(os.path.join(dirpath, afile), options.profileData)
|
||||
if options.quality == 2:
|
||||
img = image.ComicPage(os.path.join(dirpath, afile), opt.profileData)
|
||||
if opt.quality == 2:
|
||||
wipe = False
|
||||
else:
|
||||
wipe = True
|
||||
if options.nosplitrotate:
|
||||
if opt.nosplitrotate:
|
||||
split = None
|
||||
else:
|
||||
split = img.splitPage(dirpath, options.righttoleft, options.rotate)
|
||||
if split is not None and split is not "R":
|
||||
if options.verbose:
|
||||
split = img.splitPage(dirpath, opt.righttoleft, opt.rotate)
|
||||
if split is not None:
|
||||
if opt.verbose:
|
||||
print "Splitted " + afile
|
||||
if options.righttoleft:
|
||||
toRight1 = False
|
||||
toRight2 = True
|
||||
else:
|
||||
toRight1 = True
|
||||
toRight2 = False
|
||||
output = pagenumber
|
||||
img0 = image.ComicPage(split[0], options.profileData)
|
||||
applyImgOptimization(img0, True, toRight1, options)
|
||||
img0.saveToDir(dirpath, options.forcepng, options.forcecolor, wipe)
|
||||
img1 = image.ComicPage(split[1], options.profileData)
|
||||
applyImgOptimization(img1, True, toRight2, options)
|
||||
img1.saveToDir(dirpath, options.forcepng, options.forcecolor, wipe)
|
||||
if options.quality == 2:
|
||||
img3 = image.ComicPage(split[0], options.profileData)
|
||||
applyImgOptimization(img3, True, toRight1, options, 0)
|
||||
img3.saveToDir(dirpath, options.forcepng, options.forcecolor, True)
|
||||
img4 = image.ComicPage(split[1], options.profileData)
|
||||
applyImgOptimization(img4, True, toRight2, options, 0)
|
||||
img4.saveToDir(dirpath, options.forcepng, options.forcecolor, True)
|
||||
img0 = image.ComicPage(split[0], opt.profileData)
|
||||
applyImgOptimization(img0, opt)
|
||||
img0.saveToDir(dirpath, opt.forcepng, opt.forcecolor, wipe)
|
||||
img1 = image.ComicPage(split[1], opt.profileData)
|
||||
applyImgOptimization(img1, opt)
|
||||
img1.saveToDir(dirpath, opt.forcepng, opt.forcecolor, wipe)
|
||||
if opt.quality == 2:
|
||||
img3 = image.ComicPage(split[0], opt.profileData)
|
||||
applyImgOptimization(img3, opt, 0)
|
||||
img3.saveToDir(dirpath, opt.forcepng, opt.forcecolor, True)
|
||||
img4 = image.ComicPage(split[1], opt.profileData)
|
||||
applyImgOptimization(img4, opt, 0)
|
||||
img4.saveToDir(dirpath, opt.forcepng, opt.forcecolor, True)
|
||||
else:
|
||||
applyImgOptimization(img, False, False, options)
|
||||
img.saveToDir(dirpath, options.forcepng, options.forcecolor, wipe, split)
|
||||
if options.quality == 2:
|
||||
img2 = image.ComicPage(os.path.join(dirpath, afile), options.profileData)
|
||||
if split == "R":
|
||||
applyImgOptimization(img, opt)
|
||||
img.saveToDir(dirpath, opt.forcepng, opt.forcecolor, wipe)
|
||||
if opt.quality == 2:
|
||||
img2 = image.ComicPage(os.path.join(dirpath, afile), opt.profileData)
|
||||
if img.rotated:
|
||||
img2.image = img2.image.rotate(90)
|
||||
applyImgOptimization(img2, False, False, options, 0)
|
||||
img2.saveToDir(dirpath, options.forcepng, options.forcecolor, True, split)
|
||||
img2.rotated = True
|
||||
applyImgOptimization(img2, opt, 0)
|
||||
img2.saveToDir(dirpath, opt.forcepng, opt.forcecolor, True)
|
||||
return output
|
||||
|
||||
|
||||
def genEpubStruct(path):
|
||||
global options
|
||||
filelist = []
|
||||
chapterlist = []
|
||||
cover = None
|
||||
@@ -508,6 +469,36 @@ def genEpubStruct(path):
|
||||
"height: ", str(panelviewsize[1]), "px;\n",
|
||||
"width: ", str(panelviewsize[0]), "px;\n",
|
||||
"}\n",
|
||||
"#Generic-Panel {\n",
|
||||
"top: 0;\n",
|
||||
"height: 100%;\n",
|
||||
"width: 100%;\n",
|
||||
"}\n",
|
||||
"#BoxC {\n",
|
||||
"top: 0;\n",
|
||||
"height: 100%;\n",
|
||||
"width: 100%;\n",
|
||||
"}\n",
|
||||
"#BoxT {\n",
|
||||
"top: 0;\n",
|
||||
"height: 50%;\n",
|
||||
"width: 100%;\n",
|
||||
"}\n",
|
||||
"#BoxB {\n",
|
||||
"bottom: 0;\n",
|
||||
"height: 50%;\n",
|
||||
"width: 100%;\n",
|
||||
"}\n",
|
||||
"#BoxL {\n",
|
||||
"left: 0;\n",
|
||||
"height: 100%;\n",
|
||||
"width: 50%;\n",
|
||||
"}\n",
|
||||
"#BoxR {\n",
|
||||
"right: 0;\n",
|
||||
"height: 100%;\n",
|
||||
"width: 50%;\n",
|
||||
"}\n",
|
||||
"#BoxTL {\n",
|
||||
"top: 0;\n",
|
||||
"left: 0;\n",
|
||||
@@ -531,47 +522,7 @@ def genEpubStruct(path):
|
||||
"right: 0;\n",
|
||||
"height: 50%;\n",
|
||||
"width: 50%;\n",
|
||||
"}\n",
|
||||
"#BoxTL-Panel {\n",
|
||||
"top: 0;\n",
|
||||
"left: 0;\n",
|
||||
"height: 100%;\n",
|
||||
"width: 100%;\n",
|
||||
"}\n",
|
||||
"#BoxTL-Panel img {\n",
|
||||
"top: 0%;\n",
|
||||
"left: 0%;\n",
|
||||
"}\n",
|
||||
"#BoxTR-Panel {\n",
|
||||
"top: 0;\n",
|
||||
"right: 0;\n",
|
||||
"height: 100%;\n",
|
||||
"width: 100%;\n",
|
||||
"}\n",
|
||||
"#BoxTR-Panel img {\n",
|
||||
"top: 0%;\n",
|
||||
"right: 0%;\n",
|
||||
"}\n",
|
||||
"#BoxBL-Panel {\n",
|
||||
"bottom: 0;\n",
|
||||
"left: 0;\n",
|
||||
"height: 100%;\n",
|
||||
"width: 100%;\n",
|
||||
"}\n",
|
||||
"#BoxBL-Panel img {\n",
|
||||
"bottom: 0%;\n",
|
||||
"left: 0%;\n",
|
||||
"}\n",
|
||||
"#BoxBR-Panel {\n",
|
||||
"bottom: 0;\n",
|
||||
"right: 0;\n",
|
||||
"height: 100%;\n",
|
||||
"width: 100%;\n",
|
||||
"}\n",
|
||||
"#BoxBR-Panel img {\n",
|
||||
"bottom: 0%;\n",
|
||||
"right: 0%;\n",
|
||||
"}"
|
||||
"}",
|
||||
])
|
||||
f.close()
|
||||
for (dirpath, dirnames, filenames) in os.walk(os.path.join(path, 'OEBPS', 'Images')):
|
||||
@@ -588,13 +539,11 @@ def genEpubStruct(path):
|
||||
'cover' + getImageFileName(filelist[-1][1])[1])
|
||||
copyfile(os.path.join(filelist[-1][0], filelist[-1][1]), cover)
|
||||
buildNCX(path, options.title, chapterlist)
|
||||
# ensure we're sorting files alphabetically
|
||||
# Ensure we're sorting files alphabetically
|
||||
convert = lambda text: int(text) if text.isdigit() else text
|
||||
alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)]
|
||||
filelist.sort(key=lambda name: (alphanum_key(name[0].lower()), alphanum_key(name[1].lower())))
|
||||
buildOPF(path, options.title, filelist, cover)
|
||||
if options.landscapemode and splitCount > 0:
|
||||
filelist.append(buildBlankHTML(os.path.join(path, 'OEBPS', 'Text')))
|
||||
|
||||
|
||||
def getWorkFolder(afile):
|
||||
@@ -608,13 +557,13 @@ def getWorkFolder(afile):
|
||||
sanitizeTreeBeforeConversion(fullPath)
|
||||
return workdir
|
||||
except OSError:
|
||||
rmtree(workdir)
|
||||
rmtree(workdir, True)
|
||||
raise
|
||||
elif afile.lower().endswith('.pdf'):
|
||||
pdf = pdfjpgextract.PdfJpgExtract(afile)
|
||||
path, njpg = pdf.extract()
|
||||
if njpg == 0:
|
||||
rmtree(path)
|
||||
rmtree(path, True)
|
||||
raise UserWarning("Failed to extract images.")
|
||||
else:
|
||||
workdir = tempfile.mkdtemp('', 'KCC-TMP-')
|
||||
@@ -624,12 +573,11 @@ def getWorkFolder(afile):
|
||||
try:
|
||||
path = cbx.extract(workdir)
|
||||
except OSError:
|
||||
rmtree(workdir)
|
||||
print 'Unrar not found, please download from ' + \
|
||||
'http://www.rarlab.com/download.htm and put into your PATH.'
|
||||
rmtree(workdir, True)
|
||||
print 'UnRAR/7za not found or file failed to extract!'
|
||||
sys.exit(21)
|
||||
else:
|
||||
rmtree(workdir)
|
||||
rmtree(workdir, True)
|
||||
raise TypeError
|
||||
move(path, path + "_temp")
|
||||
move(path + "_temp", os.path.join(path, 'OEBPS', 'Images'))
|
||||
@@ -637,10 +585,13 @@ def getWorkFolder(afile):
|
||||
|
||||
|
||||
def slugify(value):
|
||||
# Normalizes string, converts to lowercase, removes non-alpha characters,
|
||||
# and converts spaces to hyphens.
|
||||
# Normalizes string, converts to lowercase, removes non-alpha characters and converts spaces to hyphens.
|
||||
import unicodedata
|
||||
value = unicodedata.normalize('NFKD', unicode(value, 'latin1')).encode('ascii', 'ignore')
|
||||
if isinstance(value, str):
|
||||
#noinspection PyArgumentList
|
||||
value = unicodedata.normalize('NFKD', unicode(value, 'latin1')).encode('ascii', 'ignore')
|
||||
elif isinstance(value, unicode):
|
||||
value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore')
|
||||
value = re.sub('[^\w\s\.-]', '', value).strip().lower()
|
||||
value = re.sub('[-\.\s]+', '-', value)
|
||||
value = re.sub(r'([0-9]+)', r'00000\1', value)
|
||||
@@ -656,7 +607,8 @@ def sanitizeTree(filetree):
|
||||
else:
|
||||
splitname = os.path.splitext(name)
|
||||
slugified = slugify(splitname[0])
|
||||
while os.path.exists(os.path.join(root, slugified + splitname[1])):
|
||||
while os.path.exists(os.path.join(root, slugified + splitname[1])) and splitname[0].upper()\
|
||||
!= slugified.upper():
|
||||
slugified += "A"
|
||||
os.rename(os.path.join(root, name), os.path.join(root, slugified + splitname[1]))
|
||||
for name in dirs:
|
||||
@@ -664,7 +616,7 @@ def sanitizeTree(filetree):
|
||||
os.remove(os.path.join(root, name))
|
||||
else:
|
||||
slugified = slugify(name)
|
||||
while os.path.exists(os.path.join(root, slugified)):
|
||||
while os.path.exists(os.path.join(root, slugified)) and name.upper() != slugified.upper():
|
||||
slugified += "A"
|
||||
os.rename(os.path.join(root, name), os.path.join(root, slugified))
|
||||
|
||||
@@ -689,6 +641,7 @@ def getDirectorySize(start_path='.'):
|
||||
return total_size
|
||||
|
||||
|
||||
# noinspection PyUnusedLocal
|
||||
def createNewTome(parentPath):
|
||||
tomePathRoot = tempfile.mkdtemp('', 'KCC-TMP-')
|
||||
#tomePathRoot = tempfile.mkdtemp('', 'KCC-TMP-', parentPath)
|
||||
@@ -843,21 +796,22 @@ def Usage():
|
||||
|
||||
|
||||
def main(argv=None, qtGUI=None):
|
||||
global parser, options, epub_path, splitCount, GUI
|
||||
global parser, options, GUI
|
||||
parser = OptionParser(usage="Usage: %prog [options] comic_file|comic_folder", add_help_option=False)
|
||||
mainOptions = OptionGroup(parser, "MAIN")
|
||||
experimentalOptions = OptionGroup(parser, "EXPERIMENTAL")
|
||||
processingOptions = OptionGroup(parser, "PROCESSING")
|
||||
outputOptions = OptionGroup(parser, "OUTPUT SETTINGS")
|
||||
customProfileOptions = OptionGroup(parser, "CUSTOM PROFILE")
|
||||
otherOptions = OptionGroup(parser, "OTHER")
|
||||
mainOptions.add_option("-p", "--profile", action="store", dest="profile", default="KHD",
|
||||
help="Device profile (Choose one among K1, K2, K3, K4NT, K4T, KDX, KDXG, KHD, KF, KFHD,"
|
||||
" KFHD8, KFA) [Default=KHD]")
|
||||
help="Device profile (Choose one among K1, K2, K345, KDX, KHD, KF, KFHD, KFHD8, KFHDX,"
|
||||
" KFHDX8, KFA) [Default=KHD]")
|
||||
mainOptions.add_option("-q", "--quality", type="int", dest="quality", default="0",
|
||||
help="Quality of Panel View. 0 - Normal 1 - High 2 - Ultra [Default=0]")
|
||||
mainOptions.add_option("-m", "--manga-style", action="store_true", dest="righttoleft", default=False,
|
||||
help="Manga style (Right-to-left reading and splitting)")
|
||||
mainOptions.add_option("-w", "--webtoon", action="store_true", dest="webtoon", default=False,
|
||||
help="Webtoon processing mode"),
|
||||
outputOptions.add_option("-o", "--output", action="store", dest="output", default=None,
|
||||
help="Output generated file to specified directory or file")
|
||||
outputOptions.add_option("-t", "--title", action="store", dest="title", default="defaulttitle",
|
||||
@@ -866,14 +820,14 @@ def main(argv=None, qtGUI=None):
|
||||
help="Outputs a CBZ archive and does not generate EPUB")
|
||||
outputOptions.add_option("--batchsplit", action="store_true", dest="batchsplit", default=False,
|
||||
help="Split output into multiple files"),
|
||||
experimentalOptions.add_option("-w", "--webtoon", action="store_true", dest="webtoon", default=False,
|
||||
help="Webtoon processing mode"),
|
||||
processingOptions.add_option("--blackborders", action="store_true", dest="black_borders", default=False,
|
||||
help="Use black borders instead of white ones")
|
||||
help="Disable autodetection and force black borders")
|
||||
processingOptions.add_option("--whiteborders", action="store_true", dest="white_borders", default=False,
|
||||
help="Disable autodetection and force white borders")
|
||||
processingOptions.add_option("--forcecolor", action="store_true", dest="forcecolor", default=False,
|
||||
help="Don't convert images to grayscale")
|
||||
processingOptions.add_option("--forcepng", action="store_true", dest="forcepng", default=False,
|
||||
help="Create PNG files instead JPEG (For non-Kindle devices)")
|
||||
help="Create PNG files instead JPEG")
|
||||
processingOptions.add_option("--gamma", type="float", dest="gamma", default="0.0",
|
||||
help="Apply gamma correction to linearize the image [Default=Auto]")
|
||||
processingOptions.add_option("--nocutpagenumbers", action="store_false", dest="cutpagenumbers", default=True,
|
||||
@@ -897,7 +851,6 @@ def main(argv=None, qtGUI=None):
|
||||
otherOptions.add_option("-h", "--help", action="help",
|
||||
help="Show this help message and exit")
|
||||
parser.add_option_group(mainOptions)
|
||||
parser.add_option_group(experimentalOptions)
|
||||
parser.add_option_group(outputOptions)
|
||||
parser.add_option_group(processingOptions)
|
||||
parser.add_option_group(customProfileOptions)
|
||||
@@ -920,7 +873,6 @@ def main(argv=None, qtGUI=None):
|
||||
comic2panel.main(['-y ' + str(options.customheight), '-i', path], qtGUI)
|
||||
else:
|
||||
comic2panel.main(['-y ' + str(image.ProfileData.Profiles[options.profile][1][1]), '-i', path], qtGUI)
|
||||
splitCount = 0
|
||||
if options.imgproc:
|
||||
print "\nProcessing images..."
|
||||
if GUI:
|
||||
@@ -959,7 +911,7 @@ def main(argv=None, qtGUI=None):
|
||||
filepath.append(getOutputFilename(args[0], options.output, '.epub', ''))
|
||||
make_archive(tome + '_comic', 'zip', tome)
|
||||
move(tome + '_comic.zip', filepath[-1])
|
||||
rmtree(tome)
|
||||
rmtree(tome, True)
|
||||
return filepath
|
||||
|
||||
|
||||
@@ -978,51 +930,39 @@ def getOutputFilename(srcpath, wantedname, ext, tomeNumber):
|
||||
else:
|
||||
filename = os.path.splitext(srcpath)[0] + tomeNumber + ext
|
||||
if os.path.isfile(filename):
|
||||
filename = os.path.splitext(filename)[0] + '_kcc' + tomeNumber + ext
|
||||
counter = 0
|
||||
basename = os.path.splitext(filename)[0]
|
||||
while os.path.isfile(basename + '_kcc' + str(counter) + ext):
|
||||
counter += 1
|
||||
filename = basename + '_kcc' + str(counter) + ext
|
||||
return filename
|
||||
|
||||
|
||||
def checkOptions():
|
||||
global options
|
||||
# Webtoon mode mandatory options
|
||||
if options.webtoon:
|
||||
options.nosplitrotate = True
|
||||
options.black_borders = False
|
||||
options.quality = 0
|
||||
# Landscape mode is only supported by Kindle Touch and Paperwhite.
|
||||
if options.profile == 'K4T' or options.profile == 'KHD':
|
||||
options.landscapemode = True
|
||||
else:
|
||||
options.landscapemode = False
|
||||
# Older Kindle don't support Virtual Panel View. We providing them configuration that will fake that feature.
|
||||
# Ultra quality mode require Real Panel View. Landscape mode don't work correcly without Virtual Panel View.
|
||||
if options.profile == 'K3' or options.profile == 'K4NT' or options.quality == 2:
|
||||
# Real Panel View
|
||||
options.panelview = True
|
||||
options.landscapemode = False
|
||||
else:
|
||||
# Virtual Panel View
|
||||
options.panelview = False
|
||||
options.panelview = True
|
||||
options.bordersColor = None
|
||||
if options.white_borders:
|
||||
options.bordersColor = "white"
|
||||
if options.black_borders:
|
||||
options.bordersColor = "black"
|
||||
# Disabling grayscale conversion for Kindle Fire family.
|
||||
if options.profile == 'KF' or options.profile == 'KFHD' or options.profile == 'KFHD8' or options.forcecolor:
|
||||
if options.profile == 'KF' or options.profile == 'KFHD' or options.profile == 'KFHD8' or options.profile == 'KFHDX'\
|
||||
or options.profile == 'KFHDX8' or options.forcecolor:
|
||||
options.forcecolor = True
|
||||
else:
|
||||
options.forcecolor = False
|
||||
# Mixing vertical and horizontal pages require real Panel View.
|
||||
# Landscape mode don't work correcly without Virtual Panel View.
|
||||
if options.rotate:
|
||||
options.panelview = True
|
||||
options.landscapemode = False
|
||||
# Older Kindle don't need higher resolution files due lack of Panel View.
|
||||
# Kindle Fire family have very high resolution. Bigger images are not needed.
|
||||
if options.profile == 'K1' or options.profile == 'K2' or options.profile == 'KDX' or options.profile == 'KDXG'\
|
||||
or options.profile == 'KF' or options.profile == 'KFHD' or options.profile == 'KFHD8':
|
||||
if options.profile == 'K1' or options.profile == 'K2' or options.profile == 'KDX':
|
||||
options.quality = 0
|
||||
if options.profile == 'K1' or options.profile == 'K2' or options.profile == 'KDX' or options.profile == 'KDXG':
|
||||
options.panelview = False
|
||||
# Disable all Kindle features
|
||||
options.panelview = False
|
||||
# Webtoon mode mandatory options
|
||||
if options.webtoon:
|
||||
options.nosplitrotate = True
|
||||
options.quality = 0
|
||||
options.panelview = False
|
||||
# Disable all Kindle features for other e-readers
|
||||
if options.profile == 'OTHER':
|
||||
options.landscapemode = False
|
||||
options.panelview = False
|
||||
options.quality = 0
|
||||
# Kindle for Android profile require target resolution.
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2012 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||
# Copyright (c) 2012-2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||
# Copyright (c) 2013 Pawel Jastrzebski <pawelj@vulturis.eu>
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for
|
||||
# any purpose with or without fee is hereby granted, provided that the
|
||||
@@ -17,7 +18,7 @@
|
||||
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
__version__ = '3.2'
|
||||
__version__ = '3.4'
|
||||
__license__ = 'ISC'
|
||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
@@ -28,8 +29,11 @@ from shutil import rmtree, copytree, move
|
||||
from optparse import OptionParser, OptionGroup
|
||||
from multiprocessing import Pool, Queue, freeze_support
|
||||
try:
|
||||
# noinspection PyUnresolvedReferences,PyPackageRequirements
|
||||
# noinspection PyUnresolvedReferences
|
||||
from PIL import Image, ImageStat
|
||||
if tuple(map(int, ('2.2.1'.split(".")))) > tuple(map(int, (Image.PILLOW_VERSION.split(".")))):
|
||||
print "ERROR: Pillow 2.2.1 or newer is required!"
|
||||
exit(1)
|
||||
except ImportError:
|
||||
print "ERROR: Pillow is not installed!"
|
||||
exit(1)
|
||||
@@ -53,48 +57,9 @@ def getImageFileName(imgfile):
|
||||
return filename
|
||||
|
||||
|
||||
def getImageHistogram(image):
|
||||
histogram = image.histogram()
|
||||
RBGW = []
|
||||
for i in range(256):
|
||||
RBGW.append(histogram[i] + histogram[256 + i] + histogram[512 + i])
|
||||
white = 0
|
||||
black = 0
|
||||
for i in range(245, 256):
|
||||
white += RBGW[i]
|
||||
for i in range(11):
|
||||
black += RBGW[i]
|
||||
if white > black:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
def getImageFill(image):
|
||||
imageSize = image.size
|
||||
imageT = image.crop((0, 0, imageSize[0], 1))
|
||||
imageB = image.crop((0, imageSize[1]-1, imageSize[0], imageSize[1]))
|
||||
fill = 0
|
||||
fill += getImageHistogram(imageT)
|
||||
fill += getImageHistogram(imageB)
|
||||
if fill == 2:
|
||||
return 'KCCFB'
|
||||
elif fill == 0:
|
||||
return 'KCCFW'
|
||||
else:
|
||||
imageL = image.crop((0, 0, 1, imageSize[1]))
|
||||
imageR = image.crop((imageSize[0]-1, 0, imageSize[0], imageSize[1]))
|
||||
fill += getImageHistogram(imageL)
|
||||
fill += getImageHistogram(imageR)
|
||||
if fill >= 2:
|
||||
return 'KCCFB'
|
||||
else:
|
||||
return 'KCCFW'
|
||||
|
||||
|
||||
def sanitizePanelSize(panel, options):
|
||||
def sanitizePanelSize(panel, opt):
|
||||
newPanels = []
|
||||
if panel[2] > 8 * options.height:
|
||||
if panel[2] > 8 * opt.height:
|
||||
diff = (panel[2] / 8)
|
||||
newPanels.append([panel[0], panel[1] - diff*7, diff])
|
||||
newPanels.append([panel[1] - diff*7, panel[1] - diff*6, diff])
|
||||
@@ -104,13 +69,13 @@ def sanitizePanelSize(panel, options):
|
||||
newPanels.append([panel[1] - diff*3, panel[1] - diff*2, diff])
|
||||
newPanels.append([panel[1] - diff*2, panel[1] - diff, diff])
|
||||
newPanels.append([panel[1] - diff, panel[1], diff])
|
||||
elif panel[2] > 4 * options.height:
|
||||
elif panel[2] > 4 * opt.height:
|
||||
diff = (panel[2] / 4)
|
||||
newPanels.append([panel[0], panel[1] - diff*3, diff])
|
||||
newPanels.append([panel[1] - diff*3, panel[1] - diff*2, diff])
|
||||
newPanels.append([panel[1] - diff*2, panel[1] - diff, diff])
|
||||
newPanels.append([panel[1] - diff, panel[1], diff])
|
||||
elif panel[2] > 2 * options.height:
|
||||
elif panel[2] > 2 * opt.height:
|
||||
newPanels.append([panel[0], panel[1] - (panel[2] / 2), (panel[2] / 2)])
|
||||
newPanels.append([panel[1] - (panel[2] / 2), panel[1], (panel[2] / 2)])
|
||||
else:
|
||||
@@ -118,17 +83,17 @@ def sanitizePanelSize(panel, options):
|
||||
return newPanels
|
||||
|
||||
|
||||
def splitImage_init(queue, options):
|
||||
def splitImage_init(queue, opt):
|
||||
splitImage.queue = queue
|
||||
splitImage.options = options
|
||||
splitImage.options = opt
|
||||
|
||||
|
||||
# noinspection PyUnresolvedReferences
|
||||
def splitImage(work):
|
||||
path = work[0]
|
||||
name = work[1]
|
||||
options = splitImage.options
|
||||
# Harcoded options
|
||||
opt = splitImage.options
|
||||
# Harcoded opttions
|
||||
threshold = 1.0
|
||||
delta = 15
|
||||
print ".",
|
||||
@@ -137,7 +102,7 @@ def splitImage(work):
|
||||
filePath = os.path.join(path, name)
|
||||
# Detect corrupted files
|
||||
try:
|
||||
image = Image.open(filePath)
|
||||
Image.open(filePath)
|
||||
except IOError:
|
||||
raise RuntimeError('Cannot read image file %s' % filePath)
|
||||
try:
|
||||
@@ -153,8 +118,8 @@ def splitImage(work):
|
||||
image = Image.open(filePath)
|
||||
image = image.convert('RGB')
|
||||
widthImg, heightImg = image.size
|
||||
if heightImg > options.height:
|
||||
if options.debug:
|
||||
if heightImg > opt.height:
|
||||
if opt.debug:
|
||||
from PIL import ImageDraw
|
||||
debugImage = Image.open(filePath)
|
||||
draw = ImageDraw.Draw(debugImage)
|
||||
@@ -176,23 +141,23 @@ def splitImage(work):
|
||||
if y1 + delta >= heightImg:
|
||||
y1 = heightImg - 1
|
||||
y2Temp = y1
|
||||
if options.debug:
|
||||
if opt.debug:
|
||||
draw.line([(0, y1Temp), (widthImg, y1Temp)], fill=(0, 255, 0))
|
||||
draw.line([(0, y2Temp), (widthImg, y2Temp)], fill=(255, 0, 0))
|
||||
panelHeight = y2Temp - y1Temp
|
||||
if panelHeight > delta:
|
||||
# Panels that can't be cut nicely will be forcefully splitted
|
||||
panelsCleaned = sanitizePanelSize([y1Temp, y2Temp, panelHeight], options)
|
||||
panelsCleaned = sanitizePanelSize([y1Temp, y2Temp, panelHeight], opt)
|
||||
for panel in panelsCleaned:
|
||||
panels.append(panel)
|
||||
if options.debug:
|
||||
if opt.debug:
|
||||
# noinspection PyUnboundLocalVariable
|
||||
debugImage.save(os.path.join(path, fileExpanded[0] + '-debug.png'), 'PNG')
|
||||
|
||||
# Create virtual pages
|
||||
pages = []
|
||||
currentPage = []
|
||||
pageLeft = options.height
|
||||
pageLeft = opt.height
|
||||
panelNumber = 0
|
||||
for panel in panels:
|
||||
if pageLeft - panel[2] > 0:
|
||||
@@ -202,7 +167,7 @@ def splitImage(work):
|
||||
else:
|
||||
if len(currentPage) > 0:
|
||||
pages.append(currentPage)
|
||||
pageLeft = options.height - panel[2]
|
||||
pageLeft = opt.height - panel[2]
|
||||
currentPage = [panelNumber]
|
||||
panelNumber += 1
|
||||
if len(currentPage) > 0:
|
||||
@@ -222,7 +187,7 @@ def splitImage(work):
|
||||
newPage.paste(panelImg, (0, targetHeight))
|
||||
targetHeight += panels[panel][2]
|
||||
newPage.save(os.path.join(path, fileExpanded[0] + '-' +
|
||||
str(pageNumber) + '-' + getImageFill(newPage) + '.png'), 'PNG')
|
||||
str(pageNumber) + '.png'), 'PNG')
|
||||
pageNumber += 1
|
||||
os.remove(filePath)
|
||||
|
||||
@@ -297,10 +262,10 @@ def main(argv=None, qtGUI=None):
|
||||
if GUI:
|
||||
GUI.emit(QtCore.SIGNAL("progressBarTick"), 1)
|
||||
if options.inPlace:
|
||||
rmtree(options.sourceDir, True)
|
||||
rmtree(options.sourceDir)
|
||||
move(options.targetDir, options.sourceDir)
|
||||
else:
|
||||
rmtree(options.targetDir)
|
||||
rmtree(options.targetDir, True)
|
||||
raise UserWarning("Source directory is empty.")
|
||||
else:
|
||||
raise UserWarning("Provided path is not a directory.")
|
||||
|
||||
241
kcc/image.py
241
kcc/image.py
@@ -1,6 +1,7 @@
|
||||
# Copyright (C) 2010 Alex Yatskov
|
||||
# Copyright (C) 2011 Stanislav (proDOOMman) Kosolapov <prodoomman@gmail.com>
|
||||
# Copyright (C) 2012-2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||
# Copyright (C) 2013 Pawel Jastrzebski <pawelj@vulturis.eu>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -21,14 +22,20 @@ __docformat__ = 'restructuredtext en'
|
||||
|
||||
import os
|
||||
try:
|
||||
# noinspection PyUnresolvedReferences,PyPackageRequirements
|
||||
# noinspection PyUnresolvedReferences
|
||||
from PIL import Image, ImageOps, ImageStat, ImageChops
|
||||
if tuple(map(int, ('2.2.1'.split(".")))) > tuple(map(int, (Image.PILLOW_VERSION.split(".")))):
|
||||
print "ERROR: Pillow 2.2.1 or newer is required!"
|
||||
exit(1)
|
||||
except ImportError:
|
||||
print "ERROR: Pillow is not installed!"
|
||||
exit(1)
|
||||
|
||||
|
||||
class ProfileData:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
Palette4 = [
|
||||
0x00, 0x00, 0x00,
|
||||
0x55, 0x55, 0x55,
|
||||
@@ -73,38 +80,57 @@ class ProfileData:
|
||||
0xff, 0xff, 0xff,
|
||||
]
|
||||
|
||||
PalleteNull = [
|
||||
]
|
||||
|
||||
Profiles = {
|
||||
'K1': ("Kindle 1", (600, 800), Palette4, 1.8, (900, 1200)),
|
||||
'K2': ("Kindle 2", (600, 800), Palette15, 1.8, (900, 1200)),
|
||||
'K3': ("Kindle Keyboard", (600, 800), Palette16, 1.8, (900, 1200)),
|
||||
'K4NT': ("Kindle Non-Touch", (600, 800), Palette16, 1.8, (900, 1200)),
|
||||
'K4T': ("Kindle Touch", (600, 800), Palette16, 1.8, (900, 1200)),
|
||||
'K1': ("Kindle 1", (600, 670), Palette4, 1.8, (900, 1005)),
|
||||
'K2': ("Kindle 2", (600, 670), Palette15, 1.8, (900, 1005)),
|
||||
'K345': ("Kindle", (600, 800), Palette16, 1.8, (900, 1200)),
|
||||
'KHD': ("Kindle Paperwhite", (758, 1024), Palette16, 1.8, (1137, 1536)),
|
||||
'KDX': ("Kindle DX", (824, 1200), Palette15, 1.8, (1236, 1800)),
|
||||
'KDXG': ("Kindle DXG", (824, 1200), Palette16, 1.8, (1236, 1800)),
|
||||
'KF': ("Kindle Fire", (600, 1024), Palette16, 1.0, (900, 1536)),
|
||||
'KFHD': ("Kindle Fire HD 7\"", (800, 1280), Palette16, 1.0, (1200, 1920)),
|
||||
'KFHD8': ("Kindle Fire HD 8.9\"", (1200, 1920), Palette16, 1.0, (1800, 2880)),
|
||||
'KFA': ("Kindle for Android", (0, 0), Palette16, 1.0, (0, 0)),
|
||||
'KDX': ("Kindle DX/DXG", (824, 1000), Palette16, 1.8, (1236, 1500)),
|
||||
'KF': ("Kindle Fire", (600, 1024), PalleteNull, 1.0, (900, 1536)),
|
||||
'KFHD': ("K. Fire HD 7\"", (800, 1280), PalleteNull, 1.0, (1200, 1920)),
|
||||
'KFHD8': ("K. Fire HD 8.9\"", (1200, 1920), PalleteNull, 1.0, (1800, 2880)),
|
||||
'KFHDX': ("K. Fire HDX 7\"", (1200, 1920), PalleteNull, 1.0, (1800, 2880)),
|
||||
'KFHDX8': ("K. Fire HDX 8.9\"", (1600, 2560), PalleteNull, 1.0, (2400, 3840)),
|
||||
'KFA': ("Kindle for Android", (0, 0), PalleteNull, 1.0, (0, 0)),
|
||||
'OTHER': ("Other", (0, 0), Palette16, 1.8, (0, 0)),
|
||||
}
|
||||
|
||||
ProfileLabels = {
|
||||
"Kindle 1": 'K1',
|
||||
"Kindle 2": 'K2',
|
||||
"Kindle 3/Keyboard": 'K3',
|
||||
"Kindle 4/Non-Touch": 'K4NT',
|
||||
"Kindle 4/Touch": 'K4T',
|
||||
"Kindle": 'K345',
|
||||
"Kindle Paperwhite": 'KHD',
|
||||
"Kindle DX": 'KDX',
|
||||
"Kindle DXG": 'KDXG',
|
||||
"Kindle DX/DXG": 'KDX',
|
||||
"Kindle Fire": 'KF',
|
||||
"Kindle Fire HD 7\"": 'KFHD',
|
||||
"Kindle Fire HD 8.9\"": 'KFHD8',
|
||||
"K. Fire HD 7\"": 'KFHD',
|
||||
"K. Fire HD 8.9\"": 'KFHD8',
|
||||
"K. Fire HDX 7\"": 'KFHDX',
|
||||
"K. Fire HDX 8.9\"": 'KFHDX8',
|
||||
"Kindle for Android": 'KFA',
|
||||
"Other": 'OTHER'
|
||||
}
|
||||
|
||||
ProfileLabelsGUI = [
|
||||
"Kindle Paperwhite",
|
||||
"Kindle",
|
||||
"Separator",
|
||||
"K. Fire HD 7\"",
|
||||
"K. Fire HD 8.9\"",
|
||||
"K. Fire HDX 7\"",
|
||||
"K. Fire HDX 8.9\"",
|
||||
"Separator",
|
||||
"Kindle for Android",
|
||||
"Other",
|
||||
"Separator",
|
||||
"Kindle 1",
|
||||
"Kindle 2",
|
||||
"Kindle DX/DXG",
|
||||
"Kindle Fire"
|
||||
]
|
||||
|
||||
|
||||
class ComicPage:
|
||||
def __init__(self, source, device):
|
||||
@@ -133,23 +159,35 @@ class ComicPage:
|
||||
raise RuntimeError('Image file %s is corrupted' % source)
|
||||
self.image = Image.open(source)
|
||||
self.image = self.image.convert('RGB')
|
||||
self.rotated = None
|
||||
self.border = None
|
||||
self.noHPV = None
|
||||
self.noVPV = None
|
||||
self.fill = None
|
||||
|
||||
def saveToDir(self, targetdir, forcepng, color, wipe, suffix=None):
|
||||
def saveToDir(self, targetdir, forcepng, color, wipe):
|
||||
try:
|
||||
if not color:
|
||||
self.image = self.image.convert('L') # convert to grayscale
|
||||
if suffix == "R":
|
||||
suffix = "_kccrotated"
|
||||
else:
|
||||
suffix = ""
|
||||
suffix = ""
|
||||
if not color and not forcepng:
|
||||
self.image = self.image.convert('L')
|
||||
if self.rotated:
|
||||
suffix += "_kccrot"
|
||||
if wipe:
|
||||
os.remove(os.path.join(targetdir, self.filename))
|
||||
else:
|
||||
suffix += "_kcchq"
|
||||
if self.noHPV:
|
||||
suffix += "_kccnh"
|
||||
if self.noVPV:
|
||||
suffix += "_kccnv"
|
||||
if self.border:
|
||||
suffix += "_kccx" + str(self.border[0]) + "_kccy" + str(self.border[1])
|
||||
if forcepng:
|
||||
self.image.save(os.path.join(targetdir, os.path.splitext(self.filename)[0] + suffix + ".png"), "PNG")
|
||||
self.image.save(os.path.join(targetdir, os.path.splitext(self.filename)[0] + suffix + ".png"), "PNG",
|
||||
optimize=1)
|
||||
else:
|
||||
self.image.save(os.path.join(targetdir, os.path.splitext(self.filename)[0] + suffix + ".jpg"), "JPEG")
|
||||
self.image.save(os.path.join(targetdir, os.path.splitext(self.filename)[0] + suffix + ".jpg"), "JPEG",
|
||||
optimize=1)
|
||||
except IOError as e:
|
||||
raise RuntimeError('Cannot write image in directory %s: %s' % (targetdir, e))
|
||||
|
||||
@@ -162,81 +200,113 @@ class ComicPage:
|
||||
self.image = ImageOps.autocontrast(Image.eval(self.image, lambda a: 255 * (a / 255.) ** gamma))
|
||||
|
||||
def quantizeImage(self):
|
||||
self.image = self.image.convert('L') # convert to grayscale
|
||||
self.image = self.image.convert("RGB") # convert back to RGB
|
||||
colors = len(self.palette) / 3
|
||||
if colors < 256:
|
||||
self.palette += self.palette[:3] * (256 - colors)
|
||||
palImg = Image.new('P', (1, 1))
|
||||
palImg.putpalette(self.palette)
|
||||
self.image = self.image.convert('L')
|
||||
self.image = self.image.convert('RGB')
|
||||
# Quantize is deprecated but new function call it internally anyway...
|
||||
self.image = self.image.quantize(palette=palImg)
|
||||
|
||||
def resizeImage(self, upscale=False, stretch=False, black_borders=False, isSplit=False, toRight=False,
|
||||
landscapeMode=False, qualityMode=0):
|
||||
def resizeImage(self, upscale=False, stretch=False, bordersColor=None, qualityMode=0):
|
||||
# High-quality downscaling filter
|
||||
method = Image.ANTIALIAS
|
||||
if '-KCCFW' in str(self.filename):
|
||||
fill = 'white'
|
||||
elif '-KCCFB' in str(self.filename):
|
||||
fill = 'black'
|
||||
if bordersColor:
|
||||
fill = bordersColor
|
||||
else:
|
||||
if black_borders:
|
||||
fill = 'black'
|
||||
else:
|
||||
fill = 'white'
|
||||
fill = self.fill
|
||||
if qualityMode == 0:
|
||||
size = (self.size[0], self.size[1])
|
||||
generateBorder = True
|
||||
elif qualityMode == 1:
|
||||
size = (self.panelviewsize[0], self.panelviewsize[1])
|
||||
generateBorder = True
|
||||
else:
|
||||
size = (self.panelviewsize[0], self.panelviewsize[1])
|
||||
# Kindle Paperwhite/Touch - Force upscale of splited pages to increase readability
|
||||
if isSplit and landscapeMode:
|
||||
upscale = True
|
||||
generateBorder = False
|
||||
# If image is smaller than screen and upscale is off - Just expand it
|
||||
if self.image.size[0] <= self.size[0] and self.image.size[1] <= self.size[1]:
|
||||
if not upscale:
|
||||
borderw = (self.size[0] - self.image.size[0]) / 2
|
||||
borderh = (self.size[1] - self.image.size[1]) / 2
|
||||
self.image = ImageOps.expand(self.image, border=(borderw, borderh), fill=fill)
|
||||
if generateBorder:
|
||||
if (self.image.size[0]-(2*borderw))*1.5 < self.size[0]:
|
||||
self.noHPV = True
|
||||
if (self.image.size[1]-(2*borderh))*1.5 < self.size[1]:
|
||||
self.noVPV = True
|
||||
self.border = [int(round(float(borderw)/float(self.image.size[0])*100, 2)*100*1.5),
|
||||
int(round(float(borderh)/float(self.image.size[1])*100, 2)*100*1.5)]
|
||||
return self.image
|
||||
else:
|
||||
method = Image.BILINEAR
|
||||
if stretch: # if stretching call directly resize() without other considerations.
|
||||
# Cubic spline interpolation in a 4x4 environment
|
||||
method = Image.BICUBIC
|
||||
# If stretching is on - Resize without other considerations
|
||||
if stretch:
|
||||
self.image = self.image.resize(size, method)
|
||||
if generateBorder:
|
||||
if fill == 'white':
|
||||
border = ImageOps.invert(self.image).getbbox()
|
||||
else:
|
||||
border = self.image.getbbox()
|
||||
if border is not None:
|
||||
if (border[2]-border[0])*1.5 < self.size[0]:
|
||||
self.noHPV = True
|
||||
if (border[3]-border[1])*1.5 < self.size[1]:
|
||||
self.noVPV = True
|
||||
self.border = [int(round(float(border[0])/float(self.image.size[0])*100, 2)*100*1.5),
|
||||
int(round(float(border[1])/float(self.image.size[1])*100, 2)*100*1.5)]
|
||||
else:
|
||||
self.border = [0, 0]
|
||||
self.noHPV = True
|
||||
self.noVPV = True
|
||||
return self.image
|
||||
# Otherwise - Upscale/Downscale
|
||||
ratioDev = float(self.size[0]) / float(self.size[1])
|
||||
if (float(self.image.size[0]) / float(self.image.size[1])) < ratioDev:
|
||||
if isSplit and landscapeMode:
|
||||
diff = int(self.image.size[1] * ratioDev) - self.image.size[0]
|
||||
self.image = ImageOps.expand(self.image, border=(diff / 2, 0), fill=fill)
|
||||
tempImg = Image.new(self.image.mode, (self.image.size[0] + diff, self.image.size[1]), fill)
|
||||
if toRight:
|
||||
tempImg.paste(self.image, (diff, 0))
|
||||
else:
|
||||
tempImg.paste(self.image, (0, 0))
|
||||
self.image = tempImg
|
||||
else:
|
||||
diff = int(self.image.size[1] * ratioDev) - self.image.size[0]
|
||||
self.image = ImageOps.expand(self.image, border=(diff / 2, 0), fill=fill)
|
||||
diff = int(self.image.size[1] * ratioDev) - self.image.size[0]
|
||||
self.image = ImageOps.expand(self.image, border=(diff / 2, 0), fill=fill)
|
||||
elif (float(self.image.size[0]) / float(self.image.size[1])) > ratioDev:
|
||||
diff = int(self.image.size[0] / ratioDev) - self.image.size[1]
|
||||
self.image = ImageOps.expand(self.image, border=(0, diff / 2), fill=fill)
|
||||
self.image = ImageOps.fit(self.image, size, method=method, centering=(0.5, 0.5))
|
||||
if generateBorder:
|
||||
if fill == 'white':
|
||||
border = ImageOps.invert(self.image).getbbox()
|
||||
else:
|
||||
border = self.image.getbbox()
|
||||
if border is not None:
|
||||
if (border[2]-border[0])*1.5 < self.size[0]:
|
||||
self.noHPV = True
|
||||
if (border[3]-border[1])*1.5 < self.size[1]:
|
||||
self.noVPV = True
|
||||
self.border = [int(round(float(border[0])/float(self.image.size[0])*100, 2)*100*1.5),
|
||||
int(round(float(border[1])/float(self.image.size[1])*100, 2)*100*1.5)]
|
||||
else:
|
||||
self.border = [0, 0]
|
||||
self.noHPV = True
|
||||
self.noVPV = True
|
||||
return self.image
|
||||
|
||||
def splitPage(self, targetdir, righttoleft=False, rotate=False):
|
||||
width, height = self.image.size
|
||||
dstwidth, dstheight = self.size
|
||||
#print "Image is %d x %d" % (width,height)
|
||||
# only split if origin is not oriented the same as target
|
||||
# Only split if origin is not oriented the same as target
|
||||
if (width > height) != (dstwidth > dstheight):
|
||||
if rotate:
|
||||
self.image = self.image.rotate(90)
|
||||
return "R"
|
||||
self.rotated = True
|
||||
return None
|
||||
else:
|
||||
self.rotated = False
|
||||
if width > height:
|
||||
# source is landscape, so split by the width
|
||||
# Source is landscape, so split by the width
|
||||
leftbox = (0, 0, width / 2, height)
|
||||
rightbox = (width / 2, 0, width, height)
|
||||
else:
|
||||
# source is portrait and target is landscape, so split by the height
|
||||
# Source is portrait and target is landscape, so split by the height
|
||||
leftbox = (0, 0, width, height / 2)
|
||||
rightbox = (0, height / 2, width, height)
|
||||
filename = os.path.splitext(self.filename)
|
||||
@@ -256,6 +326,7 @@ class ComicPage:
|
||||
raise RuntimeError('Cannot write image in directory %s: %s' % (targetdir, e))
|
||||
return fileone, filetwo
|
||||
else:
|
||||
self.rotated = False
|
||||
return None
|
||||
|
||||
def cutPageNumber(self):
|
||||
@@ -351,4 +422,48 @@ class ComicPage:
|
||||
# print "Right crop: %s"%diff
|
||||
self.image = self.image.crop((0, 0, widthImg - diff, heightImg))
|
||||
# print "New size: %sx%s"%(self.image.size[0],self.image.size[1])
|
||||
return self.image
|
||||
return self.image
|
||||
|
||||
def getImageHistogram(self, image):
|
||||
histogram = image.histogram()
|
||||
RBGW = []
|
||||
pixelCount = 0
|
||||
for i in range(256):
|
||||
pixelCount += histogram[i] + histogram[256 + i] + histogram[512 + i]
|
||||
RBGW.append(histogram[i] + histogram[256 + i] + histogram[512 + i])
|
||||
white = 0
|
||||
black = 0
|
||||
for i in range(245, 256):
|
||||
white += RBGW[i]
|
||||
for i in range(11):
|
||||
black += RBGW[i]
|
||||
if black > white and black > pixelCount*0.5:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def getImageFill(self, isWebToon):
|
||||
fill = 0
|
||||
if isWebToon or self.rotated:
|
||||
fill += self.getImageHistogram(self.image.crop((0, 0, self.image.size[0], 5)))
|
||||
fill += self.getImageHistogram(self.image.crop((0, self.image.size[1]-5, self.image.size[0],
|
||||
self.image.size[1])))
|
||||
else:
|
||||
fill += self.getImageHistogram(self.image.crop((0, 0, 5, self.image.size[1])))
|
||||
fill += self.getImageHistogram(self.image.crop((self.image.size[0]-5, 0, self.image.size[0],
|
||||
self.image.size[1])))
|
||||
if fill == 2:
|
||||
self.fill = 'black'
|
||||
elif fill == 0:
|
||||
self.fill = 'white'
|
||||
else:
|
||||
fill = 0
|
||||
fill += self.getImageHistogram(self.image.crop((0, 0, 5, 5)))
|
||||
fill += self.getImageHistogram(self.image.crop((self.image.size[0]-5, 0, self.image.size[0], 5)))
|
||||
fill += self.getImageHistogram(self.image.crop((0, self.image.size[1]-5, 5, self.image.size[1])))
|
||||
fill += self.getImageHistogram(self.image.crop((self.image.size[0]-5, self.image.size[1]-5,
|
||||
self.image.size[0], self.image.size[1])))
|
||||
if fill > 1:
|
||||
self.fill = 'black'
|
||||
else:
|
||||
self.fill = 'white'
|
||||
384
kcc/kindlesplit.py
Normal file
384
kcc/kindlesplit.py
Normal file
@@ -0,0 +1,384 @@
|
||||
# Based on initial version of KindleUnpack. Copyright (C) 2009 Charles M. Hannum <root@ihack.net>
|
||||
# Improvements Copyright (C) 2009-2012 P. Durrant, K. Hendricks, S. Siebert, fandrieu, DiapDealer, nickredding
|
||||
# Copyright (C) 2013 Pawel Jastrzebski <pawelj@vulturis.eu>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
__license__ = 'ISC'
|
||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import struct
|
||||
# from uuid import uuid4
|
||||
|
||||
# important pdb header offsets
|
||||
unique_id_seed = 68
|
||||
number_of_pdb_records = 76
|
||||
|
||||
# important palmdoc header offsets
|
||||
book_length = 4
|
||||
book_record_count = 8
|
||||
first_pdb_record = 78
|
||||
|
||||
# important rec0 offsets
|
||||
length_of_book = 4
|
||||
mobi_header_base = 16
|
||||
mobi_header_length = 20
|
||||
mobi_type = 24
|
||||
mobi_version = 36
|
||||
first_non_text = 80
|
||||
title_offset = 84
|
||||
first_image_record = 108
|
||||
first_content_index = 192
|
||||
last_content_index = 194
|
||||
kf8_last_content_index = 192 # for KF8 mobi headers
|
||||
fcis_index = 200
|
||||
flis_index = 208
|
||||
srcs_index = 224
|
||||
srcs_count = 228
|
||||
primary_index = 244
|
||||
datp_index = 256
|
||||
huffoff = 112
|
||||
hufftbloff = 120
|
||||
|
||||
|
||||
def getint(datain, ofs, sz='L'):
|
||||
i, = struct.unpack_from('>'+sz, datain, ofs)
|
||||
return i
|
||||
|
||||
|
||||
def writeint(datain, ofs, n, length='L'):
|
||||
if length == 'L':
|
||||
return datain[:ofs]+struct.pack('>L', n)+datain[ofs+4:]
|
||||
else:
|
||||
return datain[:ofs]+struct.pack('>H', n)+datain[ofs+2:]
|
||||
|
||||
|
||||
def getsecaddr(datain, secno):
|
||||
nsec = getint(datain, number_of_pdb_records, 'H')
|
||||
assert secno >= 0 & secno < nsec, 'secno %d out of range (nsec=%d)' % (secno, nsec)
|
||||
secstart = getint(datain, first_pdb_record+secno*8)
|
||||
if secno == nsec-1:
|
||||
secend = len(datain)
|
||||
else:
|
||||
secend = getint(datain, first_pdb_record+(secno+1)*8)
|
||||
return secstart, secend
|
||||
|
||||
|
||||
def readsection(datain, secno):
|
||||
secstart, secend = getsecaddr(datain, secno)
|
||||
return datain[secstart:secend]
|
||||
|
||||
|
||||
def writesection(datain, secno, secdata): # overwrite, accounting for different length
|
||||
dataout = deletesectionrange(datain, secno, secno)
|
||||
return insertsection(dataout, secno, secdata)
|
||||
|
||||
|
||||
def nullsection(datain, secno): # make it zero-length without deleting it
|
||||
datalst = []
|
||||
nsec = getint(datain, number_of_pdb_records, 'H')
|
||||
secstart, secend = getsecaddr(datain, secno)
|
||||
zerosecstart, zerosecend = getsecaddr(datain, 0)
|
||||
dif = secend-secstart
|
||||
datalst.append(datain[:first_pdb_record])
|
||||
for i in range(0, secno+1):
|
||||
ofs, flgval = struct.unpack_from('>2L', datain, first_pdb_record+i*8)
|
||||
datalst.append(struct.pack('>L', ofs) + struct.pack('>L', flgval))
|
||||
for i in range(secno+1, nsec):
|
||||
ofs, flgval = struct.unpack_from('>2L', datain, first_pdb_record+i*8)
|
||||
ofs -= dif
|
||||
datalst.append(struct.pack('>L', ofs) + struct.pack('>L', flgval))
|
||||
lpad = zerosecstart - (first_pdb_record + 8*nsec)
|
||||
if lpad > 0:
|
||||
datalst.append('\0' * lpad)
|
||||
datalst.append(datain[zerosecstart: secstart])
|
||||
datalst.append(datain[secend:])
|
||||
dataout = "".join(datalst)
|
||||
return dataout
|
||||
|
||||
|
||||
def deletesectionrange(datain, firstsec, lastsec): # delete a range of sections
|
||||
datalst = []
|
||||
firstsecstart, firstsecend = getsecaddr(datain, firstsec)
|
||||
lastsecstart, lastsecend = getsecaddr(datain, lastsec)
|
||||
zerosecstart, zerosecend = getsecaddr(datain, 0)
|
||||
dif = lastsecend - firstsecstart + 8*(lastsec-firstsec+1)
|
||||
nsec = getint(datain, number_of_pdb_records, 'H')
|
||||
datalst.append(datain[:unique_id_seed])
|
||||
datalst.append(struct.pack('>L', 2*(nsec-(lastsec-firstsec+1))+1))
|
||||
datalst.append(datain[unique_id_seed+4:number_of_pdb_records])
|
||||
datalst.append(struct.pack('>H', nsec-(lastsec-firstsec+1)))
|
||||
newstart = zerosecstart - 8*(lastsec-firstsec+1)
|
||||
for i in range(0, firstsec):
|
||||
ofs, flgval = struct.unpack_from('>2L', datain, first_pdb_record+i*8)
|
||||
ofs -= 8 * (lastsec - firstsec + 1)
|
||||
datalst.append(struct.pack('>L', ofs) + struct.pack('>L', flgval))
|
||||
for i in range(lastsec+1, nsec):
|
||||
ofs, flgval = struct.unpack_from('>2L', datain, first_pdb_record+i*8)
|
||||
ofs -= dif
|
||||
flgval = 2*(i-(lastsec-firstsec+1))
|
||||
datalst.append(struct.pack('>L', ofs) + struct.pack('>L', flgval))
|
||||
lpad = newstart - (first_pdb_record + 8*(nsec - (lastsec - firstsec + 1)))
|
||||
if lpad > 0:
|
||||
datalst.append('\0' * lpad)
|
||||
datalst.append(datain[zerosecstart:firstsecstart])
|
||||
datalst.append(datain[lastsecend:])
|
||||
dataout = "".join(datalst)
|
||||
return dataout
|
||||
|
||||
|
||||
def insertsection(datain, secno, secdata): # insert a new section
|
||||
datalst = []
|
||||
nsec = getint(datain, number_of_pdb_records, 'H')
|
||||
secstart, secend = getsecaddr(datain, secno)
|
||||
zerosecstart, zerosecend = getsecaddr(datain, 0)
|
||||
dif = len(secdata)
|
||||
datalst.append(datain[:unique_id_seed])
|
||||
datalst.append(struct.pack('>L', 2*(nsec+1)+1))
|
||||
datalst.append(datain[unique_id_seed+4:number_of_pdb_records])
|
||||
datalst.append(struct.pack('>H', nsec+1))
|
||||
newstart = zerosecstart + 8
|
||||
for i in range(0, secno):
|
||||
ofs, flgval = struct.unpack_from('>2L', datain, first_pdb_record+i*8)
|
||||
ofs += 8
|
||||
datalst.append(struct.pack('>L', ofs) + struct.pack('>L', flgval))
|
||||
datalst.append(struct.pack('>L', secstart + 8) + struct.pack('>L', (2*secno)))
|
||||
for i in range(secno, nsec):
|
||||
ofs, flgval = struct.unpack_from('>2L', datain, first_pdb_record+i*8)
|
||||
ofs = ofs + dif + 8
|
||||
flgval = 2*(i+1)
|
||||
datalst.append(struct.pack('>L', ofs) + struct.pack('>L', flgval))
|
||||
lpad = newstart - (first_pdb_record + 8*(nsec + 1))
|
||||
if lpad > 0:
|
||||
datalst.append('\0' * lpad)
|
||||
datalst.append(datain[zerosecstart:secstart])
|
||||
datalst.append(secdata)
|
||||
datalst.append(datain[secstart:])
|
||||
dataout = "".join(datalst)
|
||||
return dataout
|
||||
|
||||
|
||||
def insertsectionrange(sectionsource, firstsec, lastsec, sectiontarget, targetsec): # insert a range of sections
|
||||
dataout = sectiontarget
|
||||
for idx in range(lastsec, firstsec-1, -1):
|
||||
dataout = insertsection(dataout, targetsec, readsection(sectionsource, idx))
|
||||
return dataout
|
||||
|
||||
|
||||
def get_exth_params(rec0):
|
||||
ebase = mobi_header_base + getint(rec0, mobi_header_length)
|
||||
elen = getint(rec0, ebase+4)
|
||||
enum = getint(rec0, ebase+8)
|
||||
return ebase, elen, enum
|
||||
|
||||
|
||||
def add_exth(rec0, exth_num, exth_bytes):
|
||||
ebase, elen, enum = get_exth_params(rec0)
|
||||
newrecsize = 8+len(exth_bytes)
|
||||
newrec0 = rec0[0:ebase+4]+struct.pack('>L', elen+newrecsize)+struct.pack('>L', enum+1) +\
|
||||
struct.pack('>L', exth_num) + struct.pack('>L', newrecsize)+exth_bytes+rec0[ebase+12:]
|
||||
newrec0 = writeint(newrec0, title_offset, getint(newrec0, title_offset)+newrecsize)
|
||||
return newrec0
|
||||
|
||||
|
||||
def read_exth(rec0, exth_num):
|
||||
exth_values = []
|
||||
ebase, elen, enum = get_exth_params(rec0)
|
||||
ebase += 12
|
||||
while enum > 0:
|
||||
exth_id = getint(rec0, ebase)
|
||||
if exth_id == exth_num:
|
||||
# We might have multiple exths, so build a list.
|
||||
exth_values.append(rec0[ebase+8:ebase+getint(rec0, ebase+4)])
|
||||
enum -= 1
|
||||
ebase = ebase+getint(rec0, ebase+4)
|
||||
return exth_values
|
||||
|
||||
|
||||
def write_exth(rec0, exth_num, exth_bytes):
|
||||
ebase, elen, enum = get_exth_params(rec0)
|
||||
ebase_idx = ebase+12
|
||||
enum_idx = enum
|
||||
while enum_idx > 0:
|
||||
exth_id = getint(rec0, ebase_idx)
|
||||
if exth_id == exth_num:
|
||||
dif = len(exth_bytes)+8-getint(rec0, ebase_idx+4)
|
||||
newrec0 = rec0
|
||||
if dif != 0:
|
||||
newrec0 = writeint(newrec0, title_offset, getint(newrec0, title_offset)+dif)
|
||||
return newrec0[:ebase+4]+struct.pack('>L', elen+len(exth_bytes)+8-getint(rec0, ebase_idx+4)) +\
|
||||
struct.pack('>L', enum)+rec0[ebase+12:ebase_idx+4] +\
|
||||
struct.pack('>L', len(exth_bytes)+8)+exth_bytes +\
|
||||
rec0[ebase_idx+getint(rec0, ebase_idx+4):]
|
||||
enum_idx -= 1
|
||||
ebase_idx = ebase_idx+getint(rec0, ebase_idx+4)
|
||||
return rec0
|
||||
|
||||
|
||||
def del_exth(rec0, exth_num):
|
||||
ebase, elen, enum = get_exth_params(rec0)
|
||||
ebase_idx = ebase+12
|
||||
enum_idx = 0
|
||||
while enum_idx < enum:
|
||||
exth_id = getint(rec0, ebase_idx)
|
||||
exth_size = getint(rec0, ebase_idx+4)
|
||||
if exth_id == exth_num:
|
||||
newrec0 = rec0
|
||||
newrec0 = writeint(newrec0, title_offset, getint(newrec0, title_offset)-exth_size)
|
||||
newrec0 = newrec0[:ebase_idx]+newrec0[ebase_idx+exth_size:]
|
||||
newrec0 = newrec0[0:ebase+4]+struct.pack('>L', elen-exth_size)+struct.pack('>L', enum-1)+newrec0[ebase+12:]
|
||||
return newrec0
|
||||
enum_idx += 1
|
||||
ebase_idx = ebase_idx+exth_size
|
||||
return rec0
|
||||
|
||||
|
||||
class mobi_split:
|
||||
def __init__(self, infile, newKindle):
|
||||
try:
|
||||
datain = open(infile, 'rb').read()
|
||||
datain_rec0 = readsection(datain, 0)
|
||||
ver = getint(datain_rec0, mobi_version)
|
||||
# fake_asin = str(uuid4())
|
||||
self.combo = (ver != 8)
|
||||
if not self.combo:
|
||||
return
|
||||
exth121 = read_exth(datain_rec0, 121)
|
||||
if len(exth121) == 0:
|
||||
self.combo = False
|
||||
return
|
||||
else:
|
||||
# only pay attention to first exth121
|
||||
# (there should only be one)
|
||||
datain_kf8, = struct.unpack_from('>L', exth121[0], 0)
|
||||
if datain_kf8 == 0xffffffff:
|
||||
self.combo = False
|
||||
return
|
||||
datain_kfrec0 = readsection(datain, datain_kf8)
|
||||
firstimage = getint(datain_rec0, first_image_record)
|
||||
lastimage = getint(datain_rec0, last_content_index, 'H')
|
||||
|
||||
if not newKindle:
|
||||
# create the standalone mobi7
|
||||
num_sec = getint(datain, number_of_pdb_records, 'H')
|
||||
# remove BOUNDARY up to but not including ELF record
|
||||
self.result_file = deletesectionrange(datain, datain_kf8-1, num_sec-2)
|
||||
# check if there are SRCS records and delete them
|
||||
srcs = getint(datain_rec0, srcs_index)
|
||||
num_srcs = getint(datain_rec0, srcs_count)
|
||||
if srcs != 0xffffffff and num_srcs > 0:
|
||||
self.result_file = deletesectionrange(self.result_file, srcs, srcs+num_srcs-1)
|
||||
datain_rec0 = writeint(datain_rec0, srcs_index, 0xffffffff)
|
||||
datain_rec0 = writeint(datain_rec0, srcs_count, 0)
|
||||
# reset the EXTH 121 KF8 Boundary meta data to 0xffffffff
|
||||
datain_rec0 = write_exth(datain_rec0, 121, struct.pack('>L', 0xffffffff))
|
||||
# datain_rec0 = del_exth(datain_rec0,121)
|
||||
# datain_rec0 = del_exth(datain_rec0,534)
|
||||
# don't remove the EXTH 125 KF8 Count of Resources, seems to be present in mobi6 files as well
|
||||
# set the EXTH 129 KF8 Masthead / Cover Image string to the null string
|
||||
datain_rec0 = write_exth(datain_rec0, 129, '')
|
||||
# don't remove the EXTH 131 KF8 Unidentified Count, seems to be present in mobi6 files as well
|
||||
|
||||
# Make sure we have an ASIN & cdeType set...
|
||||
# if len(read_exth(datain_rec0, 113)) == 0:
|
||||
# datain_rec0 = add_exth(datain_rec0, 113, fake_asin)
|
||||
# if len(read_exth(datain_rec0, 504)) == 0:
|
||||
# datain_rec0 = add_exth(datain_rec0, 504, fake_asin)
|
||||
if len(read_exth(datain_rec0, 501)) == 0:
|
||||
datain_rec0 = add_exth(datain_rec0, 501, b'EBOK')
|
||||
|
||||
# need to reset flags stored in 0x80-0x83
|
||||
# old mobi with exth: 0x50, mobi7 part with exth: 0x1850, mobi8 part with exth: 0x1050
|
||||
# Bit Flags
|
||||
# 0x1000 = Bit 12 indicates if embedded fonts are used or not
|
||||
# 0x0800 = means this Header points to *shared* images/resource/fonts ??
|
||||
# 0x0080 = unknown new flag, why is this now being set by Kindlegen 2.8?
|
||||
# 0x0040 = exth exists
|
||||
# 0x0010 = Not sure but this is always set so far
|
||||
fval, = struct.unpack_from('>L', datain_rec0, 0x80)
|
||||
# need to remove flag 0x0800 for KindlePreviewer 2.8 and unset Bit 12 for embedded fonts
|
||||
fval &= 0x07FF
|
||||
datain_rec0 = datain_rec0[:0x80] + struct.pack('>L', fval) + datain_rec0[0x84:]
|
||||
self.result_file = writesection(self.result_file, 0, datain_rec0)
|
||||
if lastimage == 0xffff:
|
||||
# find the lowest of the next sections and copy up to that.
|
||||
ofs_list = [(kf8_last_content_index, 'L'), (fcis_index, 'L'), (flis_index, 'L'), (datp_index, 'L'),
|
||||
(hufftbloff, 'L')]
|
||||
for ofs, sz in ofs_list:
|
||||
n = getint(datain_kfrec0, ofs, sz)
|
||||
if 0 < n < lastimage:
|
||||
lastimage = n-1
|
||||
|
||||
# Try to null out FONT and RES, but leave the (empty) PDB record so image refs remain valid
|
||||
for i in range(firstimage, lastimage):
|
||||
imgsec = readsection(self.result_file, i)
|
||||
if imgsec[0:4] in ['RESC', 'FONT']:
|
||||
self.result_file = nullsection(self.result_file, i)
|
||||
# mobi7 finished
|
||||
else:
|
||||
# create standalone mobi8
|
||||
self.result_file = deletesectionrange(datain, 0, datain_kf8-1)
|
||||
target = getint(datain_kfrec0, first_image_record)
|
||||
self.result_file = insertsectionrange(datain, firstimage, lastimage, self.result_file, target)
|
||||
datain_kfrec0 = readsection(self.result_file, 0)
|
||||
|
||||
# Only keep the correct EXTH 116 StartOffset, KG 2.5 carries over the one from the mobi7 part,
|
||||
# which then points at garbage in the mobi8 part, and confuses FW 3.4
|
||||
kf8starts = read_exth(datain_kfrec0, 116)
|
||||
# If we have multiple StartOffset, keep only the last one
|
||||
kf8start_count = len(kf8starts)
|
||||
while kf8start_count > 1:
|
||||
kf8start_count -= 1
|
||||
datain_kfrec0 = del_exth(datain_kfrec0, 116)
|
||||
|
||||
# update the EXTH 125 KF8 Count of Images/Fonts/Resources
|
||||
datain_kfrec0 = write_exth(datain_kfrec0, 125, struct.pack('>L', lastimage-firstimage+1))
|
||||
|
||||
# Same dance for the KF8, we want an ASIN & cdeType :)
|
||||
# if len(read_exth(datain_kfrec0, 113)) == 0:
|
||||
# datain_kfrec0 = add_exth(datain_kfrec0, 113, fake_asin)
|
||||
# if len(read_exth(datain_kfrec0, 504)) == 0:
|
||||
# datain_kfrec0 = add_exth(datain_kfrec0, 504, fake_asin)
|
||||
if len(read_exth(datain_kfrec0, 501)) == 0:
|
||||
datain_kfrec0 = add_exth(datain_kfrec0, 501, b'EBOK')
|
||||
|
||||
# need to reset flags stored in 0x80-0x83
|
||||
# old mobi with exth: 0x50, mobi7 part with exth: 0x1850, mobi8 part with exth: 0x1050
|
||||
# standalone mobi8 with exth: 0x0050
|
||||
# Bit Flags
|
||||
# 0x1000 = Bit 12 indicates if embedded fonts are used or not
|
||||
# 0x0800 = means this Header points to *shared* images/resource/fonts ??
|
||||
# 0x0080 = unknown new flag, why is this now being set by Kindlegen 2.8?
|
||||
# 0x0040 = exth exists
|
||||
# 0x0010 = Not sure but this is always set so far
|
||||
fval, = struct.unpack_from('>L', datain_kfrec0, 0x80)
|
||||
fval &= 0x1FFF
|
||||
fval |= 0x0800
|
||||
datain_kfrec0 = datain_kfrec0[:0x80] + struct.pack('>L', fval) + datain_kfrec0[0x84:]
|
||||
|
||||
# properly update other index pointers that have been shifted by the insertion of images
|
||||
ofs_list = [(kf8_last_content_index, 'L'), (fcis_index, 'L'), (flis_index, 'L'), (datp_index, 'L'),
|
||||
(hufftbloff, 'L')]
|
||||
for ofs, sz in ofs_list:
|
||||
n = getint(datain_kfrec0, ofs, sz)
|
||||
if n != 0xffffffff:
|
||||
datain_kfrec0 = writeint(datain_kfrec0, ofs, n+lastimage-firstimage+1, sz)
|
||||
self.result_file = writesection(self.result_file, 0, datain_kfrec0)
|
||||
# mobi8 finished
|
||||
except Exception:
|
||||
raise
|
||||
|
||||
def getResult(self):
|
||||
return self.result_file
|
||||
@@ -1,236 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
|
||||
#
|
||||
# This is a python script. You need a Python interpreter to run it.
|
||||
# For example, ActiveState Python, which exists for windows.
|
||||
#
|
||||
# This script strips the penultimate record from a Mobipocket file.
|
||||
# This is useful because the current KindleGen add a compressed copy
|
||||
# of the source files used in this record, making the ebook produced
|
||||
# about twice as big as it needs to be.
|
||||
#
|
||||
#
|
||||
# This is free and unencumbered software released into the public domain.
|
||||
#
|
||||
# Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
# distribute this software, either in source code form or as a compiled
|
||||
# binary, for any purpose, commercial or non-commercial, and by any
|
||||
# means.
|
||||
#
|
||||
# In jurisdictions that recognize copyright laws, the author or authors
|
||||
# of this software dedicate any and all copyright interest in the
|
||||
# software to the public domain. We make this dedication for the benefit
|
||||
# of the public at large and to the detriment of our heirs and
|
||||
# successors. We intend this dedication to be an overt act of
|
||||
# relinquishment in perpetuity of all present and future rights to this
|
||||
# software under copyright law.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
# OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# For more information, please refer to <http://unlicense.org/>
|
||||
#
|
||||
# Written by Paul Durrant, 2010-2011, paul@durrant.co.uk, pdurrant on mobileread.com
|
||||
# With enhancements by Kevin Hendricks, KevinH on mobileread.com
|
||||
#
|
||||
# Changelog
|
||||
# 1.00 - Initial version
|
||||
# 1.10 - Added an option to output the stripped data
|
||||
# 1.20 - Added check for source files section (thanks Piquan)
|
||||
# 1.30 - Added prelim Support for K8 style mobis
|
||||
# 1.31 - removed the SRCS section but kept a 0 size entry for it
|
||||
# 1.32 - removes the SRCS section and its entry, now updates metadata 121 if needed
|
||||
# 1.33 - now uses and modifies mobiheader SRCS and CNT
|
||||
# 1.34 - added credit for Kevin Hendricks
|
||||
# 1.35 - fixed bug when more than one compilation (SRCS/CMET) records
|
||||
|
||||
__version__ = '1.35'
|
||||
|
||||
import sys
|
||||
import struct
|
||||
import binascii
|
||||
|
||||
class Unbuffered:
|
||||
def __init__(self, stream):
|
||||
self.stream = stream
|
||||
def write(self, data):
|
||||
self.stream.write(data)
|
||||
self.stream.flush()
|
||||
def __getattr__(self, attr):
|
||||
return getattr(self.stream, attr)
|
||||
|
||||
|
||||
class StripException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class SectionStripper:
|
||||
def loadSection(self, section):
|
||||
if (section + 1 == self.num_sections):
|
||||
endoff = len(self.data_file)
|
||||
else:
|
||||
endoff = self.sections[section + 1][0]
|
||||
off = self.sections[section][0]
|
||||
return self.data_file[off:endoff]
|
||||
|
||||
def patch(self, off, new):
|
||||
self.data_file = self.data_file[:off] + new + self.data_file[off+len(new):]
|
||||
|
||||
def strip(self, off, len):
|
||||
self.data_file = self.data_file[:off] + self.data_file[off+len:]
|
||||
|
||||
def patchSection(self, section, new, in_off = 0):
|
||||
if (section + 1 == self.num_sections):
|
||||
endoff = len(self.data_file)
|
||||
else:
|
||||
endoff = self.sections[section + 1][0]
|
||||
off = self.sections[section][0]
|
||||
assert off + in_off + len(new) <= endoff
|
||||
self.patch(off + in_off, new)
|
||||
|
||||
def updateEXTH121(self, srcs_secnum, srcs_cnt, mobiheader):
|
||||
mobi_length, = struct.unpack('>L',mobiheader[0x14:0x18])
|
||||
exth_flag, = struct.unpack('>L', mobiheader[0x80:0x84])
|
||||
exth = 'NONE'
|
||||
try:
|
||||
if exth_flag & 0x40:
|
||||
exth = mobiheader[16 + mobi_length:]
|
||||
if (len(exth) >= 4) and (exth[:4] == 'EXTH'):
|
||||
nitems, = struct.unpack('>I', exth[8:12])
|
||||
pos = 12
|
||||
for i in xrange(nitems):
|
||||
type, size = struct.unpack('>II', exth[pos: pos + 8])
|
||||
# print type, size
|
||||
if type == 121:
|
||||
boundaryptr, =struct.unpack('>L',exth[pos+8: pos + size])
|
||||
if srcs_secnum <= boundaryptr:
|
||||
boundaryptr -= srcs_cnt
|
||||
prefix = mobiheader[0:16 + mobi_length + pos + 8]
|
||||
suffix = mobiheader[16 + mobi_length + pos + 8 + 4:]
|
||||
nval = struct.pack('>L',boundaryptr)
|
||||
mobiheader = prefix + nval + suffix
|
||||
pos += size
|
||||
except:
|
||||
pass
|
||||
return mobiheader
|
||||
|
||||
def __init__(self, datain):
|
||||
if datain[0x3C:0x3C+8] != 'BOOKMOBI':
|
||||
raise StripException("invalid file format")
|
||||
self.num_sections, = struct.unpack('>H', datain[76:78])
|
||||
|
||||
# get mobiheader and check SRCS section number and count
|
||||
offset0, = struct.unpack_from('>L', datain, 78)
|
||||
offset1, = struct.unpack_from('>L', datain, 86)
|
||||
mobiheader = datain[offset0:offset1]
|
||||
srcs_secnum, srcs_cnt = struct.unpack_from('>2L', mobiheader, 0xe0)
|
||||
if srcs_secnum == 0xffffffff or srcs_cnt == 0:
|
||||
raise StripException("File doesn't contain the sources section.")
|
||||
|
||||
print "Found SRCS section number %d, and count %d" % (srcs_secnum, srcs_cnt)
|
||||
# find its offset and length
|
||||
next = srcs_secnum + srcs_cnt
|
||||
srcs_offset, flgval = struct.unpack_from('>2L', datain, 78+(srcs_secnum*8))
|
||||
next_offset, flgval = struct.unpack_from('>2L', datain, 78+(next*8))
|
||||
srcs_length = next_offset - srcs_offset
|
||||
if datain[srcs_offset:srcs_offset+4] != 'SRCS':
|
||||
raise StripException("SRCS section num does not point to SRCS.")
|
||||
print " beginning at offset %0x and ending at offset %0x" % (srcs_offset, srcs_length)
|
||||
|
||||
# it appears bytes 68-71 always contain (2*num_sections) + 1
|
||||
# this is not documented anyplace at all but it appears to be some sort of next
|
||||
# available unique_id used to identify specific sections in the palm db
|
||||
self.data_file = datain[:68] + struct.pack('>L',((self.num_sections-srcs_cnt)*2+1))
|
||||
self.data_file += datain[72:76]
|
||||
|
||||
# write out the number of sections reduced by srtcs_cnt
|
||||
self.data_file = self.data_file + struct.pack('>H',self.num_sections-srcs_cnt)
|
||||
|
||||
# we are going to remove srcs_cnt SRCS sections so the offset of every entry in the table
|
||||
# up to the srcs secnum must begin 8 bytes earlier per section removed (each table entry is 8 )
|
||||
delta = -8 * srcs_cnt
|
||||
for i in xrange(srcs_secnum):
|
||||
offset, flgval = struct.unpack_from('>2L', datain, 78+(i*8))
|
||||
offset += delta
|
||||
self.data_file += struct.pack('>L',offset) + struct.pack('>L',flgval)
|
||||
|
||||
# for every record after the srcs_cnt SRCS records we must start it
|
||||
# earlier by 8*srcs_cnt + the length of the srcs sections themselves)
|
||||
delta = delta - srcs_length
|
||||
for i in xrange(srcs_secnum+srcs_cnt,self.num_sections):
|
||||
offset, flgval = struct.unpack_from('>2L', datain, 78+(i*8))
|
||||
offset += delta
|
||||
flgval = 2 * (i - srcs_cnt)
|
||||
self.data_file += struct.pack('>L',offset) + struct.pack('>L',flgval)
|
||||
|
||||
# now pad it out to begin right at the first offset
|
||||
# typically this is 2 bytes of nulls
|
||||
first_offset, flgval = struct.unpack_from('>2L', self.data_file, 78)
|
||||
self.data_file += '\0' * (first_offset - len(self.data_file))
|
||||
|
||||
# now finally add on every thing up to the original src_offset
|
||||
self.data_file += datain[offset0: srcs_offset]
|
||||
|
||||
# and everything afterwards
|
||||
self.data_file += datain[srcs_offset+srcs_length:]
|
||||
|
||||
#store away the SRCS section in case the user wants it output
|
||||
self.stripped_data_header = datain[srcs_offset:srcs_offset+16]
|
||||
self.stripped_data = datain[srcs_offset+16:srcs_offset+srcs_length]
|
||||
|
||||
# update the number of sections count
|
||||
self.num_section = self.num_sections - srcs_cnt
|
||||
|
||||
# update the srcs_secnum and srcs_cnt in the mobiheader
|
||||
offset0, flgval0 = struct.unpack_from('>2L', self.data_file, 78)
|
||||
offset1, flgval1 = struct.unpack_from('>2L', self.data_file, 86)
|
||||
mobiheader = self.data_file[offset0:offset1]
|
||||
mobiheader = mobiheader[:0xe0]+ struct.pack('>L', 0xffffffff) + struct.pack('>L', 0) + mobiheader[0xe8:]
|
||||
|
||||
# if K8 mobi, handle metadata 121 in old mobiheader
|
||||
mobiheader = self.updateEXTH121(srcs_secnum, srcs_cnt, mobiheader)
|
||||
self.data_file = self.data_file[0:offset0] + mobiheader + self.data_file[offset1:]
|
||||
print "done"
|
||||
|
||||
def getResult(self):
|
||||
return self.data_file
|
||||
|
||||
def getStrippedData(self):
|
||||
return self.stripped_data
|
||||
|
||||
def getHeader(self):
|
||||
return self.stripped_data_header
|
||||
|
||||
def main(argv=None):
|
||||
infile = argv[0]
|
||||
outfile = argv[1]
|
||||
data_file = file(infile, 'rb').read()
|
||||
try:
|
||||
strippedFile = SectionStripper(data_file)
|
||||
file(outfile, 'wb').write(strippedFile.getResult())
|
||||
print "Header Bytes: " + binascii.b2a_hex(strippedFile.getHeader())
|
||||
if len(argv)==3:
|
||||
file(argv[2], 'wb').write(strippedFile.getStrippedData())
|
||||
except StripException, e:
|
||||
print "Error: %s" % e
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.stdout=Unbuffered(sys.stdout)
|
||||
print ('KindleStrip v%(__version__)s. '
|
||||
'Written 2010-2012 by Paul Durrant and Kevin Hendricks.' % globals())
|
||||
if len(sys.argv)<3 or len(sys.argv)>4:
|
||||
print "Strips the Sources record from Mobipocket ebooks"
|
||||
print "For ebooks generated using KindleGen 1.1 and later that add the source"
|
||||
print "Usage:"
|
||||
print " %s <infile> <outfile> <strippeddatafile>" % sys.argv[0]
|
||||
print "<strippeddatafile> is optional."
|
||||
sys.exit(1)
|
||||
else:
|
||||
main(sys.argv[1:])
|
||||
sys.exit(0)
|
||||
@@ -1,4 +1,5 @@
|
||||
# Copyright (c) 2012 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||
# Copyright (c) 2012-2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||
# Copyright (c) 2013 Pawel Jastrzebski <pawelj@vulturis.eu>
|
||||
#
|
||||
# Based upon the code snippet by Ned Batchelder
|
||||
# (http://nedbatchelder.com/blog/200712/extracting_jpgs_from_pdfs.html)
|
||||
|
||||
@@ -1850,6 +1850,8 @@ def check_returncode(p, out):
|
||||
code = p.returncode
|
||||
if code == 0:
|
||||
return
|
||||
if code == 9:
|
||||
return
|
||||
|
||||
# map return code to exception class
|
||||
errmap = [None,
|
||||
|
||||
91
other/Additional-LICENSE.txt
Normal file
91
other/Additional-LICENSE.txt
Normal file
@@ -0,0 +1,91 @@
|
||||
****** ***** ****** UnRAR - free utility for RAR archives
|
||||
** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
****** ******* ****** License for use and distribution of
|
||||
** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
** ** ** ** ** ** FREEWARE version
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
The UnRAR utility is freeware. This means:
|
||||
|
||||
1. All copyrights to RAR and the utility UnRAR are exclusively
|
||||
owned by the author - Alexander Roshal.
|
||||
|
||||
2. The UnRAR utility may be freely distributed. It is allowed
|
||||
to distribute UnRAR inside of other software packages.
|
||||
|
||||
3. THE RAR ARCHIVER AND THE UnRAR UTILITY ARE DISTRIBUTED "AS IS".
|
||||
NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED. YOU USE AT
|
||||
YOUR OWN RISK. THE AUTHOR WILL NOT BE LIABLE FOR DATA LOSS,
|
||||
DAMAGES, LOSS OF PROFITS OR ANY OTHER KIND OF LOSS WHILE USING
|
||||
OR MISUSING THIS SOFTWARE.
|
||||
|
||||
4. Neither RAR binary code, WinRAR binary code, UnRAR source or UnRAR
|
||||
binary code may be used or reverse engineered to re-create the RAR
|
||||
compression algorithm, which is proprietary, without written
|
||||
permission of the author.
|
||||
|
||||
5. If you don't agree with terms of the license you must remove
|
||||
UnRAR files from your storage devices and cease to use the
|
||||
utility.
|
||||
|
||||
Thank you for your interest in RAR and UnRAR.
|
||||
|
||||
|
||||
Alexander L. Roshal
|
||||
|
||||
7-Zip
|
||||
~~~~~
|
||||
License for use and distribution
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
7-Zip Copyright (C) 1999-2012 Igor Pavlov.
|
||||
|
||||
Licenses for files are:
|
||||
|
||||
1) 7z.dll: GNU LGPL + unRAR restriction
|
||||
2) All other files: GNU LGPL
|
||||
|
||||
The GNU LGPL + unRAR restriction means that you must follow both
|
||||
GNU LGPL rules and unRAR restriction rules.
|
||||
|
||||
|
||||
Note:
|
||||
You can use 7-Zip on any computer, including a computer in a commercial
|
||||
organization. You don't need to register or pay for 7-Zip.
|
||||
|
||||
|
||||
GNU LGPL information
|
||||
--------------------
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You can receive a copy of the GNU Lesser General Public License from
|
||||
http://www.gnu.org/
|
||||
|
||||
|
||||
unRAR restriction
|
||||
-----------------
|
||||
|
||||
The decompression engine for RAR archives was developed using source
|
||||
code of unRAR program.
|
||||
All copyrights to original unRAR code are owned by Alexander Roshal.
|
||||
|
||||
The license for original unRAR code has the following restriction:
|
||||
|
||||
The unRAR sources cannot be used to re-create the RAR compression algorithm,
|
||||
which is proprietary. Distribution of modified unRAR sources in separate form
|
||||
or as a part of other software is permitted, provided that it is clearly
|
||||
stated in the documentation and source comments that the code may
|
||||
not be used to develop a RAR (WinRAR) compatible archiver.
|
||||
|
||||
|
||||
--
|
||||
Igor Pavlov
|
||||
35
other/QT-4.8.5-QListWidget.patch
Normal file
35
other/QT-4.8.5-QListWidget.patch
Normal file
@@ -0,0 +1,35 @@
|
||||
--- qt-4.8.5/src/gui/kernel/qwidget_mac.mm 2013-06-07 07:16:59.000000000 +0200
|
||||
+++ qt-4.8.5-fix/src/gui/kernel/qwidget_mac.mm 2013-10-11 23:00:15.000000000 +0200
|
||||
@@ -4715,15 +4715,13 @@ void QWidgetPrivate::scroll_sys(int dx,
|
||||
}
|
||||
|
||||
// Scroll the whole widget if qscrollRect is not valid:
|
||||
- QRect validScrollRect = qscrollRect.isValid() ? qscrollRect : q->rect();
|
||||
- validScrollRect &= clipRect();
|
||||
+ QRect validScrollRect = qscrollRect.isValid() ? qscrollRect : QRect(0, 0, q->width(), q->height());
|
||||
|
||||
// If q is overlapped by other widgets, we cannot just blit pixels since
|
||||
// this will move overlapping widgets as well. In case we just update:
|
||||
const bool overlapped = isOverlapped(validScrollRect.translated(data.crect.topLeft()));
|
||||
const bool accelerateScroll = accelEnv && isOpaque && !overlapped;
|
||||
const bool isAlien = (q->internalWinId() == 0);
|
||||
- const QPoint scrollDelta(dx, dy);
|
||||
|
||||
// If qscrollRect is valid, we are _not_ supposed to scroll q's children (as documented).
|
||||
// But we do scroll children (and the whole of q) if qscrollRect is invalid. This case is
|
||||
@@ -4745,7 +4743,6 @@ void QWidgetPrivate::scroll_sys(int dx,
|
||||
}else {
|
||||
update_sys(qscrollRect);
|
||||
}
|
||||
- return;
|
||||
}
|
||||
|
||||
#ifdef QT_MAC_USE_COCOA
|
||||
@@ -4762,6 +4759,7 @@ void QWidgetPrivate::scroll_sys(int dx,
|
||||
// moved when the parent is scrolled. All directly or indirectly moved
|
||||
// children will receive a move event before the function call returns.
|
||||
QWidgetList movedChildren;
|
||||
+ const QPoint scrollDelta(dx, dy);
|
||||
if (scrollChildren) {
|
||||
QObjectList children = q->children();
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
[Paths]
|
||||
Plugins = DumbHackThatFixPY2APP
|
||||
26
setup.py
26
setup.py
@@ -10,7 +10,7 @@ Usage (Windows):
|
||||
from sys import platform
|
||||
|
||||
NAME = "KindleComicConverter"
|
||||
VERSION = "3.2"
|
||||
VERSION = "3.4"
|
||||
MAIN = "kcc.py"
|
||||
|
||||
if platform == "darwin":
|
||||
@@ -22,8 +22,11 @@ if platform == "darwin":
|
||||
py2app=dict(
|
||||
argv_emulation=True,
|
||||
iconfile='icons/comic2ebook.icns',
|
||||
includes=['PIL', 'sip', 'PyQt4', 'PyQt4.QtCore', 'PyQt4.QtGui'],
|
||||
resources=['other/qt.conf', 'LICENSE.txt'],
|
||||
includes=['PIL', 'sip', 'PyQt4', 'PyQt4.QtCore', 'PyQt4.QtGui', 'PyQt4.QtNetwork'],
|
||||
excludes=['PyQt4.QtDeclarative', 'PyQt4.QtDesigner', 'PyQt4.QtHelp', 'PyQt4.QtMultimedia',
|
||||
'PyQt4.QtOpenGL', 'PyQt4.QtScript', 'PyQt4.QtScriptTools', 'PyQt4.QtSql', 'PyQt4.QtSvg',
|
||||
'PyQt4.QtXmlPatterns', 'PyQt4.QtXml', 'PyQt4.QtWebKit', 'PyQt4.QtTest'],
|
||||
resources=['LICENSE.txt', 'other/Additional-LICENSE.txt'],
|
||||
plist=dict(
|
||||
CFBundleName=NAME,
|
||||
CFBundleShortVersionString=VERSION,
|
||||
@@ -32,6 +35,13 @@ if platform == "darwin":
|
||||
CFBundleExecutable=NAME,
|
||||
CFBundleIdentifier='com.github.ciromattia.kcc',
|
||||
CFBundleSignature='dplt',
|
||||
CFBundleDocumentTypes=[
|
||||
dict(
|
||||
CFBundleTypeExtensions=['cbz', 'cbr', 'cb7', 'zip', 'rar', '7z', 'pdf'],
|
||||
CFBundleTypeIconFile='comic2ebook.icns',
|
||||
CFBundleTypeRole='Viewer',
|
||||
)
|
||||
],
|
||||
NSHumanReadableCopyright='ISC License (ISCL)'
|
||||
)
|
||||
)
|
||||
@@ -41,7 +51,11 @@ elif platform == "win32":
|
||||
from cx_Freeze import setup, Executable
|
||||
base = "Win32GUI"
|
||||
extra_options = dict(
|
||||
options={"build_exe": {"include_files": ['LICENSE.txt'], "compressed": True}},
|
||||
options={"build_exe": {"include_files": ['LICENSE.txt',
|
||||
['other/UnRAR.exe', 'UnRAR.exe'],
|
||||
['other/7za.exe', '7za.exe'],
|
||||
['other/Additional-LICENSE.txt', 'Additional-LICENSE.txt']
|
||||
], "compressed": True}},
|
||||
executables=[Executable(MAIN,
|
||||
base=base,
|
||||
targetName="KCC.exe",
|
||||
@@ -53,7 +67,9 @@ elif platform == "win32":
|
||||
else:
|
||||
from cx_Freeze import setup, Executable
|
||||
extra_options = dict(
|
||||
options={"build_exe": {"include_files": ['LICENSE.txt'], "compressed": True}},
|
||||
options={"build_exe": {"include_files": ['LICENSE.txt',
|
||||
['other/Additional-LICENSE.txt', 'Additional-LICENSE.txt']
|
||||
], "compressed": True}},
|
||||
executables=[Executable(MAIN,
|
||||
icon="icons/comic2ebook.png",
|
||||
copyDependentFiles=True,
|
||||
|
||||
Reference in New Issue
Block a user