1
0
mirror of https://github.com/ciromattia/kcc synced 2025-12-16 03:06:33 +00:00

Version 4.0 - first draft for Python3 conversion

This commit is contained in:
Ciro Mattia Gonano
2013-11-14 15:49:46 +01:00
parent ddd223c2ec
commit d33c53b691
19 changed files with 210 additions and 191 deletions

View File

@@ -1,5 +1,5 @@
#define MyAppName "Kindle Comic Converter" #define MyAppName "Kindle Comic Converter"
#define MyAppVersion "3.6" #define MyAppVersion "4.0"
#define MyAppPublisher "Ciro Mattia Gonano, Paweł Jastrzębski" #define MyAppPublisher "Ciro Mattia Gonano, Paweł Jastrzębski"
#define MyAppURL "http://kcc.vulturis.eu/" #define MyAppURL "http://kcc.vulturis.eu/"
#define MyAppExeName "KCC.exe" #define MyAppExeName "KCC.exe"

12
kcc.py
View File

@@ -18,7 +18,7 @@
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE. # PERFORMANCE OF THIS SOFTWARE.
__version__ = '3.6' __version__ = '4.0'
__license__ = 'ISC' __license__ = 'ISC'
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>' __copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
@@ -29,13 +29,13 @@ try:
#noinspection PyUnresolvedReferences #noinspection PyUnresolvedReferences
from PyQt4 import QtCore, QtGui, QtNetwork from PyQt4 import QtCore, QtGui, QtNetwork
except ImportError: except ImportError:
print "ERROR: PyQT4 is not installed!" print("ERROR: PyQT4 is not installed!")
if sys.platform.startswith('linux'): if sys.platform.startswith('linux'):
import Tkinter import tkinter
import tkMessageBox import tkinter.messagebox
importRoot = Tkinter.Tk() importRoot = tkinter.Tk()
importRoot.withdraw() importRoot.withdraw()
tkMessageBox.showerror("KCC - Error", "PyQT4 is not installed!") tkinter.messagebox.showerror("KCC - Error", "PyQT4 is not installed!")
exit(1) exit(1)
from kcc import KCC_gui from kcc import KCC_gui
from multiprocessing import freeze_support from multiprocessing import freeze_support

View File

