mirror of
https://github.com/ciromattia/kcc
synced 2025-12-15 10:46:40 +00:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -41,7 +41,7 @@ You can find the latest released binary at the following links:
|
|||||||
### For compiling/running from source:
|
### For compiling/running from source:
|
||||||
- Python 2.7 - Included in MacOS and Linux, follow the [official documentation](http://www.python.org/getit/windows/) to install on Windows.
|
- Python 2.7 - Included in MacOS and Linux, follow the [official documentation](http://www.python.org/getit/windows/) to install on Windows.
|
||||||
- PyQt4 - Please refer to official documentation for installing into your system.
|
- 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.
|
||||||
|
|
||||||
## USAGE
|
## USAGE
|
||||||
|
|
||||||
|
|||||||
60
kcc.py
60
kcc.py
@@ -27,7 +27,7 @@ import sys
|
|||||||
import os
|
import os
|
||||||
try:
|
try:
|
||||||
# noinspection PyUnresolvedReferences
|
# noinspection PyUnresolvedReferences
|
||||||
from PyQt4 import QtGui
|
from PyQt4 import QtCore, QtGui, QtNetwork
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print "ERROR: PyQT4 is not installed!"
|
print "ERROR: PyQT4 is not installed!"
|
||||||
exit(1)
|
exit(1)
|
||||||
@@ -41,13 +41,67 @@ elif sys.platform.startswith('linux'):
|
|||||||
else:
|
else:
|
||||||
from kcc import KCC_ui
|
from kcc import KCC_ui
|
||||||
|
|
||||||
|
|
||||||
|
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())
|
||||||
|
|
||||||
|
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()
|
freeze_support()
|
||||||
APP = QtGui.QApplication(sys.argv)
|
APP = QApplicationMessaging(sys.argv)
|
||||||
|
if APP.isRunning():
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
APP.sendMessage('Araise!')
|
||||||
|
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()
|
KCC = QtGui.QMainWindow()
|
||||||
UI = KCC_ui.Ui_KCC()
|
UI = KCC_ui.Ui_KCC()
|
||||||
UI.setupUi(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.setWindowTitle("Kindle Comic Converter " + __version__)
|
||||||
KCC.show()
|
KCC.show()
|
||||||
KCC.raise_()
|
KCC.raise_()
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
GUI.handleMessage(sys.argv[1].decode(sys.getfilesystemencoding()))
|
||||||
sys.exit(APP.exec_())
|
sys.exit(APP.exec_())
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ class WorkerThread(QtCore.QThread):
|
|||||||
argv.append("--forcecolor")
|
argv.append("--forcecolor")
|
||||||
for i in range(GUI.JobList.count()):
|
for i in range(GUI.JobList.count()):
|
||||||
if GUI.JobList.item(i).icon().isNull():
|
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()
|
GUI.JobList.clear()
|
||||||
for job in currentJobs:
|
for job in currentJobs:
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
@@ -215,8 +215,8 @@ class WorkerThread(QtCore.QThread):
|
|||||||
try:
|
try:
|
||||||
self.kindlegenErrorCode = 0
|
self.kindlegenErrorCode = 0
|
||||||
if os.path.getsize(item) < 367001600:
|
if os.path.getsize(item) < 367001600:
|
||||||
output = Popen('kindlegen -locale en "' + item + '"', stdout=PIPE, stderr=STDOUT,
|
output = Popen('kindlegen -locale en "' + item.encode(sys.getfilesystemencoding()) +
|
||||||
shell=True)
|
'"', stdout=PIPE, stderr=STDOUT, shell=True)
|
||||||
for line in output.stdout:
|
for line in output.stdout:
|
||||||
# ERROR: Generic error
|
# ERROR: Generic error
|
||||||
if "Error(" in line:
|
if "Error(" in line:
|
||||||
@@ -312,18 +312,11 @@ class Ui_KCC(object):
|
|||||||
dnames = dirDialog.selectedFiles()
|
dnames = dirDialog.selectedFiles()
|
||||||
else:
|
else:
|
||||||
dnames = ""
|
dnames = ""
|
||||||
# Lame UTF-8 security measure
|
|
||||||
for dname in dnames:
|
for dname in dnames:
|
||||||
try:
|
if unicode(dname) != "":
|
||||||
str(dname)
|
|
||||||
except Exception:
|
|
||||||
QtGui.QMessageBox.critical(MainWindow, 'KCC Error', "Path cannot contain non-ASCII characters.",
|
|
||||||
QtGui.QMessageBox.Ok)
|
|
||||||
return
|
|
||||||
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(str(dname), os.pardir))
|
self.lastPath = os.path.abspath(os.path.join(unicode(dname), os.pardir))
|
||||||
GUI.JobList.addItem(dname)
|
GUI.JobList.addItem(dname)
|
||||||
|
|
||||||
def selectFile(self):
|
def selectFile(self):
|
||||||
@@ -344,16 +337,9 @@ class Ui_KCC(object):
|
|||||||
else:
|
else:
|
||||||
fnames = QtGui.QFileDialog.getOpenFileNames(MainWindow, 'Select file', self.lastPath,
|
fnames = QtGui.QFileDialog.getOpenFileNames(MainWindow, 'Select file', self.lastPath,
|
||||||
'*.cbz *.zip *.pdf')
|
'*.cbz *.zip *.pdf')
|
||||||
# Lame UTF-8 security measure
|
|
||||||
for fname in fnames:
|
for fname in fnames:
|
||||||
try:
|
if unicode(fname) != "":
|
||||||
str(fname)
|
self.lastPath = os.path.abspath(os.path.join(unicode(fname), os.pardir))
|
||||||
except Exception:
|
|
||||||
QtGui.QMessageBox.critical(MainWindow, 'KCC Error', "Path cannot contain non-ASCII characters.",
|
|
||||||
QtGui.QMessageBox.Ok)
|
|
||||||
return
|
|
||||||
if str(fname) != "":
|
|
||||||
self.lastPath = os.path.abspath(os.path.join(str(fname), os.pardir))
|
|
||||||
GUI.JobList.addItem(fname)
|
GUI.JobList.addItem(fname)
|
||||||
|
|
||||||
def clearJobs(self):
|
def clearJobs(self):
|
||||||
@@ -577,7 +563,7 @@ class Ui_KCC(object):
|
|||||||
GUI.JobList.scrollToBottom()
|
GUI.JobList.scrollToBottom()
|
||||||
|
|
||||||
def showDialog(self, message):
|
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):
|
def updateProgressbar(self, new=False, status=False):
|
||||||
if new == "status":
|
if new == "status":
|
||||||
@@ -643,7 +629,11 @@ class Ui_KCC(object):
|
|||||||
'GammaSlider': float(self.GammaValue)*100}))
|
'GammaSlider': float(self.GammaValue)*100}))
|
||||||
self.settings.sync()
|
self.settings.sync()
|
||||||
|
|
||||||
def __init__(self, UI, KCC):
|
def handleMessage(self, message):
|
||||||
|
#TODO
|
||||||
|
print message
|
||||||
|
|
||||||
|
def __init__(self, UI, KCC, APP):
|
||||||
global GUI, MainWindow
|
global GUI, MainWindow
|
||||||
GUI = UI
|
GUI = UI
|
||||||
MainWindow = KCC
|
MainWindow = KCC
|
||||||
@@ -714,6 +704,7 @@ class Ui_KCC(object):
|
|||||||
self.addMessage('Cannot find <a href="http://www.7-zip.org/download.html">7za</a>!'
|
self.addMessage('Cannot find <a href="http://www.7-zip.org/download.html">7za</a>!'
|
||||||
' Processing of CB7/7Z files will be disabled.', 'warning')
|
' Processing of CB7/7Z files will be disabled.', 'warning')
|
||||||
|
|
||||||
|
APP.connect(APP, QtCore.SIGNAL('messageFromOtherInstance'), self.handleMessage)
|
||||||
GUI.BasicModeButton.clicked.connect(self.modeBasic)
|
GUI.BasicModeButton.clicked.connect(self.modeBasic)
|
||||||
GUI.AdvModeButton.clicked.connect(self.modeAdvanced)
|
GUI.AdvModeButton.clicked.connect(self.modeAdvanced)
|
||||||
GUI.DirectoryButton.clicked.connect(self.selectDir)
|
GUI.DirectoryButton.clicked.connect(self.selectDir)
|
||||||
|
|||||||
@@ -184,7 +184,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, "</text></docTitle>\n",
|
"<docTitle><text>", title.encode('utf-8'), "</text></docTitle>\n",
|
||||||
"<navMap>"
|
"<navMap>"
|
||||||
])
|
])
|
||||||
for chapter in chapters:
|
for chapter in chapters:
|
||||||
@@ -192,8 +192,9 @@ def buildNCX(dstdir, title, chapters):
|
|||||||
if os.path.basename(folder) != "Text":
|
if os.path.basename(folder) != "Text":
|
||||||
title = os.path.basename(folder)
|
title = os.path.basename(folder)
|
||||||
filename = getImageFileName(os.path.join(folder, chapter[1]))
|
filename = getImageFileName(os.path.join(folder, chapter[1]))
|
||||||
f.write("<navPoint id=\"" + folder.replace('/', '_').replace('\\', '_') + "\"><navLabel><text>" + title
|
f.write("<navPoint id=\"" + folder.replace('/', '_').replace('\\', '_') + "\"><navLabel><text>"
|
||||||
+ "</text></navLabel><content src=\"" + filename[0].replace("\\", "/") + ".html\"/></navPoint>\n")
|
+ title.encode('utf-8') + "</text></navLabel><content src=\"" + filename[0].replace("\\", "/")
|
||||||
|
+ ".html\"/></navPoint>\n")
|
||||||
f.write("</navMap>\n</ncx>")
|
f.write("</navMap>\n</ncx>")
|
||||||
f.close()
|
f.close()
|
||||||
return
|
return
|
||||||
@@ -213,7 +214,7 @@ 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, "</dc:title>\n",
|
"<dc:title>", title.encode('utf-8'), "</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",
|
||||||
"<dc:Creator>KCC</dc:Creator>\n",
|
"<dc:Creator>KCC</dc:Creator>\n",
|
||||||
|
|||||||
@@ -32,6 +32,9 @@ from multiprocessing import Pool, Queue, freeze_support
|
|||||||
try:
|
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(".")))):
|
||||||
|
print "ERROR: Pillow 2.2.1 or newer is required!"
|
||||||
|
exit(1)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print "ERROR: Pillow is not installed!"
|
print "ERROR: Pillow is not installed!"
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ import os
|
|||||||
try:
|
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(".")))):
|
||||||
|
print "ERROR: Pillow 2.2.1 or newer is required!"
|
||||||
|
exit(1)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print "ERROR: Pillow is not installed!"
|
print "ERROR: Pillow is not installed!"
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|||||||
Reference in New Issue
Block a user