@@ -17,7 +17,7 @@
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE. # PERFORMANCE OF THIS SOFTWARE.
__version__ = '3.6' __version__ = '4.0'
__license__ = 'ISC' __license__ = 'ISC'
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>' __copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
@@ -25,39 +25,38 @@ __docformat__ = 'restructuredtext en'
import os import os
import sys import sys
import traceback import traceback
import urllib2 import urllib.request, urllib.error, urllib.parse
import socket import socket
import comic2ebook from . import comic2ebook
import kindlesplit from . import kindlesplit
from string import split
from time import sleep from time import sleep
from shutil import move from shutil import move
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer from http.server import BaseHTTPRequestHandler, HTTPServer
from SocketServer import ThreadingMixIn from socketserver import ThreadingMixIn
from image import ProfileData from .image import ProfileData
from subprocess import STDOUT, PIPE from subprocess import STDOUT, PIPE
from PyQt4 import QtGui, QtCore from PyQt4 import QtGui, QtCore
from xml.dom.minidom import parse from xml.dom.minidom import parse
from HTMLParser import HTMLParser from html.parser import HTMLParser
from KCC_rc_web import WebContent from .KCC_rc_web import WebContent
try: try:
#noinspection PyUnresolvedReferences #noinspection PyUnresolvedReferences
from psutil import TOTAL_PHYMEM, Popen from psutil import TOTAL_PHYMEM, Popen
except ImportError: except ImportError:
print "ERROR: Psutil is not installed!" print("ERROR: Psutil is not installed!")
if sys.platform.startswith('linux'): if sys.platform.startswith('linux'):
import Tkinter import tkinter
import tkMessageBox import tkinter.messagebox
importRoot = Tkinter.Tk() importRoot = tkinter.Tk()
importRoot.withdraw() importRoot.withdraw()
tkMessageBox.showerror("KCC - Error", "Psutil is not installed!") tkinter.messagebox.showerror("KCC - Error", "Psutil is not installed!")
exit(1) exit(1)
if sys.platform.startswith('darwin'): if sys.platform.startswith('darwin'):
import KCC_ui_osx as KCC_ui from . import KCC_ui_osx as KCC_ui
elif sys.platform.startswith('linux'): elif sys.platform.startswith('linux'):
import KCC_ui_linux as KCC_ui from . import KCC_ui_linux as KCC_ui
else: else:
import KCC_ui from . import KCC_ui
class Icons: class Icons:
@@ -130,8 +129,8 @@ class WebServerHandler(BaseHTTPRequestHandler):
'<p style="font-size:50px">- <img style="vertical-align: middle" ' '<p style="font-size:50px">- <img style="vertical-align: middle" '
'alt="KCC Logo" src="' + GUI.webContent.logo + '" /> -</p>\n') 'alt="KCC Logo" src="' + GUI.webContent.logo + '" /> -</p>\n')
if len(GUI.completedWork) > 0 and not GUI.conversionAlive: if len(GUI.completedWork) > 0 and not GUI.conversionAlive:
for key in sorted(GUI.completedWork.iterkeys()): for key in sorted(GUI.completedWork.keys()):
self.wfile.write('<p><a href="' + key + '">' + split(key, '.')[0] + '</a></p>\n') self.wfile.write('<p><a href="' + key + '">' + key.split('.')[0] + '</a></p>\n')
else: else:
self.wfile.write('<p style="font-weight: bold">No downloads are available.<br/>' self.wfile.write('<p style="font-weight: bold">No downloads are available.<br/>'
'Convert some files and refresh this page.</p>\n') 'Convert some files and refresh this page.</p>\n')
@@ -139,7 +138,7 @@ class WebServerHandler(BaseHTTPRequestHandler):
'</body>\n' '</body>\n'
'</html>\n') '</html>\n')
elif sendReply: elif sendReply:
outputFile = GUI.completedWork[urllib2.unquote(self.path[1:])].decode('utf-8') outputFile = GUI.completedWork[urllib.parse.unquote(self.path[1:])].decode('utf-8')
fp = open(outputFile, 'rb') fp = open(outputFile, 'rb')
self.send_response(200) self.send_response(200)
self.send_header('Content-type', mimetype) self.send_header('Content-type', mimetype)
@@ -173,7 +172,7 @@ class WebServerThread(QtCore.QThread):
try: try:
# Sweet cross-platform one-liner to get LAN ip address # Sweet cross-platform one-liner to get LAN ip address
lIP = [ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1][0] lIP = [ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1][0]
except StandardError: except Exception:
# Sadly it can fail on some Linux configurations # Sadly it can fail on some Linux configurations
lIP = None lIP = None
try: try:
@@ -186,7 +185,7 @@ class WebServerThread(QtCore.QThread):
self.emit(QtCore.SIGNAL("addMessage"), '<b>Content server</b> started on port 4242.', 'info') self.emit(QtCore.SIGNAL("addMessage"), '<b>Content server</b> started on port 4242.', 'info')
while self.running: while self.running:
self.server.handle_request() self.server.handle_request()
except StandardError: except Exception:
self.emit(QtCore.SIGNAL("addMessage"), '<b>Content server</b> failed to start!', 'error') self.emit(QtCore.SIGNAL("addMessage"), '<b>Content server</b> failed to start!', 'error')
def stop(self): def stop(self):
@@ -202,9 +201,9 @@ class VersionThread(QtCore.QThread):
def run(self): def run(self):
try: try:
XML = urllib2.urlopen('http://kcc.vulturis.eu/Version.php') XML = urllib.request.urlopen('http://kcc.vulturis.eu/Version.php')
XML = parse(XML) XML = parse(XML)
except StandardError: except Exception:
return return
latestVersion = XML.childNodes[0].getElementsByTagName('latest')[0].childNodes[0].toxml() latestVersion = XML.childNodes[0].getElementsByTagName('latest')[0].childNodes[0].toxml()
if tuple(map(int, (latestVersion.split(".")))) > tuple(map(int, (__version__.split(".")))): if tuple(map(int, (latestVersion.split(".")))) > tuple(map(int, (__version__.split(".")))):
@@ -253,9 +252,10 @@ class KindleGenThread(QtCore.QRunnable):
kindlegenError = '' kindlegenError = ''
try: try:
if os.path.getsize(self.work) < 367001600: if os.path.getsize(self.work) < 367001600:
output = Popen('kindlegen -locale en "' + self.work.encode(sys.getfilesystemencoding()) + '"', output = Popen('kindlegen -locale en "' + self.work.encode(sys.getfilesystemencoding()).decode('utf-8')
stdout=PIPE, stderr=STDOUT, shell=True) + '"', stdout=PIPE, stderr=STDOUT, shell=True)
for line in output.stdout: for line in output.stdout:
line = line.decode('utf-8')
# ERROR: Generic error # ERROR: Generic error
if "Error(" in line: if "Error(" in line:
kindlegenErrorCode = 1 kindlegenErrorCode = 1
@@ -269,9 +269,10 @@ class KindleGenThread(QtCore.QRunnable):
# ERROR: EPUB too big # ERROR: EPUB too big
kindlegenErrorCode = 23026 kindlegenErrorCode = 23026
self.signals.result.emit([kindlegenErrorCode, kindlegenError, self.work]) self.signals.result.emit([kindlegenErrorCode, kindlegenError, self.work])
except StandardError: except Exception as err:
# ERROR: Unknown generic error # ERROR: KCC unknown generic error
kindlegenErrorCode = 1 kindlegenErrorCode = 1
kindlegenError = format(err)
self.signals.result.emit([kindlegenErrorCode, kindlegenError, self.work]) self.signals.result.emit([kindlegenErrorCode, kindlegenError, self.work])
@@ -297,8 +298,9 @@ class KindleUnpackThread(QtCore.QRunnable):
mobisplit = kindlesplit.mobi_split(mobiPath + '_toclean', newKindle) mobisplit = kindlesplit.mobi_split(mobiPath + '_toclean', newKindle)
open(mobiPath, 'wb').write(mobisplit.getResult()) open(mobiPath, 'wb').write(mobisplit.getResult())
self.signals.result.emit([True]) self.signals.result.emit([True])
except StandardError: except Exception as err:
self.signals.result.emit([False]) traceback.print_exc()
self.signals.result.emit([False, format(err)])
class WorkerThread(QtCore.QThread): class WorkerThread(QtCore.QThread):
@@ -385,7 +387,7 @@ class WorkerThread(QtCore.QThread):
for i in range(GUI.JobList.count()): for i in range(GUI.JobList.count()):
# Make sure that we don't consider any system message as job to do # Make sure that we don't consider any system message as job to do
if GUI.JobList.item(i).icon().isNull(): if GUI.JobList.item(i).icon().isNull():
currentJobs.append(unicode(GUI.JobList.item(i).text())) currentJobs.append(str(GUI.JobList.item(i).text()))
GUI.JobList.clear() GUI.JobList.clear()
for job in currentJobs: for job in currentJobs:
sleep(0.5) sleep(0.5)
@@ -466,42 +468,45 @@ class WorkerThread(QtCore.QThread):
if self.kindlegenErrorCode[0] == 0: if self.kindlegenErrorCode[0] == 0:
GUI.progress.content = '' GUI.progress.content = ''
self.emit(QtCore.SIGNAL("addMessage"), 'Creating MOBI files... <b>Done!</b>', 'info', True) self.emit(QtCore.SIGNAL("addMessage"), 'Creating MOBI files... <b>Done!</b>', 'info', True)
self.emit(QtCore.SIGNAL("addMessage"), 'Cleaning MOBI files', 'info') self.emit(QtCore.SIGNAL("addMessage"), 'Cleaning MOBI files is currently disabled in this branch', 'info')
GUI.progress.content = 'Cleaning MOBI files' GUI.progress.content = 'Cleaning MOBI files is currently disabled in this branch'
self.workerOutput = [] #self.emit(QtCore.SIGNAL("addMessage"), 'Cleaning MOBI files', 'info')
# Multithreading KindleUnpack in current form is a waste of resources. #GUI.progress.content = 'Cleaning MOBI files'
# Unless we higly optimise KindleUnpack or drop 32bit support this will not change. #self.workerOutput = []
self.pool.setMaxThreadCount(1) ## Multithreading KindleUnpack in current form is a waste of resources.
for item in outputPath: ## Unless we higly optimise KindleUnpack or drop 32bit support this will not change.
worker = KindleUnpackThread([item, profile]) #self.pool.setMaxThreadCount(1)
worker.signals.result.connect(self.addResult) #for item in outputPath:
self.pool.start(worker) # worker = KindleUnpackThread([item, profile])
self.pool.waitForDone() # worker.signals.result.connect(self.addResult)
sleep(0.5) # self.pool.start(worker)
for success in self.workerOutput: #self.pool.waitForDone()
if not success: #sleep(0.5)
self.errors = True #for success in self.workerOutput:
break # if not success[0]:
if not self.errors: # self.errors = True
for item in outputPath: # print(success[1])
GUI.progress.content = '' # break
mobiPath = item.replace('.epub', '.mobi') #if not self.errors:
os.remove(mobiPath + '_toclean') # for item in outputPath:
GUI.completedWork[os.path.basename(mobiPath).encode('utf-8')] = \ # GUI.progress.content = ''
mobiPath.encode('utf-8') # mobiPath = item.replace('.epub', '.mobi')
self.emit(QtCore.SIGNAL("addMessage"), 'Cleaning MOBI files... <b>Done!</b>', 'info', # os.remove(mobiPath + '_toclean')
True) # GUI.completedWork[os.path.basename(mobiPath).encode('utf-8')] = \
else: # mobiPath.encode('utf-8')
GUI.progress.content = '' # self.emit(QtCore.SIGNAL("addMessage"), 'Cleaning MOBI files... <b>Done!</b>', 'info',
for item in outputPath: # True)
mobiPath = item.replace('.epub', '.mobi') #else:
if os.path.exists(mobiPath): # GUI.progress.content = ''
os.remove(mobiPath) # for item in outputPath:
if os.path.exists(mobiPath + '_toclean'): # mobiPath = item.replace('.epub', '.mobi')
os.remove(mobiPath + '_toclean') # if os.path.exists(mobiPath):
self.emit(QtCore.SIGNAL("addMessage"), 'KindleUnpack failed to clean MOBI file!', 'error') # os.remove(mobiPath)
self.emit(QtCore.SIGNAL("addTrayMessage"), 'KindleUnpack failed to clean MOBI file!', # if os.path.exists(mobiPath + '_toclean'):
'Critical') # os.remove(mobiPath + '_toclean')
# self.emit(QtCore.SIGNAL("addMessage"), 'KindleUnpack failed to clean MOBI file!', 'error')
# self.emit(QtCore.SIGNAL("addTrayMessage"), 'KindleUnpack failed to clean MOBI file!',
# 'Critical')
else: else:
GUI.progress.content = '' GUI.progress.content = ''
epubSize = (os.path.getsize(self.kindlegenErrorCode[2]))/1024/1024 epubSize = (os.path.getsize(self.kindlegenErrorCode[2]))/1024/1024
@@ -571,10 +576,10 @@ class KCCGUI(KCC_ui.Ui_KCC):
else: else:
dnames = "" dnames = ""
for dname in dnames: for dname in dnames:
if unicode(dname) != "": if str(dname) != "":
if sys.platform == 'win32': if sys.platform == 'win32':
dname = dname.replace('/', '\\') dname = dname.replace('/', '\\')
self.lastPath = os.path.abspath(os.path.join(unicode(dname), os.pardir)) self.lastPath = os.path.abspath(os.path.join(str(dname), os.pardir))
GUI.JobList.addItem(dname) GUI.JobList.addItem(dname)
MW.setFocus() MW.setFocus()
@@ -597,8 +602,8 @@ class KCCGUI(KCC_ui.Ui_KCC):
fnames = QtGui.QFileDialog.getOpenFileNames(MW, 'Select file', self.lastPath, fnames = QtGui.QFileDialog.getOpenFileNames(MW, 'Select file', self.lastPath,
'*.cbz *.zip *.pdf') '*.cbz *.zip *.pdf')
for fname in fnames: for fname in fnames:
if unicode(fname) != "": if str(fname) != "":
self.lastPath = os.path.abspath(os.path.join(unicode(fname), os.pardir)) self.lastPath = os.path.abspath(os.path.join(str(fname), os.pardir))
GUI.JobList.addItem(fname) GUI.JobList.addItem(fname)
def clearJobs(self): def clearJobs(self):
@@ -884,19 +889,19 @@ class KCCGUI(KCC_ui.Ui_KCC):
self.settings.setValue('currentFormat', GUI.FormatBox.currentIndex()) self.settings.setValue('currentFormat', GUI.FormatBox.currentIndex())
self.settings.setValue('currentMode', self.currentMode) self.settings.setValue('currentMode', self.currentMode)
self.settings.setValue('firstStart', False) self.settings.setValue('firstStart', False)
self.settings.setValue('options', QtCore.QVariant({'MangaBox': GUI.MangaBox.checkState(), self.settings.setValue('options', {'MangaBox': GUI.MangaBox.checkState(),
'RotateBox': GUI.RotateBox.checkState(), 'RotateBox': GUI.RotateBox.checkState(),
'QualityBox': GUI.QualityBox.checkState(), 'QualityBox': GUI.QualityBox.checkState(),
'ProcessingBox': GUI.ProcessingBox.checkState(), 'ProcessingBox': GUI.ProcessingBox.checkState(),
'UpscaleBox': GUI.UpscaleBox.checkState(), 'UpscaleBox': GUI.UpscaleBox.checkState(),
'NoRotateBox': GUI.NoRotateBox.checkState(), 'NoRotateBox': GUI.NoRotateBox.checkState(),
'BorderBox': GUI.BorderBox.checkState(), 'BorderBox': GUI.BorderBox.checkState(),
'WebtoonBox': GUI.WebtoonBox.checkState(), 'WebtoonBox': GUI.WebtoonBox.checkState(),
'NoDitheringBox': GUI.NoDitheringBox.checkState(), 'NoDitheringBox': GUI.NoDitheringBox.checkState(),
'ColorBox': GUI.ColorBox.checkState(), 'ColorBox': GUI.ColorBox.checkState(),
'customWidth': GUI.customWidth.text(), 'customWidth': GUI.customWidth.text(),
'customHeight': GUI.customHeight.text(), 'customHeight': GUI.customHeight.text(),
'GammaSlider': float(self.GammaValue)*100})) 'GammaSlider': float(self.GammaValue)*100})
self.settings.sync() self.settings.sync()
def handleMessage(self, message): def handleMessage(self, message):
@@ -947,8 +952,7 @@ class KCCGUI(KCC_ui.Ui_KCC):
self.currentMode = self.settings.value('currentMode', 1, type=int) self.currentMode = self.settings.value('currentMode', 1, type=int)
self.currentFormat = self.settings.value('currentFormat', 0, type=int) self.currentFormat = self.settings.value('currentFormat', 0, type=int)
self.firstStart = self.settings.value('firstStart', True, type=bool) self.firstStart = self.settings.value('firstStart', True, type=bool)
self.options = self.settings.value('options', QtCore.QVariant({'GammaSlider': 0})) self.options = self.settings.value('options', {'GammaSlider': 0})
self.options = self.options.toPyObject()
self.worker = WorkerThread() self.worker = WorkerThread()
self.versionCheck = VersionThread() self.versionCheck = VersionThread()
self.contentServer = WebServerThread() self.contentServer = WebServerThread()
@@ -996,7 +1000,8 @@ class KCCGUI(KCC_ui.Ui_KCC):
formats = ['MOBI', 'EPUB', 'CBZ'] formats = ['MOBI', 'EPUB', 'CBZ']
versionCheck = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, shell=True) versionCheck = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, shell=True)
for line in versionCheck.stdout: for line in versionCheck.stdout:
if "Amazon kindlegen" in line: line = line.decode("utf-8")
if 'Amazon kindlegen' in line:
versionCheck = line.split('V')[1].split(' ')[0] versionCheck = line.split('V')[1].split(' ')[0]
if tuple(map(int, (versionCheck.split(".")))) < tuple(map(int, ('2.9'.split(".")))): if tuple(map(int, (versionCheck.split(".")))) < tuple(map(int, ('2.9'.split(".")))):
self.addMessage('Your <a href="http://www.amazon.com/gp/feature.html?ie=UTF8&docId=' self.addMessage('Your <a href="http://www.amazon.com/gp/feature.html?ie=UTF8&docId='

View File

@@ -2,14 +2,14 @@
# Resource object code # Resource object code
# #
# Created: N 6. paź 13:26:15 2013 # Created: mer nov 13 21:20:16 2013
# by: The Resource Compiler for PyQt (Qt v4.8.5) # by: The Resource Compiler for PyQt (Qt v4.8.6)
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore from PyQt4 import QtCore
qt_resource_data = "\ qt_resource_data = b"\
\x00\x00\x09\x59\ \x00\x00\x09\x59\
\x89\ \x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ \x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
@@ -8360,7 +8360,7 @@ qt_resource_data = "\
\xfc\xce\x76\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\ \xfc\xce\x76\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
" "
qt_resource_name = "\ qt_resource_name = b"\
\x00\x07\ \x00\x07\
\x0a\xcc\xf9\x43\ \x0a\xcc\xf9\x43\
\x00\x44\ \x00\x44\
@@ -8444,7 +8444,7 @@ qt_resource_name = "\
\x00\x74\x00\x68\x00\x65\x00\x72\x00\x2e\x00\x70\x00\x6e\x00\x67\ \x00\x74\x00\x68\x00\x65\x00\x72\x00\x2e\x00\x70\x00\x6e\x00\x67\
" "
qt_resource_struct = "\ qt_resource_struct = b"\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x05\x00\x00\x00\x01\ \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\x17\ \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\x36\x00\x02\x00\x00\x00\x01\x00\x00\x00\x11\

View File

@@ -321,4 +321,4 @@ class Ui_KCC(object):
self.ActionBasic.setText(_translate("KCC", "Basic", None)) self.ActionBasic.setText(_translate("KCC", "Basic", None))
self.ActionAdvanced.setText(_translate("KCC", "Advanced", None)) self.ActionAdvanced.setText(_translate("KCC", "Advanced", None))
import KCC_rc from . import KCC_rc

View File

@@ -390,4 +390,4 @@ class Ui_KCC(object):
self.ActionBasic.setText(_translate("KCC", "Basic", None)) self.ActionBasic.setText(_translate("KCC", "Basic", None))
self.ActionAdvanced.setText(_translate("KCC", "Advanced", None)) self.ActionAdvanced.setText(_translate("KCC", "Advanced", None))
import KCC_rc from . import KCC_rc

View File

@@ -408,4 +408,4 @@ class Ui_KCC(object):
self.ActionBasic.setText(_translate("KCC", "Basic", None)) self.ActionBasic.setText(_translate("KCC", "Basic", None))
self.ActionAdvanced.setText(_translate("KCC", "Advanced", None)) self.ActionAdvanced.setText(_translate("KCC", "Advanced", None))
import KCC_rc from . import KCC_rc

View File

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

2
kcc/__main__.py Normal file
View File

@@ -0,0 +1,2 @@
from kcc.comic2ebook import main
main()

View File

@@ -21,7 +21,7 @@ __docformat__ = 'restructuredtext en'
import os import os
import zipfile import zipfile
import rarfile from . import rarfile
import locale import locale
from subprocess import STDOUT, PIPE from subprocess import STDOUT, PIPE
from psutil import Popen from psutil import Popen
@@ -52,7 +52,7 @@ class CBxArchive:
elif f.endswith('/'): elif f.endswith('/'):
try: try:
os.makedirs(os.path.join(targetdir, f)) os.makedirs(os.path.join(targetdir, f))
except StandardError: except Exception:
pass # the dir exists so we are going to extract the images only. pass # the dir exists so we are going to extract the images only.
else: else:
filelist.append(f) filelist.append(f)
@@ -67,7 +67,7 @@ class CBxArchive:
elif f.endswith('/'): elif f.endswith('/'):
try: try:
os.makedirs(os.path.join(targetdir, f)) os.makedirs(os.path.join(targetdir, f))
except StandardError: except Exception:
pass # the dir exists so we are going to extract the images only. pass # the dir exists so we are going to extract the images only.
else: else:
filelist.append(f.encode(locale.getpreferredencoding())) filelist.append(f.encode(locale.getpreferredencoding()))
@@ -85,7 +85,7 @@ class CBxArchive:
raise OSError raise OSError
def extract(self, targetdir): def extract(self, targetdir):
print "\n" + targetdir + "\n" print("\n" + targetdir + "\n")
if self.compressor == 'rar': if self.compressor == 'rar':
self.extractCBR(targetdir) self.extractCBR(targetdir)
elif self.compressor == 'zip': elif self.compressor == 'zip':

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# Copyright (c) 2012-2013 Ciro Mattia Gonano <ciromattia@gmail.com> # Copyright (c) 2012-2013 Ciro Mattia Gonano <ciromattia@gmail.com>
@@ -18,7 +18,7 @@
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE. # PERFORMANCE OF THIS SOFTWARE.
# #
__version__ = '3.6' __version__ = '4.0'
__license__ = 'ISC' __license__ = 'ISC'
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>' __copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
@@ -35,14 +35,15 @@ from optparse import OptionParser, OptionGroup
from multiprocessing import Pool, freeze_support from multiprocessing import Pool, freeze_support
from xml.dom.minidom import parse from xml.dom.minidom import parse
from uuid import uuid4 from uuid import uuid4
from slugify import slugify
try: try:
from PyQt4 import QtCore from PyQt4 import QtCore
except ImportError: except ImportError:
QtCore = None QtCore = None
import comic2panel from . import comic2panel
import image from . import image
import cbxarchive from . import cbxarchive
import pdfjpgextract from . import pdfjpgextract
def buildHTML(path, imgfile): def buildHTML(path, imgfile):
@@ -172,7 +173,6 @@ def buildHTML(path, imgfile):
def buildNCX(dstdir, title, chapters): def buildNCX(dstdir, title, chapters):
options.uuid = str(uuid4()) options.uuid = str(uuid4())
options.uuid = options.uuid.encode('utf-8')
ncxfile = os.path.join(dstdir, 'OEBPS', 'toc.ncx') ncxfile = os.path.join(dstdir, 'OEBPS', 'toc.ncx')
f = open(ncxfile, "w") f = open(ncxfile, "w")
f.writelines(["<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", f.writelines(["<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
@@ -186,7 +186,7 @@ def buildNCX(dstdir, title, chapters):
"<meta name=\"dtb:maxPageNumber\" content=\"0\"/>\n", "<meta name=\"dtb:maxPageNumber\" content=\"0\"/>\n",
"<meta name=\"generated\" content=\"true\"/>\n", "<meta name=\"generated\" content=\"true\"/>\n",
"</head>\n", "</head>\n",
"<docTitle><text>", title.encode('utf-8'), "</text></docTitle>\n", "<docTitle><text>", title, "</text></docTitle>\n",
"<navMap>" "<navMap>"
]) ])
for chapter in chapters: for chapter in chapters:
@@ -195,7 +195,7 @@ def buildNCX(dstdir, title, chapters):
title = os.path.basename(folder) title = os.path.basename(folder)
filename = getImageFileName(os.path.join(folder, chapter[1])) filename = getImageFileName(os.path.join(folder, chapter[1]))
f.write("<navPoint id=\"" + folder.replace('/', '_').replace('\\', '_') + "\"><navLabel><text>" f.write("<navPoint id=\"" + folder.replace('/', '_').replace('\\', '_') + "\"><navLabel><text>"
+ title.encode('utf-8') + "</text></navLabel><content src=\"" + filename[0].replace("\\", "/") + title + "</text></navLabel><content src=\"" + filename[0].replace("\\", "/")
+ ".html\"/></navPoint>\n") + ".html\"/></navPoint>\n")
f.write("</navMap>\n</ncx>") f.write("</navMap>\n</ncx>")
f.close() f.close()
@@ -216,11 +216,11 @@ def buildOPF(dstdir, title, filelist, cover=None):
"xmlns=\"http://www.idpf.org/2007/opf\">\n", "xmlns=\"http://www.idpf.org/2007/opf\">\n",
"<metadata xmlns:opf=\"http://www.idpf.org/2007/opf\" ", "<metadata xmlns:opf=\"http://www.idpf.org/2007/opf\" ",
"xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n", "xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n",
"<dc:title>", title.encode('utf-8'), "</dc:title>\n", "<dc:title>", title, "</dc:title>\n",
"<dc:language>en-US</dc:language>\n", "<dc:language>en-US</dc:language>\n",
"<dc:identifier id=\"BookID\" opf:scheme=\"UUID\">", options.uuid, "</dc:identifier>\n"]) "<dc:identifier id=\"BookID\" opf:scheme=\"UUID\">", options.uuid, "</dc:identifier>\n"])
for author in options.authors: for author in options.authors:
f.writelines(["<dc:Creator>", author.encode('utf-8'), "</dc:Creator>\n"]) f.writelines(["<dc:Creator>", author, "</dc:Creator>\n"])
f.writelines(["<meta name=\"generator\" content=\"KindleComicConverter-" + __version__ + "\"/>\n", f.writelines(["<meta name=\"generator\" content=\"KindleComicConverter-" + __version__ + "\"/>\n",
"<meta name=\"RegionMagnification\" content=\"true\"/>\n", "<meta name=\"RegionMagnification\" content=\"true\"/>\n",
"<meta name=\"region-mag\" content=\"true\"/>\n", "<meta name=\"region-mag\" content=\"true\"/>\n",
@@ -356,9 +356,9 @@ def fileImgProcess(work):
dirpath = work[1] dirpath = work[1]
opt = work[2] opt = work[2]
if opt.verbose: if opt.verbose:
print "Optimizing " + afile + " for " + opt.profile print("Optimizing " + afile + " for " + opt.profile)
else: else:
print ".", print(".", end=' ')
img = image.ComicPage(os.path.join(dirpath, afile), opt.profileData) img = image.ComicPage(os.path.join(dirpath, afile), opt.profileData)
if opt.quality == 2: if opt.quality == 2:
wipe = False wipe = False
@@ -370,7 +370,7 @@ def fileImgProcess(work):
split = img.splitPage(dirpath, opt.righttoleft, opt.rotate) split = img.splitPage(dirpath, opt.righttoleft, opt.rotate)
if split is not None: if split is not None:
if opt.verbose: if opt.verbose:
print "Splitted " + afile print("Splitted " + afile)
img0 = image.ComicPage(split[0], opt.profileData) img0 = image.ComicPage(split[0], opt.profileData)
applyImgOptimization(img0, opt) applyImgOptimization(img0, opt)
img0.saveToDir(dirpath, opt.forcepng, opt.forcecolor, wipe) img0.saveToDir(dirpath, opt.forcepng, opt.forcecolor, wipe)
@@ -394,7 +394,9 @@ def fileImgProcess(work):
img2.rotated = True img2.rotated = True
applyImgOptimization(img2, opt, 0) applyImgOptimization(img2, opt, 0)
img2.saveToDir(dirpath, opt.forcepng, opt.forcecolor, True) img2.saveToDir(dirpath, opt.forcepng, opt.forcecolor, True)
except StandardError: except Exception:
import traceback
traceback.print_tb(sys.exc_info()[2])
return str(sys.exc_info()[1]) return str(sys.exc_info()[1])
@@ -565,7 +567,7 @@ def getWorkFolder(afile):
path = cbx.extract(workdir) path = cbx.extract(workdir)
except OSError: except OSError:
rmtree(workdir, True) rmtree(workdir, True)
print 'UnRAR/7za not found or file failed to extract!' print('UnRAR/7za not found or file failed to extract!')
sys.exit(21) sys.exit(21)
else: else:
rmtree(workdir, True) rmtree(workdir, True)
@@ -592,7 +594,7 @@ def checkComicInfo(path, originalPath):
if os.path.exists(xmlPath): if os.path.exists(xmlPath):
try: try:
xml = parse(xmlPath) xml = parse(xmlPath)
except StandardError: except Exception:
os.remove(xmlPath) os.remove(xmlPath)
return return
options.authors = [] options.authors = []
@@ -628,18 +630,14 @@ def checkComicInfo(path, originalPath):
os.remove(xmlPath) os.remove(xmlPath)
def slugify(value): #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.
if isinstance(value, str): # value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore')
#noinspection PyArgumentList # value = re.sub('[^\w\s\.-]', '', value).strip().lower()
value = unicodedata.normalize('NFKD', unicode(value, 'latin1')).encode('ascii', 'ignore') # value = re.sub('[-\.\s]+', '-', value)
elif isinstance(value, unicode): # value = re.sub(r'([0-9]+)', r'00000\1', value)
value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore') # value = re.sub(r'0*([0-9]{6,})', r'\1', value)
value = re.sub('[^\w\s\.-]', '', value).strip().lower() # return value
value = re.sub('[-\.\s]+', '-', value)
value = re.sub(r'([0-9]+)', r'00000\1', value)
value = re.sub(r'0*([0-9]{6,})', r'\1', value)
return value
def sanitizeTree(filetree): def sanitizeTree(filetree):
@@ -775,7 +773,7 @@ def preSplitDirectory(path):
mode = 0 mode = 0
else: else:
if filesNumber > 0: if filesNumber > 0:
print '\nWARNING: Automatic output splitting failed.' print('\nWARNING: Automatic output splitting failed.')
if GUI: if GUI:
GUI.emit(QtCore.SIGNAL("addMessage"), 'Automatic output splitting failed. <a href=' GUI.emit(QtCore.SIGNAL("addMessage"), 'Automatic output splitting failed. <a href='
'"https://github.com/ciromattia/kcc/wiki' '"https://github.com/ciromattia/kcc/wiki'
@@ -790,7 +788,7 @@ def preSplitDirectory(path):
if len(dirs) != 0: if len(dirs) != 0:
detectedSubSubdirectories = True detectedSubSubdirectories = True
elif len(dirs) == 0 and detectedSubSubdirectories: elif len(dirs) == 0 and detectedSubSubdirectories:
print '\nWARNING: Automatic output splitting failed.' print('\nWARNING: Automatic output splitting failed.')
if GUI: if GUI:
GUI.emit(QtCore.SIGNAL("addMessage"), 'Automatic output splitting failed. <a href=' GUI.emit(QtCore.SIGNAL("addMessage"), 'Automatic output splitting failed. <a href='
'"https://github.com/ciromattia/kcc/wiki' '"https://github.com/ciromattia/kcc/wiki'
@@ -807,7 +805,7 @@ def preSplitDirectory(path):
# One level of subdirectories # One level of subdirectories
mode = 1 mode = 1
if detectedFilesInSubdirectories and detectedSubSubdirectories: if detectedFilesInSubdirectories and detectedSubSubdirectories:
print '\nWARNING: Automatic output splitting failed.' print('\nWARNING: Automatic output splitting failed.')
if GUI: if GUI:
GUI.emit(QtCore.SIGNAL("addMessage"), 'Automatic output splitting failed. <a href=' GUI.emit(QtCore.SIGNAL("addMessage"), 'Automatic output splitting failed. <a href='
'"https://github.com/ciromattia/kcc/wiki' '"https://github.com/ciromattia/kcc/wiki'
@@ -827,12 +825,12 @@ def preSplitDirectory(path):
def Copyright(): def Copyright():
print ('comic2ebook v%(__version__)s. ' print(('comic2ebook v%(__version__)s. '
'Written 2013 by Ciro Mattia Gonano and Pawel Jastrzebski.' % globals()) 'Written 2013 by Ciro Mattia Gonano and Pawel Jastrzebski.' % globals()))
def Usage(): def Usage():
print "Generates EPUB/CBZ comic ebook from a bunch of images." print("Generates EPUB/CBZ comic ebook from a bunch of images.")
parser.print_help() parser.print_help()
@@ -916,7 +914,7 @@ def main(argv=None, qtGUI=None):
else: else:
comic2panel.main(['-y ' + str(image.ProfileData.Profiles[options.profile][1][1]), '-i', path], qtGUI) comic2panel.main(['-y ' + str(image.ProfileData.Profiles[options.profile][1][1]), '-i', path], qtGUI)
if options.imgproc: if options.imgproc:
print "\nProcessing images..." print("\nProcessing images...")
if GUI: if GUI:
GUI.emit(QtCore.SIGNAL("progressBarTick"), 'status', 'Processing images') GUI.emit(QtCore.SIGNAL("progressBarTick"), 'status', 'Processing images')
dirImgProcess(path + "/OEBPS/Images/") dirImgProcess(path + "/OEBPS/Images/")
@@ -943,14 +941,14 @@ def main(argv=None, qtGUI=None):
options.title = options.baseTitle + ' [' + str(tomeNumber) + '/' + str(len(tomes)) + ']' options.title = options.baseTitle + ' [' + str(tomeNumber) + '/' + str(len(tomes)) + ']'
if options.cbzoutput: if options.cbzoutput:
# if CBZ output wanted, compress all images and return filepath # if CBZ output wanted, compress all images and return filepath
print "\nCreating CBZ file..." print("\nCreating CBZ file...")
if len(tomes) > 1: if len(tomes) > 1:
filepath.append(getOutputFilename(args[0], options.output, '.cbz', ' ' + str(tomeNumber))) filepath.append(getOutputFilename(args[0], options.output, '.cbz', ' ' + str(tomeNumber)))
else: else:
filepath.append(getOutputFilename(args[0], options.output, '.cbz', '')) filepath.append(getOutputFilename(args[0], options.output, '.cbz', ''))
make_archive(tome + '_comic', 'zip', tome + '/OEBPS/Images') make_archive(tome + '_comic', 'zip', tome + '/OEBPS/Images')
else: else:
print "\nCreating EPUB structure..." print("\nCreating EPUB structure...")
genEpubStruct(tome) genEpubStruct(tome)
# actually zip the ePub # actually zip the ePub
if len(tomes) > 1: if len(tomes) > 1:
@@ -1017,7 +1015,7 @@ def checkOptions():
options.quality = 0 options.quality = 0
# Kindle for Android profile require target resolution. # Kindle for Android profile require target resolution.
if options.profile == 'KFA' and (options.customwidth == 0 or options.customheight == 0): if options.profile == 'KFA' and (options.customwidth == 0 or options.customheight == 0):
print "ERROR: Kindle for Android profile require --customwidth and --customheight options!" print("ERROR: Kindle for Android profile require --customwidth and --customheight options!")
sys.exit(1) sys.exit(1)
# Override profile data # Override profile data
if options.customwidth != 0 or options.customheight != 0: if options.customwidth != 0 or options.customheight != 0:

View File

@@ -18,7 +18,7 @@
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE. # PERFORMANCE OF THIS SOFTWARE.
# #
__version__ = '3.6' __version__ = '4.0'
__license__ = 'ISC' __license__ = 'ISC'
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>' __copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
@@ -32,26 +32,26 @@ try:
#noinspection PyUnresolvedReferences #noinspection PyUnresolvedReferences
from PIL import Image, ImageStat from PIL import Image, ImageStat
if tuple(map(int, ('2.2.1'.split(".")))) > tuple(map(int, (Image.PILLOW_VERSION.split(".")))): 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!" print("ERROR: Pillow 2.2.1 or newer is required!")
if sys.platform.startswith('linux'): if sys.platform.startswith('linux'):
#noinspection PyUnresolvedReferences #noinspection PyUnresolvedReferences
import Tkinter import tkinter
#noinspection PyUnresolvedReferences #noinspection PyUnresolvedReferences
import tkMessageBox import tkinter.messagebox
importRoot = Tkinter.Tk() importRoot = tkinter.Tk()
importRoot.withdraw() importRoot.withdraw()
tkMessageBox.showerror("KCC - Error", "Pillow 2.2.1 or newer is required!") tkinter.messagebox.showerror("KCC - Error", "Pillow 2.2.1 or newer is required!")
exit(1) exit(1)
except ImportError: except ImportError:
print "ERROR: Pillow is not installed!" print("ERROR: Pillow is not installed!")
if sys.platform.startswith('linux'): if sys.platform.startswith('linux'):
#noinspection PyUnresolvedReferences #noinspection PyUnresolvedReferences
import Tkinter import tkinter
#noinspection PyUnresolvedReferences #noinspection PyUnresolvedReferences
import tkMessageBox import tkinter.messagebox
importRoot = Tkinter.Tk() importRoot = tkinter.Tk()
importRoot.withdraw() importRoot.withdraw()
tkMessageBox.showerror("KCC - Error", "Pillow 2.2.1 or newer is required!") tkinter.messagebox.showerror("KCC - Error", "Pillow 2.2.1 or newer is required!")
exit(1) exit(1)
try: try:
from PyQt4 import QtCore from PyQt4 import QtCore
@@ -118,7 +118,7 @@ def splitImage(work):
# Harcoded opttions # Harcoded opttions
threshold = 1.0 threshold = 1.0
delta = 15 delta = 15
print ".", print(".", end=' ')
fileExpanded = os.path.splitext(name) fileExpanded = os.path.splitext(name)
filePath = os.path.join(path, name) filePath = os.path.join(path, name)
# Detect corrupted files # Detect corrupted files
@@ -210,13 +210,13 @@ def splitImage(work):
str(pageNumber) + '.png'), 'PNG') str(pageNumber) + '.png'), 'PNG')
pageNumber += 1 pageNumber += 1
os.remove(filePath) os.remove(filePath)
except StandardError: except Exception:
return str(sys.exc_info()[1]) return str(sys.exc_info()[1])
def Copyright(): def Copyright():
print ('comic2panel v%(__version__)s. ' print(('comic2panel v%(__version__)s. '
'Written 2013 by Ciro Mattia Gonano and Pawel Jastrzebski.' % globals()) 'Written 2013 by Ciro Mattia Gonano and Pawel Jastrzebski.' % globals()))
def main(argv=None, qtGUI=None): def main(argv=None, qtGUI=None):
@@ -245,7 +245,7 @@ def main(argv=None, qtGUI=None):
if options.height > 0: if options.height > 0:
options.sourceDir = args[0] options.sourceDir = args[0]
options.targetDir = args[0] + "-Splitted" options.targetDir = args[0] + "-Splitted"
print "\nSplitting images..." print("\nSplitting images...")
if os.path.isdir(options.sourceDir): if os.path.isdir(options.sourceDir):
rmtree(options.targetDir, True) rmtree(options.targetDir, True)
copytree(options.sourceDir, options.targetDir) copytree(options.sourceDir, options.targetDir)

View File

@@ -26,26 +26,26 @@ try:
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
from PIL import Image, ImageOps, ImageStat, ImageChops from PIL import Image, ImageOps, ImageStat, ImageChops
if tuple(map(int, ('2.2.1'.split(".")))) > tuple(map(int, (Image.PILLOW_VERSION.split(".")))): 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!" print("ERROR: Pillow 2.2.1 or newer is required!")
if platform.startswith('linux'): if platform.startswith('linux'):
#noinspection PyUnresolvedReferences #noinspection PyUnresolvedReferences
import Tkinter import tkinter
#noinspection PyUnresolvedReferences #noinspection PyUnresolvedReferences
import tkMessageBox import tkinter.messagebox
importRoot = Tkinter.Tk() importRoot = tkinter.Tk()
importRoot.withdraw() importRoot.withdraw()
tkMessageBox.showerror("KCC - Error", "Pillow 2.2.1 or newer is required!") tkinter.messagebox.showerror("KCC - Error", "Pillow 2.2.1 or newer is required!")
exit(1) exit(1)
except ImportError: except ImportError:
print "ERROR: Pillow is not installed!" print("ERROR: Pillow is not installed!")
if platform.startswith('linux'): if platform.startswith('linux'):
#noinspection PyUnresolvedReferences #noinspection PyUnresolvedReferences
import Tkinter import tkinter
#noinspection PyUnresolvedReferences #noinspection PyUnresolvedReferences
import tkMessageBox import tkinter.messagebox
importRoot = Tkinter.Tk() importRoot = tkinter.Tk()
importRoot.withdraw() importRoot.withdraw()
tkMessageBox.showerror("KCC - Error", "Pillow 2.2.1 or newer is required!") tkinter.messagebox.showerror("KCC - Error", "Pillow 2.2.1 or newer is required!")
exit(1) exit(1)
@@ -287,10 +287,10 @@ class ComicPage:
ratioDev = float(self.size[0]) / float(self.size[1]) ratioDev = float(self.size[0]) / float(self.size[1])
if (float(self.image.size[0]) / float(self.image.size[1])) < ratioDev: if (float(self.image.size[0]) / float(self.image.size[1])) < ratioDev:
diff = int(self.image.size[1] * ratioDev) - self.image.size[0] diff = int(self.image.size[1] * ratioDev) - self.image.size[0]
self.image = ImageOps.expand(self.image, border=(diff / 2, 0), fill=fill) self.image = ImageOps.expand(self.image, border=(int(diff / 2), 0), fill=fill)
elif (float(self.image.size[0]) / float(self.image.size[1])) > ratioDev: elif (float(self.image.size[0]) / float(self.image.size[1])) > ratioDev:
diff = int(self.image.size[0] / ratioDev) - self.image.size[1] diff = int(self.image.size[0] / ratioDev) - self.image.size[1]
self.image = ImageOps.expand(self.image, border=(0, diff / 2), fill=fill) self.image = ImageOps.expand(self.image, border=(0, int(diff / 2)), fill=fill)
self.image = ImageOps.fit(self.image, size, method=method, centering=(0.5, 0.5)) self.image = ImageOps.fit(self.image, size, method=method, centering=(0.5, 0.5))
if generateBorder: if generateBorder:
if fill == 'white': if fill == 'white':

View File

@@ -1,3 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Based on initial version of KindleUnpack. Copyright (C) 2009 Charles M. Hannum <root@ihack.net> # 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 # Improvements Copyright (C) 2009-2012 P. Durrant, K. Hendricks, S. Siebert, fandrieu, DiapDealer, nickredding
# Copyright (C) 2013 Pawel Jastrzebski <pawelj@vulturis.eu> # Copyright (C) 2013 Pawel Jastrzebski <pawelj@vulturis.eu>
@@ -105,8 +108,8 @@ def nullsection(datain, secno): # make it zero-length without deleting it
datalst.append('\0' * lpad) datalst.append('\0' * lpad)
datalst.append(datain[zerosecstart: secstart]) datalst.append(datain[zerosecstart: secstart])
datalst.append(datain[secend:]) datalst.append(datain[secend:])
dataout = "".join(datalst) dataout = "".join(str(datalst)[1:-1])
return dataout return dataout.encode('utf-8')
def deletesectionrange(datain, firstsec, lastsec): # delete a range of sections def deletesectionrange(datain, firstsec, lastsec): # delete a range of sections
@@ -135,8 +138,8 @@ def deletesectionrange(datain, firstsec, lastsec): # delete a range of sections
datalst.append('\0' * lpad) datalst.append('\0' * lpad)
datalst.append(datain[zerosecstart:firstsecstart]) datalst.append(datain[zerosecstart:firstsecstart])
datalst.append(datain[lastsecend:]) datalst.append(datain[lastsecend:])
dataout = "".join(datalst) dataout = "".join(str(datalst)[1:-1])
return dataout return dataout.encode('utf-8')
def insertsection(datain, secno, secdata): # insert a new section def insertsection(datain, secno, secdata): # insert a new section
@@ -166,13 +169,14 @@ def insertsection(datain, secno, secdata): # insert a new section
datalst.append(datain[zerosecstart:secstart]) datalst.append(datain[zerosecstart:secstart])
datalst.append(secdata) datalst.append(secdata)
datalst.append(datain[secstart:]) datalst.append(datain[secstart:])
dataout = "".join(datalst) dataout = "".join(str(datalst)[1:-1])
return dataout return dataout.encode('utf-8')
def insertsectionrange(sectionsource, firstsec, lastsec, sectiontarget, targetsec): # insert a range of sections def insertsectionrange(sectionsource, firstsec, lastsec, sectiontarget, targetsec): # insert a range of sections
dataout = sectiontarget dataout = sectiontarget
for idx in range(lastsec, firstsec-1, -1): for idx in range(lastsec, firstsec-1, -1):
print(dataout)
dataout = insertsection(dataout, targetsec, readsection(sectionsource, idx)) dataout = insertsection(dataout, targetsec, readsection(sectionsource, idx))
return dataout return dataout
@@ -381,4 +385,10 @@ class mobi_split:
raise raise
def getResult(self): def getResult(self):
return self.result_file return self.result_file
if __name__ == "__main__":
import sys
mobi_split(sys.argv[1], False)
sys.exit(0)

View File

@@ -63,7 +63,7 @@ class PdfJpgExtract:
istart += startfix istart += startfix
iend += endfix iend += endfix
print "JPG %d from %d to %d" % (njpg, istart, iend) print("JPG %d from %d to %d" % (njpg, istart, iend))
jpg = pdf[istart:iend] jpg = pdf[istart:iend]
jpgfile = file(self.path + "/jpg%d.jpg" % njpg, "wb") jpgfile = file(self.path + "/jpg%d.jpg" % njpg, "wb")
jpgfile.write(jpg) jpgfile.write(jpg)

View File

@@ -633,7 +633,7 @@ class RarFile(object):
def printdir(self): def printdir(self):
"""Print archive file list to stdout.""" """Print archive file list to stdout."""
for f in self._info_list: for f in self._info_list:
print(f.filename) print((f.filename))
def extract(self, member, path=None, pwd=None): def extract(self, member, path=None, pwd=None):
"""Extract single file into current directory. """Extract single file into current directory.
@@ -1138,7 +1138,7 @@ class RarFile(object):
if self._crc_check: if self._crc_check:
crc = crc32(cmt) crc = crc32(cmt)
if crc < 0: if crc < 0:
crc += (long(1) << 32) crc += (int(1) << 32)
if crc != inf.CRC: if crc != inf.CRC:
return None return None
@@ -1342,7 +1342,7 @@ class RarExtFile(RawIOBase):
raise BadRarFile("Failed the read enough data") raise BadRarFile("Failed the read enough data")
crc = self.CRC crc = self.CRC
if crc < 0: if crc < 0:
crc += (long(1) << 32) crc += (int(1) << 32)
if crc != self.inf.CRC: if crc != self.inf.CRC:
raise BadRarFile("Corrupt file - CRC check failed: " + self.inf.filename) raise BadRarFile("Corrupt file - CRC check failed: " + self.inf.filename)

4
requirements.txt Normal file
View File

@@ -0,0 +1,4 @@
Pillow==2.2.1
Unidecode==0.04.14
psutil==1.1.3
python-slugify==0.0.6

View File

@@ -11,7 +11,7 @@ Usage (Windows):
from sys import platform from sys import platform
NAME = "KindleComicConverter" NAME = "KindleComicConverter"
VERSION = "3.6" VERSION = "4.0"
MAIN = "kcc.py" MAIN = "kcc.py"
if platform == "darwin": if platform == "darwin":
@@ -72,7 +72,7 @@ elif platform == "win32":
appendScriptToLibrary=False, appendScriptToLibrary=False,
compress=True)]) compress=True)])
else: else:
print 'Please use setup.sh to build Linux package.' print('Please use setup.sh to build Linux package.')
exit() exit()
#noinspection PyUnboundLocalVariable #noinspection PyUnboundLocalVariable
@@ -91,5 +91,5 @@ setup(
if platform == "darwin": if platform == "darwin":
from os import chmod from os import chmod
chmod('dist/' + NAME + '.app/Contents/Resources/unrar', 0777) chmod('dist/' + NAME + '.app/Contents/Resources/unrar', 0o777)
chmod('dist/' + NAME + '.app/Contents/Resources/7za', 0777) chmod('dist/' + NAME + '.app/Contents/Resources/7za', 0o777)

View File

@@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
# Linux Python package build script # Linux Python package build script
VERSION="3.6" VERSION="4.0"
cp kcc.py __main__.py cp kcc.py __main__.py
zip kcc.zip __main__.py kcc/*.py zip kcc.zip __main__.py kcc/*.py