From 36f8c82eaf2a539bb4571bf97309f9a30a4f0926 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jastrz=C4=99bski?= Date: Tue, 30 Dec 2014 11:00:21 +0100 Subject: [PATCH 01/12] Fixed OSX race condition --- kcc.py | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/kcc.py b/kcc.py index 296714a..0c963d3 100755 --- a/kcc.py +++ b/kcc.py @@ -24,10 +24,31 @@ __copyright__ = '2012-2014, Ciro Mattia Gonano , Pawel Jas __docformat__ = 'restructuredtext en' import sys +import os if sys.version_info[0] != 3: print('ERROR: This is Python 3 script!') exit(1) +# OS specific PATH variable workarounds +if sys.platform.startswith('darwin') and 'RESOURCEPATH' not in os.environ: + os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + '/other/:' + os.environ['PATH'] +elif sys.platform.startswith('win'): + if getattr(sys, 'frozen', False): + os.chdir(os.path.dirname(os.path.abspath(sys.executable))) + + # Implementing dummy stdout and stderr for frozen Windows release + class FakeSTD(object): + def write(self, string): + pass + + def flush(self): + pass + sys.stdout = FakeSTD() + sys.stderr = FakeSTD() + else: + os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + '/other/;' + os.environ['PATH'] + os.chdir(os.path.dirname(os.path.abspath(__file__))) + # Dependency check missing = [] try: @@ -69,30 +90,9 @@ if len(missing) > 0: print('ERROR: ' + ', '.join(missing) + ' is not installed!') exit(1) -import os from multiprocessing import freeze_support from kcc import KCC_gui -# OS specific PATH variable workarounds -if sys.platform.startswith('darwin') and 'RESOURCEPATH' not in os.environ: - os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + '/other/:' + os.environ['PATH'] -elif sys.platform.startswith('win'): - if getattr(sys, 'frozen', False): - os.chdir(os.path.dirname(os.path.abspath(sys.executable))) - - # Implementing dummy stdout and stderr for frozen Windows release - class FakeSTD(object): - def write(self, string): - pass - - def flush(self): - pass - sys.stdout = FakeSTD() - sys.stderr = FakeSTD() - else: - os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + '/other/;' + os.environ['PATH'] - os.chdir(os.path.dirname(os.path.abspath(__file__))) - # Implementing detection of already running KCC instance and forwarding argv to it class QApplicationMessaging(QtWidgets.QApplication): From 68b4b7114dea8dc668682f129f6be0ca0d982b97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jastrz=C4=99bski?= Date: Tue, 30 Dec 2014 11:07:11 +0100 Subject: [PATCH 02/12] Added RAR5 support --- kcc/rarfile.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/kcc/rarfile.py b/kcc/rarfile.py index 6eefdb4..567f5ce 100644 --- a/kcc/rarfile.py +++ b/kcc/rarfile.py @@ -1,6 +1,6 @@ # rarfile.py # -# Copyright (c) 2005-2013 Marko Kreen +# Copyright (c) 2005-2014 Marko Kreen # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted, provided that the above @@ -74,7 +74,7 @@ For more details, refer to source. """ -__version__ = '2.6' +__version__ = '2.7-kcc' # export only interesting items __all__ = ['is_rarfile', 'RarInfo', 'RarFile', 'RarExtFile'] @@ -196,7 +196,7 @@ ALT_TEST_ARGS = ('-t', '-f') ALT_CHECK_ARGS = ('--help',) #: whether to speed up decompression by using tmp archive -USE_EXTRACT_HACK = 1 +USE_EXTRACT_HACK = 0 #: limit the filesize for tmp archive usage HACK_SIZE_LIMIT = 20*1024*1024 @@ -295,6 +295,7 @@ RAR_M5 = 0x35 ## RAR_ID = bytes("Rar!\x1a\x07\x00", 'ascii') +RAR5_ID = bytes("Rar!\x1a\x07\x01", 'ascii') ZERO = bytes("\0", 'ascii') EMPTY = bytes("", 'ascii') @@ -362,7 +363,10 @@ def is_rarfile(xfile): fd = XFile(xfile) buf = fd.read(len(RAR_ID)) fd.close() - return buf == RAR_ID + if buf == RAR_ID or buf == RAR5_ID: + return True + else: + return False class RarInfo(object): @@ -785,7 +789,7 @@ class RarFile(object): fd = XFile(self.rarfile) self._fd = fd id = fd.read(len(RAR_ID)) - if id != RAR_ID: + if id != RAR_ID and id != RAR5_ID: raise NotRarFile("Not a Rar archive: "+self.rarfile) volume = 0 # first vol (.rar) is 0 From f66c83425c0f1dfd870247f7ada5661427438055 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jastrz=C4=99bski?= Date: Thu, 1 Jan 2015 15:24:59 +0100 Subject: [PATCH 03/12] PyQT 5.4 update --- KCC-Linux.ui | 6 ------ KCC-OSX.ui | 6 ------ KCC.ui | 6 ------ kcc/KCC_gui.py | 4 ++++ kcc/KCC_ui.py | 2 -- kcc/KCC_ui_linux.py | 2 -- kcc/KCC_ui_osx.py | 2 -- 7 files changed, 4 insertions(+), 24 deletions(-) diff --git a/KCC-Linux.ui b/KCC-Linux.ui index 6c6c2f8..727d3e4 100644 --- a/KCC-Linux.ui +++ b/KCC-Linux.ui @@ -457,12 +457,6 @@ 18 - - QAbstractItemView::ScrollPerPixel - - - QAbstractItemView::ScrollPerPixel - diff --git a/KCC-OSX.ui b/KCC-OSX.ui index 28e1daa..da3690a 100644 --- a/KCC-OSX.ui +++ b/KCC-OSX.ui @@ -456,12 +456,6 @@ QAbstractItemView::NoSelection - - QAbstractItemView::ScrollPerPixel - - - QAbstractItemView::ScrollPerPixel - diff --git a/KCC.ui b/KCC.ui index 28b7cd9..15a9443 100644 --- a/KCC.ui +++ b/KCC.ui @@ -391,12 +391,6 @@ QAbstractItemView::NoSelection - - QAbstractItemView::ScrollPerPixel - - - QAbstractItemView::ScrollPerPixel - diff --git a/kcc/KCC_gui.py b/kcc/KCC_gui.py index 1fd8a7f..9e18389 100644 --- a/kcc/KCC_gui.py +++ b/kcc/KCC_gui.py @@ -525,6 +525,7 @@ class KCCGUI(KCC_ui.Ui_KCC): dname = dname.replace('/', '\\') self.lastPath = os.path.abspath(os.path.join(dname, os.pardir)) GUI.JobList.addItem(dname) + GUI.JobList.scrollToBottom() def selectFile(self): if self.needClean: @@ -550,6 +551,7 @@ class KCCGUI(KCC_ui.Ui_KCC): fname = fname.replace('/', '\\') self.lastPath = os.path.abspath(os.path.join(fname, os.pardir)) GUI.JobList.addItem(fname) + GUI.JobList.scrollToBottom() def clearJobs(self): GUI.JobList.clear() @@ -954,10 +956,12 @@ class KCCGUI(KCC_ui.Ui_KCC): formats = ['.cbz', '.zip', '.pdf'] if os.path.isdir(message): GUI.JobList.addItem(message) + GUI.JobList.scrollToBottom() elif os.path.isfile(message): extension = os.path.splitext(message) if extension[1].lower() in formats: GUI.JobList.addItem(message) + GUI.JobList.scrollToBottom() else: self.addMessage('This file type is unsupported!', 'error') diff --git a/kcc/KCC_ui.py b/kcc/KCC_ui.py index 612009a..c8c6f47 100644 --- a/kcc/KCC_ui.py +++ b/kcc/KCC_ui.py @@ -141,8 +141,6 @@ class Ui_KCC(object): self.JobList.setStyleSheet("QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}") self.JobList.setProperty("showDropIndicator", False) self.JobList.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection) - self.JobList.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel) - self.JobList.setHorizontalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel) self.JobList.setObjectName("JobList") self.BasicModeButton = QtWidgets.QPushButton(self.Form) self.BasicModeButton.setGeometry(QtCore.QRect(10, 10, 195, 32)) diff --git a/kcc/KCC_ui_linux.py b/kcc/KCC_ui_linux.py index cdc0661..009977c 100644 --- a/kcc/KCC_ui_linux.py +++ b/kcc/KCC_ui_linux.py @@ -182,8 +182,6 @@ class Ui_KCC(object): self.JobList.setProperty("showDropIndicator", False) self.JobList.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection) self.JobList.setIconSize(QtCore.QSize(18, 18)) - self.JobList.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel) - self.JobList.setHorizontalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel) self.JobList.setObjectName("JobList") self.BasicModeButton = QtWidgets.QPushButton(self.Form) self.BasicModeButton.setGeometry(QtCore.QRect(10, 10, 195, 32)) diff --git a/kcc/KCC_ui_osx.py b/kcc/KCC_ui_osx.py index 4bc9848..09fed61 100644 --- a/kcc/KCC_ui_osx.py +++ b/kcc/KCC_ui_osx.py @@ -188,8 +188,6 @@ class Ui_KCC(object): self.JobList.setStyleSheet("QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}") self.JobList.setProperty("showDropIndicator", False) self.JobList.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection) - self.JobList.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel) - self.JobList.setHorizontalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel) self.JobList.setObjectName("JobList") self.BasicModeButton = QtWidgets.QPushButton(self.Form) self.BasicModeButton.setGeometry(QtCore.QRect(5, 10, 210, 41)) From b629b45d461be473c3d1a38bd8e921ef493b80c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jastrz=C4=99bski?= Date: Fri, 2 Jan 2015 09:27:54 +0100 Subject: [PATCH 04/12] Pillow update --- kcc-c2e.py | 6 +++--- kcc-c2p.py | 6 +++--- kcc.py | 6 +++--- kcc/comic2ebook.py | 2 +- kcc/comic2panel.py | 6 +++--- kcc/image.py | 32 ++++++++++++++++---------------- kcc/shared.py | 14 ++++---------- 7 files changed, 33 insertions(+), 39 deletions(-) diff --git a/kcc-c2e.py b/kcc-c2e.py index 01ab86e..bbc22b2 100755 --- a/kcc-c2e.py +++ b/kcc-c2e.py @@ -40,10 +40,10 @@ except ImportError: try: # noinspection PyUnresolvedReferences import PIL - if tuple(map(int, ('2.5.0'.split(".")))) > tuple(map(int, (PIL.PILLOW_VERSION.split(".")))): - missing.append('Pillow 2.5.0+') + if tuple(map(int, ('2.7.0'.split(".")))) > tuple(map(int, (PIL.PILLOW_VERSION.split(".")))): + missing.append('Pillow 2.7.0+') except ImportError: - missing.append('Pillow 2.5.0+') + missing.append('Pillow 2.7.0+') try: # noinspection PyUnresolvedReferences import slugify diff --git a/kcc-c2p.py b/kcc-c2p.py index 57acd33..7388f7f 100755 --- a/kcc-c2p.py +++ b/kcc-c2p.py @@ -33,10 +33,10 @@ missing = [] try: # noinspection PyUnresolvedReferences import PIL - if tuple(map(int, ('2.5.0'.split(".")))) > tuple(map(int, (PIL.PILLOW_VERSION.split(".")))): - missing.append('Pillow 2.5.0+') + if tuple(map(int, ('2.7.0'.split(".")))) > tuple(map(int, (PIL.PILLOW_VERSION.split(".")))): + missing.append('Pillow 2.7.0+') except ImportError: - missing.append('Pillow 2.5.0+') + missing.append('Pillow 2.7.0+') if len(missing) > 0: try: # noinspection PyUnresolvedReferences diff --git a/kcc.py b/kcc.py index 0c963d3..f7fc51f 100755 --- a/kcc.py +++ b/kcc.py @@ -68,10 +68,10 @@ except ImportError: try: # noinspection PyUnresolvedReferences import PIL - if tuple(map(int, ('2.5.0'.split(".")))) > tuple(map(int, (PIL.PILLOW_VERSION.split(".")))): - missing.append('Pillow 2.5.0+') + if tuple(map(int, ('2.7.0'.split(".")))) > tuple(map(int, (PIL.PILLOW_VERSION.split(".")))): + missing.append('Pillow 2.7.0+') except ImportError: - missing.append('Pillow 2.5.0+') + missing.append('Pillow 2.7.0+') try: # noinspection PyUnresolvedReferences import slugify diff --git a/kcc/comic2ebook.py b/kcc/comic2ebook.py index b658c2b..7401e45 100755 --- a/kcc/comic2ebook.py +++ b/kcc/comic2ebook.py @@ -552,7 +552,7 @@ def imgFileProcessing(work): if opt.quality == 2: img2 = image.ComicPage(os.path.join(dirpath, afile), opt.profileData, img.fill) if img.rotated: - img2.image = img2.image.rotate(90) + img2.image = img2.image.rotate(90, Image.BICUBIC, True) img2.rotated = True imgOptimization(img2, opt, img) output.append(img2.saveToDir(dirpath, opt.forcepng, opt.forcecolor)) diff --git a/kcc/comic2panel.py b/kcc/comic2panel.py index fff58ec..3b42258 100644 --- a/kcc/comic2panel.py +++ b/kcc/comic2panel.py @@ -77,7 +77,7 @@ def mergeDirectory(work): y += img.size[1] os.remove(i) savePath = os.path.split(imagesClear[0]) - result.save(os.path.join(savePath[0], os.path.splitext(savePath[1])[0] + '.png'), 'PNG') + result.save(os.path.join(savePath[0], os.path.splitext(savePath[1])[0] + '.png'), 'PNG', optimize=1) except Exception: return str(sys.exc_info()[1]) @@ -165,7 +165,7 @@ def splitImage(work): panels.append(panel) if opt.debug: # noinspection PyUnboundLocalVariable - debugImage.save(os.path.join(path, fileExpanded[0] + '-debug.png'), 'PNG') + debugImage.save(os.path.join(path, fileExpanded[0] + '-debug.png'), 'PNG', optimize=1) # Create virtual pages pages = [] @@ -200,7 +200,7 @@ def splitImage(work): newPage.paste(panelImg, (0, targetHeight)) targetHeight += panels[panel][2] newPage.save(os.path.join(path, fileExpanded[0] + '-' + - str(pageNumber) + '.png'), 'PNG') + str(pageNumber) + '.png'), 'PNG', optimize=1) pageNumber += 1 os.remove(filePath) except Exception: diff --git a/kcc/image.py b/kcc/image.py index b32bb74..212feda 100755 --- a/kcc/image.py +++ b/kcc/image.py @@ -144,14 +144,14 @@ class ComicPage: if self.noVPV: flags.append('NoVerticalPanelView') if self.border: - flags.append("Margins-" + str(self.border[0]) + "-" + str(self.border[1]) + "-" - + str(self.border[2]) + "-" + str(self.border[3])) + flags.append('Margins-' + str(self.border[0]) + '-' + str(self.border[1]) + '-' + + str(self.border[2]) + '-' + str(self.border[3])) if forcepng: - filename += ".png" - self.image.save(filename, "PNG", optimize=1) + filename += '.png' + self.image.save(filename, 'PNG', optimize=1) else: - filename += ".jpg" - self.image.save(filename, "JPEG", optimize=1) + filename += '.jpg' + self.image.save(filename, 'JPEG', optimize=1, quality=80) return [md5Checksum(filename), flags] else: return None @@ -243,7 +243,7 @@ class ComicPage: if self.image.size[0] <= size[0] and self.image.size[1] <= size[1]: method = Image.BICUBIC else: - method = Image.ANTIALIAS + method = Image.LANCZOS self.image = self.image.resize(size, method) return self.image # If image is smaller than target resolution and upscale is off - Just expand it by adding margins @@ -269,7 +269,7 @@ class ComicPage: if self.image.size[0] <= size[0] and self.image.size[1] <= size[1]: method = Image.BICUBIC else: - method = Image.ANTIALIAS + method = Image.LANCZOS self.image = ImageOps.fit(self.image, size, method=method, centering=(0.5, 0.5)) return self.image @@ -279,7 +279,7 @@ class ComicPage: # Only split if origin is not oriented the same as target if (width > height) != (dstwidth > dstheight): if rotate: - self.image = self.image.rotate(90) + self.image = self.image.rotate(90, Image.BICUBIC, True) self.rotated = True return None else: @@ -292,9 +292,9 @@ class ComicPage: # Source is portrait and target is landscape, so split by the height leftbox = (0, 0, width, int(height / 2)) rightbox = (0, int(height / 2), width, height) - filename = os.path.splitext(self.filename) - fileone = targetdir + '/' + filename[0] + '-A' + filename[1] - filetwo = targetdir + '/' + filename[0] + '-B' + filename[1] + filename = os.path.splitext(self.filename)[0] + fileone = targetdir + '/' + filename + '-AAA.png' + filetwo = targetdir + '/' + filename + '-BBB.png' try: if righttoleft: pageone = self.image.crop(rightbox) @@ -302,8 +302,8 @@ class ComicPage: else: pageone = self.image.crop(leftbox) pagetwo = self.image.crop(rightbox) - pageone.save(fileone) - pagetwo.save(filetwo) + pageone.save(fileone, 'PNG', optimize=1) + pagetwo.save(filetwo, 'PNG', optimize=1) except IOError as e: raise RuntimeError('Cannot write image in directory %s: %s' % (targetdir, e)) return fileone, filetwo @@ -498,7 +498,7 @@ class Cover: def processExternal(self): self.image = self.image.convert('RGB') - self.image.thumbnail(self.options.profileData[1], Image.ANTIALIAS) + self.image.thumbnail(self.options.profileData[1], Image.LANCZOS) self.save(True) def trim(self): @@ -520,6 +520,6 @@ class Cover: if os.path.splitext(source)[1].lower() == '.png': self.image.save(self.target, "PNG", optimize=1) else: - self.image.save(self.target, "JPEG", optimize=1) + self.image.save(self.target, "JPEG", optimize=1, quality=80) except IOError: raise RuntimeError('Failed to save cover') diff --git a/kcc/shared.py b/kcc/shared.py index 7ac5163..418abf1 100644 --- a/kcc/shared.py +++ b/kcc/shared.py @@ -25,17 +25,11 @@ from hashlib import md5 def getImageFileName(imgfile): - filename = os.path.splitext(imgfile) - if filename[0].startswith('.') or\ - (filename[1].lower() != '.png' and - filename[1].lower() != '.jpg' and - filename[1].lower() != '.gif' and - filename[1].lower() != '.tif' and - filename[1].lower() != '.tiff' and - filename[1].lower() != '.bmp' and - filename[1].lower() != '.jpeg'): + name, ext = os.path.splitext(imgfile) + ext = ext.lower() + if name.startswith('.') or (ext != '.png' and ext != '.jpg' and ext != '.jpeg' and ext != '.gif'): return None - return filename + return [name, ext] def walkLevel(some_dir, level=1): From 2768e622f2d5253c570d86963b0d9538afdd9de1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jastrz=C4=99bski?= Date: Fri, 2 Jan 2015 11:51:14 +0100 Subject: [PATCH 05/12] PyQT 5.4 workarounds --- KCC-Linux.ui | 9 +++++++++ KCC-OSX.ui | 9 +++++++++ KCC.ui | 9 +++++++++ kcc/KCC_ui.py | 3 +++ kcc/KCC_ui_linux.py | 3 +++ kcc/KCC_ui_osx.py | 3 +++ 6 files changed, 36 insertions(+) diff --git a/KCC-Linux.ui b/KCC-Linux.ui index 727d3e4..7c41928 100644 --- a/KCC-Linux.ui +++ b/KCC-Linux.ui @@ -445,6 +445,9 @@ 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} + + Qt::ScrollBarAlwaysOn + false @@ -457,6 +460,12 @@ 18 + + QAbstractItemView::ScrollPerPixel + + + QAbstractItemView::ScrollPerPixel + diff --git a/KCC-OSX.ui b/KCC-OSX.ui index da3690a..e73c93d 100644 --- a/KCC-OSX.ui +++ b/KCC-OSX.ui @@ -450,12 +450,21 @@ 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} + + Qt::ScrollBarAlwaysOn + false QAbstractItemView::NoSelection + + QAbstractItemView::ScrollPerPixel + + + QAbstractItemView::ScrollPerPixel + diff --git a/KCC.ui b/KCC.ui index 15a9443..883a351 100644 --- a/KCC.ui +++ b/KCC.ui @@ -385,12 +385,21 @@ 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} + + Qt::ScrollBarAlwaysOn + false QAbstractItemView::NoSelection + + QAbstractItemView::ScrollPerPixel + + + QAbstractItemView::ScrollPerPixel + diff --git a/kcc/KCC_ui.py b/kcc/KCC_ui.py index c8c6f47..dd36744 100644 --- a/kcc/KCC_ui.py +++ b/kcc/KCC_ui.py @@ -138,6 +138,9 @@ class Ui_KCC(object): self.JobList = QtWidgets.QListWidget(self.Form) self.JobList.setGeometry(QtCore.QRect(10, 50, 401, 101)) self.JobList.setFocusPolicy(QtCore.Qt.NoFocus) + self.JobList.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel) + self.JobList.setHorizontalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel) + self.JobList.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) self.JobList.setStyleSheet("QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}") self.JobList.setProperty("showDropIndicator", False) self.JobList.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection) diff --git a/kcc/KCC_ui_linux.py b/kcc/KCC_ui_linux.py index 009977c..d077804 100644 --- a/kcc/KCC_ui_linux.py +++ b/kcc/KCC_ui_linux.py @@ -178,6 +178,9 @@ class Ui_KCC(object): font.setItalic(False) self.JobList.setFont(font) self.JobList.setFocusPolicy(QtCore.Qt.NoFocus) + self.JobList.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel) + self.JobList.setHorizontalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel) + self.JobList.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) self.JobList.setStyleSheet("QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}") self.JobList.setProperty("showDropIndicator", False) self.JobList.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection) diff --git a/kcc/KCC_ui_osx.py b/kcc/KCC_ui_osx.py index 09fed61..fb12b70 100644 --- a/kcc/KCC_ui_osx.py +++ b/kcc/KCC_ui_osx.py @@ -185,6 +185,9 @@ class Ui_KCC(object): font.setPointSize(11) self.JobList.setFont(font) self.JobList.setFocusPolicy(QtCore.Qt.NoFocus) + self.JobList.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel) + self.JobList.setHorizontalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel) + self.JobList.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) self.JobList.setStyleSheet("QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}") self.JobList.setProperty("showDropIndicator", False) self.JobList.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection) From 180123fee2640fe9639249dd01f0f4decda6af73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jastrz=C4=99bski?= Date: Sat, 3 Jan 2015 09:17:00 +0100 Subject: [PATCH 06/12] Improved 7zip detection --- kcc/cbxarchive.py | 3 ++- kcc/shared.py | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/kcc/cbxarchive.py b/kcc/cbxarchive.py index 216c1fa..6a7c598 100644 --- a/kcc/cbxarchive.py +++ b/kcc/cbxarchive.py @@ -27,6 +27,7 @@ from subprocess import STDOUT, PIPE from psutil import Popen from shutil import move, copy from . import rarfile +from .shared import check7ZFile as is_7zfile class CBxArchive: @@ -36,7 +37,7 @@ class CBxArchive: self.compressor = 'zip' elif rarfile.is_rarfile(origFileName): self.compressor = 'rar' - elif origFileName.endswith('.7z') or origFileName.endswith('.cb7'): + elif is_7zfile(origFileName): self.compressor = '7z' else: self.compressor = None diff --git a/kcc/shared.py b/kcc/shared.py index 418abf1..dbbdd44 100644 --- a/kcc/shared.py +++ b/kcc/shared.py @@ -52,3 +52,9 @@ def md5Checksum(filePath): break m.update(data) return m.hexdigest() + + +def check7ZFile(filePath): + with open(filePath, 'rb') as fh: + header = fh.read(6) + return header == b"7z\xbc\xaf'\x1c" \ No newline at end of file From 147d815057a5d0dfbeab2de54e7f9730f72dce13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jastrz=C4=99bski?= Date: Sat, 3 Jan 2015 09:41:07 +0100 Subject: [PATCH 07/12] Code cleanup --- LICENSE.txt | 2 +- kcc-c2e.py | 39 ++------------ kcc-c2p.py | 29 ++-------- kcc.iss | 2 +- kcc.py | 124 +++++-------------------------------------- kcc/KCC_gui.py | 80 +++++++++++++++++++++------- kcc/__init__.py | 2 +- kcc/cbxarchive.py | 4 +- kcc/comic2ebook.py | 4 +- kcc/comic2panel.py | 4 +- kcc/dualmetafix.py | 2 +- kcc/image.py | 4 +- kcc/pdfjpgextract.py | 4 +- kcc/shared.py | 61 +++++++++++++++++++-- setup.py | 4 +- 15 files changed, 157 insertions(+), 208 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index c32421a..b0eadda 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,7 +1,7 @@ ISC LICENSE Copyright (c) 2012-2014 Ciro Mattia Gonano -Copyright (c) 2013-2014 Paweł Jastrzębski +Copyright (c) 2013-2015 Paweł Jastrzębski Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the diff --git a/kcc-c2e.py b/kcc-c2e.py index bbc22b2..5bc3680 100755 --- a/kcc-c2e.py +++ b/kcc-c2e.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- # # Copyright (c) 2012-2014 Ciro Mattia Gonano -# Copyright (c) 2013-2014 Pawel Jastrzebski +# Copyright (c) 2013-2015 Pawel Jastrzebski # # Permission to use, copy, modify, and/or distribute this software for # any purpose with or without fee is hereby granted, provided that the @@ -20,7 +20,7 @@ __version__ = '4.3.1' __license__ = 'ISC' -__copyright__ = '2012-2014, Ciro Mattia Gonano , Pawel Jastrzebski ' +__copyright__ = '2012-2015, Ciro Mattia Gonano , Pawel Jastrzebski ' __docformat__ = 'restructuredtext en' import sys @@ -28,39 +28,8 @@ if sys.version_info[0] != 3: print('ERROR: This is Python 3 script!') exit(1) -# Dependency check -missing = [] -try: - # noinspection PyUnresolvedReferences - import psutil - if tuple(map(int, ('2.0.0'.split(".")))) > tuple(map(int, psutil.version_info)): - missing.append('psutil 2.0.0+') -except ImportError: - missing.append('psutil 2.0.0+') -try: - # noinspection PyUnresolvedReferences - import PIL - if tuple(map(int, ('2.7.0'.split(".")))) > tuple(map(int, (PIL.PILLOW_VERSION.split(".")))): - missing.append('Pillow 2.7.0+') -except ImportError: - missing.append('Pillow 2.7.0+') -try: - # noinspection PyUnresolvedReferences - import slugify -except ImportError: - missing.append('python-slugify') -if len(missing) > 0: - try: - # noinspection PyUnresolvedReferences - import tkinter - # noinspection PyUnresolvedReferences - import tkinter.messagebox - importRoot = tkinter.Tk() - importRoot.withdraw() - tkinter.messagebox.showerror('KCC - Error', 'ERROR: ' + ', '.join(missing) + ' is not installed!') - except ImportError: - print('ERROR: ' + ', '.join(missing) + ' is not installed!') - exit(1) +from kcc.shared import dependencyCheck +dependencyCheck(2) from multiprocessing import freeze_support from kcc.comic2ebook import main diff --git a/kcc-c2p.py b/kcc-c2p.py index 7388f7f..53216a4 100755 --- a/kcc-c2p.py +++ b/kcc-c2p.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- # # Copyright (c) 2012-2014 Ciro Mattia Gonano -# Copyright (c) 2013-2014 Pawel Jastrzebski +# Copyright (c) 2013-2015 Pawel Jastrzebski # # Permission to use, copy, modify, and/or distribute this software for # any purpose with or without fee is hereby granted, provided that the @@ -20,7 +20,7 @@ __version__ = '4.3.1' __license__ = 'ISC' -__copyright__ = '2012-2014, Ciro Mattia Gonano , Pawel Jastrzebski ' +__copyright__ = '2012-2015, Ciro Mattia Gonano , Pawel Jastrzebski ' __docformat__ = 'restructuredtext en' import sys @@ -28,33 +28,14 @@ if sys.version_info[0] != 3: print('ERROR: This is Python 3 script!') exit(1) -# Dependency check -missing = [] -try: - # noinspection PyUnresolvedReferences - import PIL - if tuple(map(int, ('2.7.0'.split(".")))) > tuple(map(int, (PIL.PILLOW_VERSION.split(".")))): - missing.append('Pillow 2.7.0+') -except ImportError: - missing.append('Pillow 2.7.0+') -if len(missing) > 0: - try: - # noinspection PyUnresolvedReferences - import tkinter - # noinspection PyUnresolvedReferences - import tkinter.messagebox - importRoot = tkinter.Tk() - importRoot.withdraw() - tkinter.messagebox.showerror('KCC - Error', 'ERROR: ' + ', '.join(missing) + ' is not installed!') - except ImportError: - print('ERROR: ' + ', '.join(missing) + ' is not installed!') - exit(1) +from kcc.shared import dependencyCheck +dependencyCheck(1) from multiprocessing import freeze_support from kcc.comic2panel import main if __name__ == "__main__": freeze_support() - print(('comic2ebook v%(__version__)s. Written by Ciro Mattia Gonano and Pawel Jastrzebski.' % globals())) + print(('comic2panel v%(__version__)s. Written by Ciro Mattia Gonano and Pawel Jastrzebski.' % globals())) main(sys.argv[1:]) sys.exit(0) \ No newline at end of file diff --git a/kcc.iss b/kcc.iss index f40959d..f05ab56 100644 --- a/kcc.iss +++ b/kcc.iss @@ -12,7 +12,7 @@ AppPublisher={#MyAppPublisher} AppPublisherURL={#MyAppURL} AppSupportURL={#MyAppURL} AppUpdatesURL={#MyAppURL} -AppCopyright=Copyright (C) 2012-2014 Ciro Mattia Gonano and Paweł Jastrzębski +AppCopyright=Copyright (C) 2012-2015 Ciro Mattia Gonano and Paweł Jastrzębski DefaultDirName={pf}\{#MyAppName} DefaultGroupName={#MyAppName} AllowNoIcons=yes diff --git a/kcc.py b/kcc.py index f7fc51f..119cd13 100755 --- a/kcc.py +++ b/kcc.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- # # Copyright (c) 2012-2014 Ciro Mattia Gonano -# Copyright (c) 2013-2014 Pawel Jastrzebski +# Copyright (c) 2013-2015 Pawel Jastrzebski # # Permission to use, copy, modify, and/or distribute this software for # any purpose with or without fee is hereby granted, provided that the @@ -20,16 +20,16 @@ __version__ = '4.3.1' __license__ = 'ISC' -__copyright__ = '2012-2014, Ciro Mattia Gonano , Pawel Jastrzebski ' +__copyright__ = '2012-2015, Ciro Mattia Gonano , Pawel Jastrzebski ' __docformat__ = 'restructuredtext en' import sys -import os if sys.version_info[0] != 3: print('ERROR: This is Python 3 script!') exit(1) # OS specific PATH variable workarounds +import os if sys.platform.startswith('darwin') and 'RESOURCEPATH' not in os.environ: os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + '/other/:' + os.environ['PATH'] elif sys.platform.startswith('win'): @@ -49,123 +49,23 @@ elif sys.platform.startswith('win'): os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + '/other/;' + os.environ['PATH'] os.chdir(os.path.dirname(os.path.abspath(__file__))) -# Dependency check -missing = [] -try: - # noinspection PyUnresolvedReferences - from PyQt5 import QtCore, QtNetwork, QtWidgets - if tuple(map(int, ('5.2.0'.split(".")))) > tuple(map(int, (QtCore.qVersion().split(".")))): - missing.append('PyQt5 5.2.0+') -except ImportError: - missing.append('PyQt5 5.2.0+') -try: - # noinspection PyUnresolvedReferences - import psutil - if tuple(map(int, ('2.0.0'.split(".")))) > tuple(map(int, psutil.version_info)): - missing.append('psutil 2.0.0+') -except ImportError: - missing.append('psutil 2.0.0+') -try: - # noinspection PyUnresolvedReferences - import PIL - if tuple(map(int, ('2.7.0'.split(".")))) > tuple(map(int, (PIL.PILLOW_VERSION.split(".")))): - missing.append('Pillow 2.7.0+') -except ImportError: - missing.append('Pillow 2.7.0+') -try: - # noinspection PyUnresolvedReferences - import slugify -except ImportError: - missing.append('python-slugify') -if len(missing) > 0: - try: - # noinspection PyUnresolvedReferences - import tkinter - # noinspection PyUnresolvedReferences - import tkinter.messagebox - importRoot = tkinter.Tk() - importRoot.withdraw() - tkinter.messagebox.showerror('KCC - Error', 'ERROR: ' + ', '.join(missing) + ' is not installed!') - except ImportError: - print('ERROR: ' + ', '.join(missing) + ' is not installed!') - exit(1) +from kcc.shared import dependencyCheck +dependencyCheck(3) from multiprocessing import freeze_support from kcc import KCC_gui - -# Implementing detection of already running KCC instance and forwarding argv to it -class QApplicationMessaging(QtWidgets.QApplication): - messageFromOtherInstance = QtCore.pyqtSignal(bytes) - - def __init__(self, argv): - QtWidgets.QApplication.__init__(self, argv) - self._key = 'KCC' - self._timeout = 1000 - self._locked = False - socket = QtNetwork.QLocalSocket(self) - socket.connectToServer(self._key, QtCore.QIODevice.WriteOnly) - if not socket.waitForConnected(self._timeout): - self._server = QtNetwork.QLocalServer(self) - # noinspection PyUnresolvedReferences - self._server.newConnection.connect(self.handleMessage) - self._server.listen(self._key) - else: - self._locked = True - socket.disconnectFromServer() - - def __del__(self): - if not self._locked: - self._server.close() - - def event(self, e): - if e.type() == QtCore.QEvent.FileOpen: - self.messageFromOtherInstance.emit(bytes(e.file(), 'UTF-8')) - return True - else: - return QtWidgets.QApplication.event(self, e) - - def isRunning(self): - return self._locked - - def handleMessage(self): - socket = self._server.nextPendingConnection() - if socket.waitForReadyRead(self._timeout): - self.messageFromOtherInstance.emit(socket.readAll().data()) - - def sendMessage(self, message): - socket = QtNetwork.QLocalSocket(self) - socket.connectToServer(self._key, QtCore.QIODevice.WriteOnly) - socket.waitForConnected(self._timeout) - socket.write(bytes(message, 'UTF-8')) - socket.waitForBytesWritten(self._timeout) - socket.disconnectFromServer() - - -# Adding signals to QMainWindow -class QMainWindowKCC(QtWidgets.QMainWindow): - progressBarTick = QtCore.pyqtSignal(str) - modeConvert = QtCore.pyqtSignal(int) - addMessage = QtCore.pyqtSignal(str, str, bool) - addTrayMessage = QtCore.pyqtSignal(str, str) - showDialog = QtCore.pyqtSignal(str, str) - hideProgressBar = QtCore.pyqtSignal() - forceShutdown = QtCore.pyqtSignal() - dialogAnswer = QtCore.pyqtSignal(int) - - if __name__ == "__main__": freeze_support() - KCCAplication = QApplicationMessaging(sys.argv) + KCCAplication = KCC_gui.QApplicationMessaging(sys.argv) if KCCAplication.isRunning(): if len(sys.argv) > 1: KCCAplication.sendMessage(sys.argv[1]) - sys.exit(0) else: KCCAplication.sendMessage('ARISE') - sys.exit(0) - KCCWindow = QMainWindowKCC() - KCCUI = KCC_gui.KCCGUI(KCCAplication, KCCWindow) - if len(sys.argv) > 1: - KCCUI.handleMessage(sys.argv[1]) - sys.exit(KCCAplication.exec_()) + else: + KCCWindow = KCC_gui.QMainWindowKCC() + KCCUI = KCC_gui.KCCGUI(KCCAplication, KCCWindow) + if len(sys.argv) > 1: + KCCUI.handleMessage(sys.argv[1]) + sys.exit(KCCAplication.exec_()) diff --git a/kcc/KCC_gui.py b/kcc/KCC_gui.py index 9e18389..42eb9b9 100644 --- a/kcc/KCC_gui.py +++ b/kcc/KCC_gui.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # Copyright (c) 2012-2014 Ciro Mattia Gonano -# Copyright (c) 2013-2014 Pawel Jastrzebski +# Copyright (c) 2013-2015 Pawel Jastrzebski # # Permission to use, copy, modify, and/or distribute this software for # any purpose with or without fee is hereby granted, provided that the @@ -19,7 +19,7 @@ __version__ = '4.3.1' __license__ = 'ISC' -__copyright__ = '2012-2014, Ciro Mattia Gonano , Pawel Jastrzebski ' +__copyright__ = '2012-2015, Ciro Mattia Gonano , Pawel Jastrzebski ' __docformat__ = 'restructuredtext en' import os @@ -33,12 +33,11 @@ from shutil import move from http.server import BaseHTTPRequestHandler, HTTPServer from socketserver import ThreadingMixIn from subprocess import STDOUT, PIPE -from PyQt5 import QtGui, QtCore, QtWidgets +from PyQt5 import QtGui, QtCore, QtWidgets, QtNetwork from xml.dom.minidom import parse -from html.parser import HTMLParser from psutil import Popen, Process from copy import copy -from .shared import md5Checksum +from .shared import md5Checksum, HTMLStripper from . import comic2ebook from . import KCC_rc_web if sys.platform.startswith('darwin'): @@ -49,6 +48,64 @@ else: from . import KCC_ui +class QApplicationMessaging(QtWidgets.QApplication): + messageFromOtherInstance = QtCore.pyqtSignal(bytes) + + def __init__(self, argv): + QtWidgets.QApplication.__init__(self, argv) + self._key = 'KCC' + self._timeout = 1000 + self._locked = False + socket = QtNetwork.QLocalSocket(self) + socket.connectToServer(self._key, QtCore.QIODevice.WriteOnly) + if not socket.waitForConnected(self._timeout): + self._server = QtNetwork.QLocalServer(self) + # noinspection PyUnresolvedReferences + self._server.newConnection.connect(self.handleMessage) + self._server.listen(self._key) + else: + self._locked = True + socket.disconnectFromServer() + + def __del__(self): + if not self._locked: + self._server.close() + + def event(self, e): + if e.type() == QtCore.QEvent.FileOpen: + self.messageFromOtherInstance.emit(bytes(e.file(), 'UTF-8')) + return True + else: + return QtWidgets.QApplication.event(self, e) + + def isRunning(self): + return self._locked + + def handleMessage(self): + socket = self._server.nextPendingConnection() + if socket.waitForReadyRead(self._timeout): + self.messageFromOtherInstance.emit(socket.readAll().data()) + + def sendMessage(self, message): + socket = QtNetwork.QLocalSocket(self) + socket.connectToServer(self._key, QtCore.QIODevice.WriteOnly) + socket.waitForConnected(self._timeout) + socket.write(bytes(message, 'UTF-8')) + socket.waitForBytesWritten(self._timeout) + socket.disconnectFromServer() + + +class QMainWindowKCC(QtWidgets.QMainWindow): + progressBarTick = QtCore.pyqtSignal(str) + modeConvert = QtCore.pyqtSignal(int) + addMessage = QtCore.pyqtSignal(str, str, bool) + addTrayMessage = QtCore.pyqtSignal(str, str) + showDialog = QtCore.pyqtSignal(str, str) + hideProgressBar = QtCore.pyqtSignal() + forceShutdown = QtCore.pyqtSignal() + dialogAnswer = QtCore.pyqtSignal(int) + + class Icons: def __init__(self): self.deviceKindle = QtGui.QIcon() @@ -76,19 +133,6 @@ class Icons: self.programIcon.addPixmap(QtGui.QPixmap(":/Icon/icons/comic2ebook.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) -class HTMLStripper(HTMLParser): - def __init__(self): - HTMLParser.__init__(self) - self.reset() - self.fed = [] - - def handle_data(self, d): - self.fed.append(d) - - def get_data(self): - return ''.join(self.fed) - - class WebServerHandler(BaseHTTPRequestHandler): # noinspection PyAttributeOutsideInit, PyArgumentList def do_GET(self): diff --git a/kcc/__init__.py b/kcc/__init__.py index 49174f8..72fa985 100644 --- a/kcc/__init__.py +++ b/kcc/__init__.py @@ -1,4 +1,4 @@ __version__ = '4.3.1' __license__ = 'ISC' -__copyright__ = '2012-2014, Ciro Mattia Gonano , Pawel Jastrzebski ' +__copyright__ = '2012-2015, Ciro Mattia Gonano , Pawel Jastrzebski ' __docformat__ = 'restructuredtext en' \ No newline at end of file diff --git a/kcc/cbxarchive.py b/kcc/cbxarchive.py index 6a7c598..cdca253 100644 --- a/kcc/cbxarchive.py +++ b/kcc/cbxarchive.py @@ -1,5 +1,5 @@ # Copyright (c) 2012-2014 Ciro Mattia Gonano -# Copyright (c) 2013-2014 Pawel Jastrzebski +# Copyright (c) 2013-2015 Pawel Jastrzebski # # 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 +17,7 @@ # __license__ = 'ISC' -__copyright__ = '2012-2014, Ciro Mattia Gonano , Pawel Jastrzebski ' +__copyright__ = '2012-2015, Ciro Mattia Gonano , Pawel Jastrzebski ' __docformat__ = 'restructuredtext en' import sys diff --git a/kcc/comic2ebook.py b/kcc/comic2ebook.py index 7401e45..dfd0702 100755 --- a/kcc/comic2ebook.py +++ b/kcc/comic2ebook.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # Copyright (c) 2012-2014 Ciro Mattia Gonano -# Copyright (c) 2013-2014 Pawel Jastrzebski +# Copyright (c) 2013-2015 Pawel Jastrzebski # # Permission to use, copy, modify, and/or distribute this software for # any purpose with or without fee is hereby granted, provided that the @@ -20,7 +20,7 @@ __version__ = '4.3.1' __license__ = 'ISC' -__copyright__ = '2012-2014, Ciro Mattia Gonano , Pawel Jastrzebski ' +__copyright__ = '2012-2015, Ciro Mattia Gonano , Pawel Jastrzebski ' __docformat__ = 'restructuredtext en' import os diff --git a/kcc/comic2panel.py b/kcc/comic2panel.py index 3b42258..22c783f 100644 --- a/kcc/comic2panel.py +++ b/kcc/comic2panel.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # Copyright (c) 2012-2014 Ciro Mattia Gonano -# Copyright (c) 2013-2014 Pawel Jastrzebski +# Copyright (c) 2013-2015 Pawel Jastrzebski # # Permission to use, copy, modify, and/or distribute this software for # any purpose with or without fee is hereby granted, provided that the @@ -20,7 +20,7 @@ __version__ = '4.3.1' __license__ = 'ISC' -__copyright__ = '2012-2014, Ciro Mattia Gonano , Pawel Jastrzebski ' +__copyright__ = '2012-2015, Ciro Mattia Gonano , Pawel Jastrzebski ' __docformat__ = 'restructuredtext en' import os diff --git a/kcc/dualmetafix.py b/kcc/dualmetafix.py index 1c80b58..5889d68 100644 --- a/kcc/dualmetafix.py +++ b/kcc/dualmetafix.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # Based on initial version of DualMetaFix. Copyright (C) 2013 Kevin Hendricks -# Changes for KCC Copyright (C) 2014 Pawel Jastrzebski +# Changes for KCC Copyright (C) 2014-2015 Pawel Jastrzebski # # 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 diff --git a/kcc/image.py b/kcc/image.py index 212feda..9eff741 100755 --- a/kcc/image.py +++ b/kcc/image.py @@ -1,7 +1,7 @@ # Copyright (C) 2010 Alex Yatskov # Copyright (C) 2011 Stanislav (proDOOMman) Kosolapov # Copyright (c) 2012-2014 Ciro Mattia Gonano -# Copyright (c) 2013-2014 Pawel Jastrzebski +# Copyright (c) 2013-2015 Pawel Jastrzebski # # 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 @@ -18,7 +18,7 @@ __version__ = '4.3.1' __license__ = 'ISC' -__copyright__ = '2012-2014, Ciro Mattia Gonano , Pawel Jastrzebski ' +__copyright__ = '2012-2015, Ciro Mattia Gonano , Pawel Jastrzebski ' __docformat__ = 'restructuredtext en' import os diff --git a/kcc/pdfjpgextract.py b/kcc/pdfjpgextract.py index 4531fa7..7ebae06 100644 --- a/kcc/pdfjpgextract.py +++ b/kcc/pdfjpgextract.py @@ -1,5 +1,5 @@ # Copyright (c) 2012-2014 Ciro Mattia Gonano -# Copyright (c) 2013-2014 Pawel Jastrzebski +# Copyright (c) 2013-2015 Pawel Jastrzebski # # Based upon the code snippet by Ned Batchelder # (http://nedbatchelder.com/blog/200712/extracting_jpgs_from_pdfs.html) @@ -20,7 +20,7 @@ # __license__ = 'ISC' -__copyright__ = '2012-2014, Ciro Mattia Gonano , Pawel Jastrzebski ' +__copyright__ = '2012-2015, Ciro Mattia Gonano , Pawel Jastrzebski ' __docformat__ = 'restructuredtext en' import os diff --git a/kcc/shared.py b/kcc/shared.py index dbbdd44..b8c7334 100644 --- a/kcc/shared.py +++ b/kcc/shared.py @@ -1,5 +1,5 @@ # Copyright (c) 2012-2014 Ciro Mattia Gonano -# Copyright (c) 2013-2014 Pawel Jastrzebski +# Copyright (c) 2013-2015 Pawel Jastrzebski # # Permission to use, copy, modify, and/or distribute this software for # any purpose with or without fee is hereby granted, provided that the @@ -17,11 +17,27 @@ # __license__ = 'ISC' -__copyright__ = '2012-2014, Ciro Mattia Gonano , Pawel Jastrzebski ' +__copyright__ = '2012-2015, Ciro Mattia Gonano , Pawel Jastrzebski ' __docformat__ = 'restructuredtext en' import os from hashlib import md5 +from html.parser import HTMLParser + + +class HTMLStripper(HTMLParser): + def __init__(self): + HTMLParser.__init__(self) + self.reset() + self.strict = False + self.convert_charrefs = True + self.fed = [] + + def handle_data(self, d): + self.fed.append(d) + + def get_data(self): + return ''.join(self.fed) def getImageFileName(imgfile): @@ -57,4 +73,43 @@ def md5Checksum(filePath): def check7ZFile(filePath): with open(filePath, 'rb') as fh: header = fh.read(6) - return header == b"7z\xbc\xaf'\x1c" \ No newline at end of file + return header == b"7z\xbc\xaf'\x1c" + + +# noinspection PyUnresolvedReferences +def dependencyCheck(level): + missing = [] + if level > 2: + try: + from PyQt5 import QtCore, QtNetwork, QtWidgets + if tuple(map(int, ('5.2.0'.split(".")))) > tuple(map(int, (QtCore.qVersion().split(".")))): + missing.append('PyQt5 5.2.0+') + except ImportError: + missing.append('PyQt5 5.2.0+') + if level > 1: + try: + import psutil + if tuple(map(int, ('2.0.0'.split(".")))) > tuple(map(int, psutil.version_info)): + missing.append('psutil 2.0.0+') + except ImportError: + missing.append('psutil 2.0.0+') + try: + import slugify + except ImportError: + missing.append('python-slugify') + try: + import PIL + if tuple(map(int, ('2.7.0'.split(".")))) > tuple(map(int, (PIL.PILLOW_VERSION.split(".")))): + missing.append('Pillow 2.7.0+') + except ImportError: + missing.append('Pillow 2.7.0+') + if len(missing) > 0: + try: + import tkinter + import tkinter.messagebox + importRoot = tkinter.Tk() + importRoot.withdraw() + tkinter.messagebox.showerror('KCC - Error', 'ERROR: ' + ', '.join(missing) + ' is not installed!') + except ImportError: + print('ERROR: ' + ', '.join(missing) + ' is not installed!') + exit(1) \ No newline at end of file diff --git a/setup.py b/setup.py index 9476d3e..99bd3f5 100755 --- a/setup.py +++ b/setup.py @@ -33,7 +33,7 @@ if platform == "darwin": CFBundleName=NAME, CFBundleShortVersionString=VERSION, CFBundleGetInfoString=NAME + " " + VERSION + - ", written 2012-2014 by Ciro Mattia Gonano and Pawel Jastrzebski", + ", written 2012-2015 by Ciro Mattia Gonano and Pawel Jastrzebski", CFBundleExecutable=NAME, CFBundleIdentifier='com.github.ciromattia.kcc', CFBundleSignature='dplt', @@ -81,7 +81,7 @@ elif platform == "win32": windows=[{"script": MAIN, "dest_base": "KCC", "version": VERSION, - "copyright": "Ciro Mattia Gonano, Pawel Jastrzebski © 2014", + "copyright": "Ciro Mattia Gonano, Pawel Jastrzebski © 2012-2015", "legal_copyright": "ISC License (ISCL)", "product_version": VERSION, "product_name": "Kindle Comic Converter", From b9276e9edec837f27d7bf156e3b5ed18eed78fb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jastrz=C4=99bski?= Date: Sun, 4 Jan 2015 09:11:46 +0100 Subject: [PATCH 08/12] WebToon processing improvements --- kcc/comic2ebook.py | 12 ++++++++---- kcc/comic2panel.py | 38 ++++++++++++++++++++------------------ 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/kcc/comic2ebook.py b/kcc/comic2ebook.py index dfd0702..98feb17 100755 --- a/kcc/comic2ebook.py +++ b/kcc/comic2ebook.py @@ -824,11 +824,15 @@ def splitProcess(path, mode): output = [] currentSize = 0 currentTarget = path + if options.webtoon: + targetSize = 104857600 + else: + targetSize = 419430400 if mode == 0: for root, dirs, files in walkLevel(path, 0): for name in files: size = os.path.getsize(os.path.join(root, name)) - if currentSize + size > 419430400: + if currentSize + size > targetSize: currentTarget, pathRoot = createNewTome() output.append(pathRoot) currentSize = size @@ -840,7 +844,7 @@ def splitProcess(path, mode): for root, dirs, files in walkLevel(path, 0): for name in dirs: size = getDirectorySize(os.path.join(root, name)) - if currentSize + size > 419430400: + if currentSize + size > targetSize: currentTarget, pathRoot = createNewTome() output.append(pathRoot) currentSize = size @@ -854,7 +858,7 @@ def splitProcess(path, mode): for name in dirs: size = getDirectorySize(os.path.join(root, name)) currentSize = 0 - if size > 419430400: + if size > targetSize: if not firstTome: currentTarget, pathRoot = createNewTome() output.append(pathRoot) @@ -863,7 +867,7 @@ def splitProcess(path, mode): for rootInside, dirsInside, filesInside in walkLevel(os.path.join(root, name), 0): for nameInside in dirsInside: size = getDirectorySize(os.path.join(rootInside, nameInside)) - if currentSize + size > 419430400: + if currentSize + size > targetSize: currentTarget, pathRoot = createNewTome() output.append(pathRoot) currentSize = size diff --git a/kcc/comic2panel.py b/kcc/comic2panel.py index 22c783f..16a88be 100644 --- a/kcc/comic2panel.py +++ b/kcc/comic2panel.py @@ -28,7 +28,7 @@ import sys from shutil import rmtree, copytree, move from optparse import OptionParser, OptionGroup from multiprocessing import Pool -from PIL import Image, ImageStat +from PIL import Image, ImageStat, ImageOps from .shared import getImageFileName, walkLevel try: from PyQt5 import QtCore @@ -50,9 +50,9 @@ def mergeDirectory(work): try: directory = work[0] images = [] - imagesClear = [] + imagesValid = [] sizes = [] - h = 0 + targetHeight = 0 for root, dirs, files in walkLevel(directory, 0): for name in files: if getImageFileName(name) is not None: @@ -60,31 +60,34 @@ def mergeDirectory(work): images.append([os.path.join(root, name), i.size[0], i.size[1]]) sizes.append(i.size[0]) if len(images) > 0: - mw = max(set(sizes), key=sizes.count) + targetWidth = max(set(sizes), key=sizes.count) for i in images: - if i[1] == mw: - h += i[2] - imagesClear.append(i[0]) + if i[1] <= targetWidth: + targetHeight += i[2] + imagesValid.append(i[0]) # Silently drop directories that contain too many images - if h > 262144: + # 131072 = GIMP_MAX_IMAGE_SIZE / 4 + if targetHeight > 131072: return None - result = Image.new('RGB', (mw, h)) + result = Image.new('RGB', (targetWidth, targetHeight)) y = 0 - for i in imagesClear: + for i in imagesValid: img = Image.open(i) img = img.convert('RGB') + if img.size[0] < targetWidth: + img = ImageOps.fit(img, (targetWidth, img.size[1]), method=Image.BICUBIC, centering=(0.5, 0.5)) result.paste(img, (0, y)) y += img.size[1] os.remove(i) - savePath = os.path.split(imagesClear[0]) - result.save(os.path.join(savePath[0], os.path.splitext(savePath[1])[0] + '.png'), 'PNG', optimize=1) + savePath = os.path.split(imagesValid[0]) + result.save(os.path.join(savePath[0], os.path.splitext(savePath[1])[0] + '.png'), 'PNG') except Exception: return str(sys.exc_info()[1]) def sanitizePanelSize(panel, opt): newPanels = [] - if panel[2] > 8 * opt.height: + if panel[2] > 6 * opt.height: diff = int(panel[2] / 8) newPanels.append([panel[0], panel[1] - diff*7, diff]) newPanels.append([panel[1] - diff*7, panel[1] - diff*6, diff]) @@ -94,13 +97,13 @@ def sanitizePanelSize(panel, opt): newPanels.append([panel[1] - diff*3, panel[1] - diff*2, diff]) newPanels.append([panel[1] - diff*2, panel[1] - diff, diff]) newPanels.append([panel[1] - diff, panel[1], diff]) - elif panel[2] > 4 * opt.height: + elif panel[2] > 3 * opt.height: diff = int(panel[2] / 4) 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 * opt.height: + elif panel[2] > 1.5 * opt.height: newPanels.append([panel[0], panel[1] - int(panel[2] / 2), int(panel[2] / 2)]) newPanels.append([panel[1] - int(panel[2] / 2), panel[1], int(panel[2] / 2)]) else: @@ -165,7 +168,7 @@ def splitImage(work): panels.append(panel) if opt.debug: # noinspection PyUnboundLocalVariable - debugImage.save(os.path.join(path, fileExpanded[0] + '-debug.png'), 'PNG', optimize=1) + debugImage.save(os.path.join(path, fileExpanded[0] + '-debug.png'), 'PNG') # Create virtual pages pages = [] @@ -199,8 +202,7 @@ def splitImage(work): panelImg = image.crop([0, panels[panel][0], widthImg, panels[panel][1]]) newPage.paste(panelImg, (0, targetHeight)) targetHeight += panels[panel][2] - newPage.save(os.path.join(path, fileExpanded[0] + '-' + - str(pageNumber) + '.png'), 'PNG', optimize=1) + newPage.save(os.path.join(path, fileExpanded[0] + '-' + str(pageNumber) + '.png'), 'PNG') pageNumber += 1 os.remove(filePath) except Exception: From 3187ebb0544716215bf421449ab3d42d91d09f0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jastrz=C4=99bski?= Date: Sun, 4 Jan 2015 09:13:20 +0100 Subject: [PATCH 09/12] Generic processing improvements --- kcc/comic2ebook.py | 32 ++++++++++++++++---------------- kcc/image.py | 45 +++++++++++++++++++++++++++++---------------- 2 files changed, 45 insertions(+), 32 deletions(-) diff --git a/kcc/comic2ebook.py b/kcc/comic2ebook.py index 98feb17..2a9aade 100755 --- a/kcc/comic2ebook.py +++ b/kcc/comic2ebook.py @@ -444,12 +444,12 @@ def imgOptimization(img, opt, hqImage=None): img.cropWhiteSpace() if opt.cutpagenumbers and not opt.webtoon: img.cutPageNumber() - img.optimizeImage(opt.gamma) + img.optimizeImage() if hqImage: - img.resizeImage(opt.upscale, opt.stretch, opt.bordersColor, 0) + img.resizeImage(0) img.calculateBorder(hqImage, True) else: - img.resizeImage(opt.upscale, opt.stretch, opt.bordersColor, opt.quality) + img.resizeImage() if opt.panelview: if opt.quality == 0: img.calculateBorder(img) @@ -515,7 +515,7 @@ def imgFileProcessing(work): dirpath = work[1] opt = work[2] output = [] - img = image.ComicPage(os.path.join(dirpath, afile), opt.profileData) + img = image.ComicPage(os.path.join(dirpath, afile), opt) if opt.quality == 2: wipe = False else: @@ -523,39 +523,39 @@ def imgFileProcessing(work): if opt.nosplitrotate: splitter = None else: - splitter = img.splitPage(dirpath, opt.righttoleft, opt.rotate) + splitter = img.splitPage(dirpath) if splitter is not None: - img0 = image.ComicPage(splitter[0], opt.profileData) + img0 = image.ComicPage(splitter[0], opt) imgOptimization(img0, opt) - output.append(img0.saveToDir(dirpath, opt.forcepng, opt.forcecolor)) - img1 = image.ComicPage(splitter[1], opt.profileData) + output.append(img0.saveToDir(dirpath)) + img1 = image.ComicPage(splitter[1], opt) imgOptimization(img1, opt) - output.append(img1.saveToDir(dirpath, opt.forcepng, opt.forcecolor)) + output.append(img1.saveToDir(dirpath)) if wipe: output.append(img0.origFileName) output.append(img1.origFileName) if opt.quality == 2: - img0b = image.ComicPage(splitter[0], opt.profileData, img0.fill) + img0b = image.ComicPage(splitter[0], opt, img0.fill) imgOptimization(img0b, opt, img0) - output.append(img0b.saveToDir(dirpath, opt.forcepng, opt.forcecolor)) - img1b = image.ComicPage(splitter[1], opt.profileData, img1.fill) + output.append(img0b.saveToDir(dirpath)) + img1b = image.ComicPage(splitter[1], opt, img1.fill) imgOptimization(img1b, opt, img1) - output.append(img1b.saveToDir(dirpath, opt.forcepng, opt.forcecolor)) + output.append(img1b.saveToDir(dirpath)) output.append(img0.origFileName) output.append(img1.origFileName) output.append(img.origFileName) else: imgOptimization(img, opt) - output.append(img.saveToDir(dirpath, opt.forcepng, opt.forcecolor)) + output.append(img.saveToDir(dirpath)) if wipe: output.append(img.origFileName) if opt.quality == 2: - img2 = image.ComicPage(os.path.join(dirpath, afile), opt.profileData, img.fill) + img2 = image.ComicPage(os.path.join(dirpath, afile), opt, img.fill) if img.rotated: img2.image = img2.image.rotate(90, Image.BICUBIC, True) img2.rotated = True imgOptimization(img2, opt, img) - output.append(img2.saveToDir(dirpath, opt.forcepng, opt.forcecolor)) + output.append(img2.saveToDir(dirpath)) output.append(img.origFileName) return output except Exception: diff --git a/kcc/image.py b/kcc/image.py index 9eff741..f8cc4af 100755 --- a/kcc/image.py +++ b/kcc/image.py @@ -102,16 +102,15 @@ class ProfileData: class ComicPage: - def __init__(self, source, device, fill=None): + def __init__(self, source, options, fill=None): try: - self.profile_label, self.size, self.palette, self.gamma, self.panelviewsize = device + self.profile_label, self.size, self.palette, self.gamma, self.panelviewsize = options.profileData except KeyError: - raise RuntimeError('Unexpected output device %s' % device) + raise RuntimeError('Unexpected output device %s' % options.profileData) self.origFileName = source self.filename = os.path.basename(self.origFileName) self.image = Image.open(source) self.image = self.image.convert('RGB') - self.color = self.isImageColor() self.rotated = None self.border = None self.noHPV = None @@ -119,17 +118,22 @@ class ComicPage: self.noPV = None self.purge = False self.hq = False + self.opt = options if fill: self.fill = fill else: self.fill = None + if options.webtoon: + self.color = True + else: + self.color = self.isImageColor() - def saveToDir(self, targetdir, forcepng, color): + def saveToDir(self, targetdir): try: if not self.purge: flags = [] filename = os.path.join(targetdir, os.path.splitext(self.filename)[0]) + '-KCC' - if not color and not forcepng: + if not self.opt.forcecolor and not self.opt.forcepng: self.image = self.image.convert('L') if self.rotated: flags.append('Rotated') @@ -146,7 +150,7 @@ class ComicPage: if self.border: flags.append('Margins-' + str(self.border[0]) + '-' + str(self.border[1]) + '-' + str(self.border[2]) + '-' + str(self.border[3])) - if forcepng: + if self.opt.forcepng: filename += '.png' self.image.save(filename, 'PNG', optimize=1) else: @@ -158,7 +162,8 @@ class ComicPage: except IOError as e: raise RuntimeError('Cannot write image in directory %s: %s' % (targetdir, e)) - def optimizeImage(self, gamma): + def optimizeImage(self): + gamma = self.opt.gamma if gamma < 0.1: gamma = self.gamma if self.gamma != 1.0 and self.color: @@ -215,7 +220,12 @@ class ComicPage: self.noHPV = True self.noVPV = True - def resizeImage(self, upscale=False, stretch=False, bordersColor=None, qualityMode=0): + def resizeImage(self, qualityMode=None): + upscale = self.opt.upscale + stretch = self.opt.stretch + bordersColor = self.opt.bordersColor + if qualityMode is None: + qualityMode = self.opt.quality if bordersColor: fill = bordersColor else: @@ -273,12 +283,12 @@ class ComicPage: self.image = ImageOps.fit(self.image, size, method=method, centering=(0.5, 0.5)) return self.image - def splitPage(self, targetdir, righttoleft=False, rotate=False): + def splitPage(self, targetdir): width, height = self.image.size dstwidth, dstheight = self.size # Only split if origin is not oriented the same as target if (width > height) != (dstwidth > dstheight): - if rotate: + if self.opt.rotate: self.image = self.image.rotate(90, Image.BICUBIC, True) self.rotated = True return None @@ -296,7 +306,7 @@ class ComicPage: fileone = targetdir + '/' + filename + '-AAA.png' filetwo = targetdir + '/' + filename + '-BBB.png' try: - if righttoleft: + if self.opt.righttoleft: pageone = self.image.crop(rightbox) pagetwo = self.image.crop(leftbox) else: @@ -417,13 +427,16 @@ class ComicPage: imageBoxB = ImageChops.invert(bw).getbbox() if imageBoxA is None or imageBoxB is None: surfaceB, surfaceW = 0, 0 + diff = 0 else: surfaceB = (imageBoxA[2] - imageBoxA[0]) * (imageBoxA[3] - imageBoxA[1]) surfaceW = (imageBoxB[2] - imageBoxB[0]) * (imageBoxB[3] - imageBoxB[1]) - if surfaceW < surfaceB: - self.fill = 'white' - elif surfaceW > surfaceB: - self.fill = 'black' + diff = ((max(surfaceB, surfaceW) - min(surfaceB, surfaceW)) / min(surfaceB, surfaceW)) * 100 + if diff > 0.5: + if surfaceW < surfaceB: + self.fill = 'white' + elif surfaceW > surfaceB: + self.fill = 'black' else: fill = 0 startY = 0 From 917eaef5484c070d0a392a14519f42c93a7d5a2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jastrz=C4=99bski?= Date: Sun, 4 Jan 2015 10:27:13 +0100 Subject: [PATCH 10/12] GUI tweaks --- KCC-Linux.ui | 24 +++++++++++++++--------- KCC-OSX.ui | 18 ++++++++++++------ KCC.ui | 14 ++++++++++---- kcc/KCC_gui.py | 2 +- kcc/KCC_ui.py | 20 +++++++++++--------- kcc/KCC_ui_linux.py | 30 ++++++++++++++++-------------- kcc/KCC_ui_osx.py | 24 +++++++++++++----------- 7 files changed, 78 insertions(+), 54 deletions(-) diff --git a/KCC-Linux.ui b/KCC-Linux.ui index 7c41928..edf8fa4 100644 --- a/KCC-Linux.ui +++ b/KCC-Linux.ui @@ -71,7 +71,7 @@ Qt::NoFocus - <html><head/><body><p style='white-space:pre'>Disable image optimizations.<br/>Input images must be already resized.</p></body></html> + <html><head/><body><p style='white-space:pre'>Disable image optimizations.<br/><span style=" font-weight:600;">Input images must be already resized.</span></p></body></html> No optimisation @@ -110,7 +110,7 @@ Qt::NoFocus - <html><head/><body><p>Enable auto-splitting of webtoons like <span style=" font-style:italic;">Tower of God</span> or <span style=" font-style:italic;">Noblesse</span>.<br/>This mode was created for pages with a low width, high height and vertical panel flow.</p></body></html> + <html><head/><body><p style='white-space:pre'>Enable special parsing mode for WebToons.</p></body></html> Webtoon mode @@ -167,7 +167,7 @@ Qt::NoFocus - <html><head/><body><p style='white-space:pre'>Disable splitting and rotation.</p></body></html> + <html><head/><body><p style='white-space:pre'>Disable page splitting and rotation.</p></body></html> No split/rotate @@ -241,7 +241,7 @@ Qt::NoFocus - <html><head/><body><p style='white-space:pre'>Shift+Click to select the output directory.</p></body></html> + <html><head/><body><p style='white-space:pre'>Shift+Click to select the output directory.</p></body></html> Convert @@ -269,6 +269,9 @@ Qt::NoFocus + + <html><head/><body><p style='white-space:pre'>Add directory containing JPG, PNG or GIF files to queue.<br/><span style=" font-weight:600;">CBR, CBZ and CB7 files inside will not be processed!</span></p></body></html> + Add directory @@ -295,6 +298,9 @@ Qt::NoFocus + + <html><head/><body><p style='white-space:pre'>Add CBR, CBZ, CB7 or PDF file to queue.</p></body></html> + Add file @@ -386,7 +392,7 @@ Qt::NoFocus - <html><head/><body><p><span style=" font-weight:600; text-decoration: underline;">Unchecked - Normal quality mode</span><br/>Maximal quality of images but very poor magnification quality.<br/>Use it only when zoom is not needed or output files needs to be small.</p><p><span style=" font-weight:600; text-decoration: underline;">Indeterminate - High quality mode</span><br/>In most cases high quality of images and magnification.<br/>Overall quality highly depends on the resolution of source files.<br/>On Kindle models older than Paperwhite non-zoomed images might be a little blurred.<br/><br/><span style=" font-weight:600; text-decoration: underline;">Checked - Ultra quality mode</span><br/>Highest possible quality. Output files will be big.</p></body></html> + <html><head/><body><p style='white-space:pre'>Quality of Panel View/zoom. Highly impact size of output file.<br/><span style=" font-weight:600;">This option control only quality of magnification!</span></p></body></html> High/Ultra quality @@ -664,7 +670,7 @@ - <html><head/><body><p>Resolution of target device.</p></body></html> + <html><head/><body><p style='white-space:pre'>Resolution of target device.</p></body></html> Custom width: @@ -697,7 +703,7 @@ false - <html><head/><body><p>Resolution of target device.</p></body></html> + <html><head/><body><p style='white-space:pre'>Resolution of target device.</p></body></html> 0000 @@ -715,7 +721,7 @@ - <html><head/><body><p>Resolution of target device.</p></body></html> + <html><head/><body><p style='white-space:pre'>Resolution of target device.</p></body></html> Custom height: @@ -748,7 +754,7 @@ false - <html><head/><body><p>Resolution of target device.</p></body></html> + <html><head/><body><p style='white-space:pre'>Resolution of target device.</p></body></html> 0000 diff --git a/KCC-OSX.ui b/KCC-OSX.ui index e73c93d..77a9079 100644 --- a/KCC-OSX.ui +++ b/KCC-OSX.ui @@ -69,7 +69,7 @@ Qt::NoFocus - <html><head/><body><p style='white-space:pre'>Disable image optimizations.<br/>Input images must be already resized.</p></body></html> + <html><head/><body><p style='white-space:pre'>Disable image optimizations.<br/><span style=" font-weight:600;">Input images must be already resized.</span></p></body></html> No optimisation @@ -110,7 +110,7 @@ Qt::NoFocus - <html><head/><body><p>Enable auto-splitting of webtoons like <span style=" font-style:italic;">Tower of God </span>or <span style=" font-style:italic;">Noblesse</span>.<br/>This mode was created for pages with a low width, high height and vertical panel flow.</p><p><br/></p></body></html> + <html><head/><body><p style='white-space:pre'>Enable special parsing mode for WebToons.</p></body></html> Webtoon mode @@ -170,7 +170,7 @@ Qt::NoFocus - <html><head/><body><p style='white-space:pre'>Disable splitting and rotation.</p></body></html> + <html><head/><body><p style='white-space:pre'>Disable page splitting and rotation.</p></body></html> No split/rotate @@ -220,7 +220,7 @@ Qt::NoFocus - <html><head/><body><p style='white-space:pre'>Output format.</p></body></html> + <html><head/><body><p style='white-space:pre'>Output format.</p></body></html> @@ -244,7 +244,7 @@ Qt::NoFocus - <html><head/><body><p style='white-space:pre'>Shift+Click to select the output directory.</p></body></html> + <html><head/><body><p style='white-space:pre'>Shift+Click to select the output directory.</p></body></html> Convert @@ -272,6 +272,9 @@ Qt::NoFocus + + <html><head/><body><p style='white-space:pre'>Add directory containing JPG, PNG or GIF files to queue.<br/><span style=" font-weight:600;">CBR, CBZ and CB7 files inside will not be processed!</span></p></body></html> + Add directory @@ -298,6 +301,9 @@ Qt::NoFocus + + <html><head/><body><p style='white-space:pre'>Add CBR, CBZ, CB7 or PDF file to queue.</p></body></html> + Add file @@ -391,7 +397,7 @@ Qt::NoFocus - <html><head/><body><p><span style=" font-weight:600; text-decoration: underline;">Unchecked - Normal quality mode</span><br/>Maximal quality of images but very poor magnification quality.<br/>Use it only when zoom is not needed or output files needs to be small.</p><p><span style=" font-weight:600; text-decoration: underline;">Indeterminate - High quality mode</span><br/>In most cases high quality of images and magnification.<br/>Overall quality highly depends on the resolution of source files.<br/>On Kindle models older than Paperwhite non-zoomed images might be a little blurred.</p><p><span style=" font-weight:600; text-decoration: underline;">Checked - Ultra quality mode</span><br/>Highest possible quality. Output files will be big.</p></body></html> + <html><head/><body><p style='white-space:pre'>Quality of Panel View/zoom. Highly impact size of output file.<br/><span style=" font-weight:600;">This option control only quality of magnification!</span></p></body></html> High/Ultra quality diff --git a/KCC.ui b/KCC.ui index 883a351..9e83cf7 100644 --- a/KCC.ui +++ b/KCC.ui @@ -65,7 +65,7 @@ Qt::NoFocus - <html><head/><body><p style='white-space:pre'>Disable image optimizations.<br/>Input images must be already resized.</p></body></html> + <html><head/><body><p style='white-space:pre'>Disable image optimizations.<br/><span style=" font-weight:600;">Input images must be already resized.</span></p></body></html> No optimisation @@ -94,7 +94,7 @@ Qt::NoFocus - <html><head/><body><p style="white-space:pre">Enable auto-splitting of webtoons like <span style=" font-style:italic;">Tower of God</span> or <span style=" font-style:italic;">Noblesse</span>.<br/>This mode is created for pages with a low width, high height and vertical panel flow.</p></body></html> + <html><head/><body><p style='white-space:pre'>Enable special parsing mode for WebToons.</p></body></html> Webtoon mode @@ -136,7 +136,7 @@ Qt::NoFocus - <html><head/><body><p style='white-space:pre'>Disable splitting and rotation.</p></body></html> + <html><head/><body><p style='white-space:pre'>Disable page splitting and rotation.</p></body></html> No split/rotate @@ -234,6 +234,9 @@ Qt::NoFocus + + <html><head/><body><p style='white-space:pre'>Add directory containing JPG, PNG or GIF files to queue.<br/><span style=" font-weight:600;">CBR, CBZ and CB7 files inside will not be processed!</span></p></body></html> + Add directory @@ -259,6 +262,9 @@ Qt::NoFocus + + <html><head/><body><p style='white-space:pre'>Add CBR, CBZ, CB7 or PDF file to queue.</p></body></html> + Add file @@ -338,7 +344,7 @@ Qt::NoFocus - <html><head/><body><p style="white-space:pre"><span style=" font-weight:600; text-decoration: underline;">Unchecked - Normal quality mode<br/></span>Maximal quality of images but very poor magnification quality.<br/>Use it only when zoom is not needed or output files needs to be small.</p><p style="white-space:pre"><span style=" font-weight:600; text-decoration: underline;">Indeterminate - High quality mode<br/></span>In most cases high quality of images and magnification.<br/>Overall quality highly depends on the resolution of source files.<br/>On Kindle models older than Paperwhite non-zoomed images might be a little blurred.</p><p style="white-space:pre"><span style=" font-weight:600; text-decoration: underline;">Checked - Ultra quality mode<br/></span>Highest possible quality. Output files will be big.</p></body></html> + <html><head/><body><p style='white-space:pre'>Quality of Panel View/zoom. Highly impact size of output file.<br/><span style=" font-weight:600;">This option control only quality of magnification!</span></p></body></html> High/Ultra quality diff --git a/kcc/KCC_gui.py b/kcc/KCC_gui.py index 42eb9b9..74dc7f6 100644 --- a/kcc/KCC_gui.py +++ b/kcc/KCC_gui.py @@ -1070,7 +1070,7 @@ class KCCGUI(KCC_ui.Ui_KCC): elif sys.platform.startswith('linux'): self.listFontSize = 8 self.statusBarFontSize = 8 - self.statusBarStyle = 'QLabel{padding-top:5px;padding-bottom:3px;}' + self.statusBarStyle = 'QLabel{padding-top:3px;padding-bottom:3px;}' self.statusBar.setStyleSheet('QStatusBar::item{border:0px;border-top:2px solid #C2C7CB;}') else: self.listFontSize = 9 diff --git a/kcc/KCC_ui.py b/kcc/KCC_ui.py index dd36744..4de51be 100644 --- a/kcc/KCC_ui.py +++ b/kcc/KCC_ui.py @@ -2,8 +2,8 @@ # Form implementation generated from reading ui file 'KCC.ui' # -# Created: Sun May 18 09:08:27 2014 -# by: PyQt5 UI code generator 5.2.1 +# Created: Sun Jan 4 09:58:25 2015 +# by: PyQt5 UI code generator 5.4 # # WARNING! All changes made in this file will be lost! @@ -138,12 +138,12 @@ class Ui_KCC(object): self.JobList = QtWidgets.QListWidget(self.Form) self.JobList.setGeometry(QtCore.QRect(10, 50, 401, 101)) self.JobList.setFocusPolicy(QtCore.Qt.NoFocus) - self.JobList.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel) - self.JobList.setHorizontalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel) - self.JobList.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) self.JobList.setStyleSheet("QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}") + self.JobList.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) self.JobList.setProperty("showDropIndicator", False) self.JobList.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection) + self.JobList.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel) + self.JobList.setHorizontalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel) self.JobList.setObjectName("JobList") self.BasicModeButton = QtWidgets.QPushButton(self.Form) self.BasicModeButton.setGeometry(QtCore.QRect(10, 10, 195, 32)) @@ -261,28 +261,30 @@ class Ui_KCC(object): def retranslateUi(self, KCC): _translate = QtCore.QCoreApplication.translate KCC.setWindowTitle(_translate("KCC", "Kindle Comic Converter")) - self.ProcessingBox.setToolTip(_translate("KCC", "

Disable image optimizations.
Input images must be already resized.

")) + self.ProcessingBox.setToolTip(_translate("KCC", "

Disable image optimizations.
Input images must be already resized.

")) self.ProcessingBox.setText(_translate("KCC", "No optimisation")) self.UpscaleBox.setToolTip(_translate("KCC", "

Unchecked - Nothing
Images smaller than device resolution will not be resized.

Indeterminate - Stretching
Images smaller than device resolution will be resized. Aspect ratio will be not preserved.

Checked - Upscaling
Images smaller than device resolution will be resized. Aspect ratio will be preserved.

")) self.UpscaleBox.setText(_translate("KCC", "Stretch/Upscale")) - self.WebtoonBox.setToolTip(_translate("KCC", "

Enable auto-splitting of webtoons like Tower of God or Noblesse.
This mode is created for pages with a low width, high height and vertical panel flow.

")) + self.WebtoonBox.setToolTip(_translate("KCC", "

Enable special parsing mode for WebToons.

")) self.WebtoonBox.setText(_translate("KCC", "Webtoon mode")) self.NoDitheringBox.setToolTip(_translate("KCC", "

Create PNG files instead JPEG.
Quality increase is not noticeable on most of devices.
Output files might be smaller.
MOBI conversion will be much slower.

")) self.NoDitheringBox.setText(_translate("KCC", "PNG output")) self.BorderBox.setToolTip(_translate("KCC", "

Unchecked - Autodetection
Color of margins fill will be detected automatically.

Indeterminate - White
Margins will be filled with white color.

Checked - Black
Margins will be filled with black color.

")) self.BorderBox.setText(_translate("KCC", "W/B margins")) - self.NoRotateBox.setToolTip(_translate("KCC", "

Disable splitting and rotation.

")) + self.NoRotateBox.setToolTip(_translate("KCC", "

Disable page splitting and rotation.

")) self.NoRotateBox.setText(_translate("KCC", "No split/rotate")) self.DeviceBox.setToolTip(_translate("KCC", "

Target device.

")) self.FormatBox.setToolTip(_translate("KCC", "

Output format.

")) self.ConvertButton.setToolTip(_translate("KCC", "

Shift+Click to select the output directory.

")) self.ConvertButton.setText(_translate("KCC", "Convert")) + self.DirectoryButton.setToolTip(_translate("KCC", "

Add directory containing JPG, PNG or GIF files to queue.
CBR, CBZ and CB7 files inside will not be processed!

")) self.DirectoryButton.setText(_translate("KCC", "Add directory")) + self.FileButton.setToolTip(_translate("KCC", "

Add CBR, CBZ, CB7 or PDF file to queue.

")) self.FileButton.setText(_translate("KCC", "Add file")) self.ClearButton.setText(_translate("KCC", "Clear list")) self.MangaBox.setToolTip(_translate("KCC", "

Enable right-to-left reading.

")) self.MangaBox.setText(_translate("KCC", "Manga mode")) - self.QualityBox.setToolTip(_translate("KCC", "

Unchecked - Normal quality mode
Maximal quality of images but very poor magnification quality.
Use it only when zoom is not needed or output files needs to be small.

Indeterminate - High quality mode
In most cases high quality of images and magnification.
Overall quality highly depends on the resolution of source files.
On Kindle models older than Paperwhite non-zoomed images might be a little blurred.

Checked - Ultra quality mode
Highest possible quality. Output files will be big.

")) + self.QualityBox.setToolTip(_translate("KCC", "

Quality of Panel View/zoom. Highly impact size of output file.
This option control only quality of magnification!

")) self.QualityBox.setText(_translate("KCC", "High/Ultra quality")) self.RotateBox.setToolTip(_translate("KCC", "

Disable splitting of two-page spreads.
They will be rotated instead.

")) self.RotateBox.setText(_translate("KCC", "Horizontal mode")) diff --git a/kcc/KCC_ui_linux.py b/kcc/KCC_ui_linux.py index d077804..eabddc6 100644 --- a/kcc/KCC_ui_linux.py +++ b/kcc/KCC_ui_linux.py @@ -2,8 +2,8 @@ # Form implementation generated from reading ui file 'KCC-Linux.ui' # -# Created: Sun May 18 09:08:37 2014 -# by: PyQt5 UI code generator 5.2.1 +# Created: Sun Jan 4 10:06:14 2015 +# by: PyQt5 UI code generator 5.4 # # WARNING! All changes made in this file will be lost! @@ -178,13 +178,13 @@ class Ui_KCC(object): font.setItalic(False) self.JobList.setFont(font) self.JobList.setFocusPolicy(QtCore.Qt.NoFocus) - self.JobList.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel) - self.JobList.setHorizontalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel) - self.JobList.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) self.JobList.setStyleSheet("QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}") + self.JobList.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) self.JobList.setProperty("showDropIndicator", False) self.JobList.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection) self.JobList.setIconSize(QtCore.QSize(18, 18)) + self.JobList.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel) + self.JobList.setHorizontalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel) self.JobList.setObjectName("JobList") self.BasicModeButton = QtWidgets.QPushButton(self.Form) self.BasicModeButton.setGeometry(QtCore.QRect(10, 10, 195, 32)) @@ -330,28 +330,30 @@ class Ui_KCC(object): def retranslateUi(self, KCC): _translate = QtCore.QCoreApplication.translate KCC.setWindowTitle(_translate("KCC", "Kindle Comic Converter")) - self.ProcessingBox.setToolTip(_translate("KCC", "

Disable image optimizations.
Input images must be already resized.

")) + self.ProcessingBox.setToolTip(_translate("KCC", "

Disable image optimizations.
Input images must be already resized.

")) self.ProcessingBox.setText(_translate("KCC", "No optimisation")) self.UpscaleBox.setToolTip(_translate("KCC", "

Unchecked - Nothing
Images smaller than device resolution will not be resized.

Indeterminate - Stretching
Images smaller than device resolution will be resized. Aspect ratio will be not preserved.

Checked - Upscaling
Images smaller than device resolution will be resized. Aspect ratio will be preserved.

")) self.UpscaleBox.setText(_translate("KCC", "Stretch/Upscale")) - self.WebtoonBox.setToolTip(_translate("KCC", "

Enable auto-splitting of webtoons like Tower of God or Noblesse.
This mode was created for pages with a low width, high height and vertical panel flow.

")) + self.WebtoonBox.setToolTip(_translate("KCC", "

Enable special parsing mode for WebToons.

")) self.WebtoonBox.setText(_translate("KCC", "Webtoon mode")) self.NoDitheringBox.setToolTip(_translate("KCC", "

Create PNG files instead JPEG.
Quality increase is not noticeable on most of devices.
Output files might be smaller.
MOBI conversion will be much slower.

")) self.NoDitheringBox.setText(_translate("KCC", "PNG output")) self.BorderBox.setToolTip(_translate("KCC", "

Unchecked - Autodetection
Color of margins fill will be detected automatically.

Indeterminate - White
Margins will be filled with white color.

Checked - Black
Margins will be filled with black color.

")) self.BorderBox.setText(_translate("KCC", "W/B margins")) - self.NoRotateBox.setToolTip(_translate("KCC", "

Disable splitting and rotation.

")) + self.NoRotateBox.setToolTip(_translate("KCC", "

Disable page splitting and rotation.

")) self.NoRotateBox.setText(_translate("KCC", "No split/rotate")) self.DeviceBox.setToolTip(_translate("KCC", "

Target device.

")) self.FormatBox.setToolTip(_translate("KCC", "

Output format.

")) - self.ConvertButton.setToolTip(_translate("KCC", "

Shift+Click to select the output directory.

")) + self.ConvertButton.setToolTip(_translate("KCC", "

Shift+Click to select the output directory.

")) self.ConvertButton.setText(_translate("KCC", "Convert")) + self.DirectoryButton.setToolTip(_translate("KCC", "

Add directory containing JPG, PNG or GIF files to queue.
CBR, CBZ and CB7 files inside will not be processed!

")) self.DirectoryButton.setText(_translate("KCC", "Add directory")) + self.FileButton.setToolTip(_translate("KCC", "

Add CBR, CBZ, CB7 or PDF file to queue.

")) self.FileButton.setText(_translate("KCC", "Add file")) self.ClearButton.setText(_translate("KCC", "Clear list")) self.MangaBox.setToolTip(_translate("KCC", "

Enable right-to-left reading.

")) self.MangaBox.setText(_translate("KCC", "Manga mode")) - self.QualityBox.setToolTip(_translate("KCC", "

Unchecked - Normal quality mode
Maximal quality of images but very poor magnification quality.
Use it only when zoom is not needed or output files needs to be small.

Indeterminate - High quality mode
In most cases high quality of images and magnification.
Overall quality highly depends on the resolution of source files.
On Kindle models older than Paperwhite non-zoomed images might be a little blurred.

Checked - Ultra quality mode
Highest possible quality. Output files will be big.

")) + self.QualityBox.setToolTip(_translate("KCC", "

Quality of Panel View/zoom. Highly impact size of output file.
This option control only quality of magnification!

")) self.QualityBox.setText(_translate("KCC", "High/Ultra quality")) self.RotateBox.setToolTip(_translate("KCC", "

Disable splitting of two-page spreads.
They will be rotated instead.

")) self.RotateBox.setText(_translate("KCC", "Horizontal mode")) @@ -360,13 +362,13 @@ class Ui_KCC(object): self.GammaLabel.setText(_translate("KCC", "Gamma: Auto")) self.ColorBox.setToolTip(_translate("KCC", "

Don\'t convert images to grayscale.

")) self.ColorBox.setText(_translate("KCC", "Color mode")) - self.wLabel.setToolTip(_translate("KCC", "

Resolution of target device.

")) + self.wLabel.setToolTip(_translate("KCC", "

Resolution of target device.

")) self.wLabel.setText(_translate("KCC", "Custom width: ")) - self.customWidth.setToolTip(_translate("KCC", "

Resolution of target device.

")) + self.customWidth.setToolTip(_translate("KCC", "

Resolution of target device.

")) self.customWidth.setInputMask(_translate("KCC", "0000")) - self.hLabel.setToolTip(_translate("KCC", "

Resolution of target device.

")) + self.hLabel.setToolTip(_translate("KCC", "

Resolution of target device.

")) self.hLabel.setText(_translate("KCC", "Custom height: ")) - self.customHeight.setToolTip(_translate("KCC", "

Resolution of target device.

")) + self.customHeight.setToolTip(_translate("KCC", "

Resolution of target device.

")) self.customHeight.setInputMask(_translate("KCC", "0000")) self.ActionBasic.setText(_translate("KCC", "Basic")) self.ActionAdvanced.setText(_translate("KCC", "Advanced")) diff --git a/kcc/KCC_ui_osx.py b/kcc/KCC_ui_osx.py index fb12b70..775ecc8 100644 --- a/kcc/KCC_ui_osx.py +++ b/kcc/KCC_ui_osx.py @@ -2,8 +2,8 @@ # Form implementation generated from reading ui file 'KCC-OSX.ui' # -# Created: Sun May 18 09:08:44 2014 -# by: PyQt5 UI code generator 5.2.1 +# Created: Sun Jan 4 10:26:09 2015 +# by: PyQt5 UI code generator 5.4 # # WARNING! All changes made in this file will be lost! @@ -185,12 +185,12 @@ class Ui_KCC(object): font.setPointSize(11) self.JobList.setFont(font) self.JobList.setFocusPolicy(QtCore.Qt.NoFocus) - self.JobList.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel) - self.JobList.setHorizontalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel) - self.JobList.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) self.JobList.setStyleSheet("QListWidget#JobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;}QScrollBar:vertical{border:1px solid #999;background:#FFF;width:5px;margin:0}QScrollBar::handle:vertical{background:DarkGray;min-height:0}QScrollBar::add-line:vertical{height:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:vertical{height:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}QScrollBar:horizontal{border:1px solid #999;background:#FFF;height:5px;margin:0}QScrollBar::handle:horizontal{background:DarkGray;min-width:0}QScrollBar::add-line:horizontal{width:0;background:DarkGray;subcontrol-position:bottom;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{width:0;background:DarkGray;subcontrol-position:top;subcontrol-origin:margin}") + self.JobList.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) self.JobList.setProperty("showDropIndicator", False) self.JobList.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection) + self.JobList.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel) + self.JobList.setHorizontalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel) self.JobList.setObjectName("JobList") self.BasicModeButton = QtWidgets.QPushButton(self.Form) self.BasicModeButton.setGeometry(QtCore.QRect(5, 10, 210, 41)) @@ -353,28 +353,30 @@ class Ui_KCC(object): def retranslateUi(self, KCC): _translate = QtCore.QCoreApplication.translate KCC.setWindowTitle(_translate("KCC", "Kindle Comic Converter")) - self.ProcessingBox.setToolTip(_translate("KCC", "

Disable image optimizations.
Input images must be already resized.

")) + self.ProcessingBox.setToolTip(_translate("KCC", "

Disable image optimizations.
Input images must be already resized.

")) self.ProcessingBox.setText(_translate("KCC", "No optimisation")) self.UpscaleBox.setToolTip(_translate("KCC", "

Unchecked - Nothing
Images smaller than device resolution will not be resized.

Indeterminate - Stretching
Images smaller than device resolution will be resized. Aspect ratio will be not preserved.

Checked - Upscaling
Images smaller than device resolution will be resized. Aspect ratio will be preserved.

")) self.UpscaleBox.setText(_translate("KCC", "Stretch/Upscale")) - self.WebtoonBox.setToolTip(_translate("KCC", "

Enable auto-splitting of webtoons like Tower of God or Noblesse.
This mode was created for pages with a low width, high height and vertical panel flow.


")) + self.WebtoonBox.setToolTip(_translate("KCC", "

Enable special parsing mode for WebToons.

")) self.WebtoonBox.setText(_translate("KCC", "Webtoon mode")) self.NoDitheringBox.setToolTip(_translate("KCC", "

Create PNG files instead JPEG.
Quality increase is not noticeable on most of devices.
Output files might be smaller.
MOBI conversion will be much slower.

")) self.NoDitheringBox.setText(_translate("KCC", "PNG output")) self.BorderBox.setToolTip(_translate("KCC", "

Unchecked - Autodetection
Color of margins fill will be detected automatically.

Indeterminate - White
Margins will be filled with white color.

Checked - Black
Margins will be filled with black color.

")) self.BorderBox.setText(_translate("KCC", "W/B margins")) - self.NoRotateBox.setToolTip(_translate("KCC", "

Disable splitting and rotation.

")) + self.NoRotateBox.setToolTip(_translate("KCC", "

Disable page splitting and rotation.

")) self.NoRotateBox.setText(_translate("KCC", "No split/rotate")) self.DeviceBox.setToolTip(_translate("KCC", "

Target device.

")) - self.FormatBox.setToolTip(_translate("KCC", "

Output format.

")) - self.ConvertButton.setToolTip(_translate("KCC", "

Shift+Click to select the output directory.

")) + self.FormatBox.setToolTip(_translate("KCC", "

Output format.

")) + self.ConvertButton.setToolTip(_translate("KCC", "

Shift+Click to select the output directory.

")) self.ConvertButton.setText(_translate("KCC", "Convert")) + self.DirectoryButton.setToolTip(_translate("KCC", "

Add directory containing JPG, PNG or GIF files to queue.
CBR, CBZ and CB7 files inside will not be processed!

")) self.DirectoryButton.setText(_translate("KCC", "Add directory")) + self.FileButton.setToolTip(_translate("KCC", "

Add CBR, CBZ, CB7 or PDF file to queue.

")) self.FileButton.setText(_translate("KCC", "Add file")) self.ClearButton.setText(_translate("KCC", "Clear list")) self.MangaBox.setToolTip(_translate("KCC", "

Enable right-to-left reading.

")) self.MangaBox.setText(_translate("KCC", "Manga mode")) - self.QualityBox.setToolTip(_translate("KCC", "

Unchecked - Normal quality mode
Maximal quality of images but very poor magnification quality.
Use it only when zoom is not needed or output files needs to be small.

Indeterminate - High quality mode
In most cases high quality of images and magnification.
Overall quality highly depends on the resolution of source files.
On Kindle models older than Paperwhite non-zoomed images might be a little blurred.

Checked - Ultra quality mode
Highest possible quality. Output files will be big.

")) + self.QualityBox.setToolTip(_translate("KCC", "

Quality of Panel View/zoom. Highly impact size of output file.
This option control only quality of magnification!

")) self.QualityBox.setText(_translate("KCC", "High/Ultra quality")) self.RotateBox.setToolTip(_translate("KCC", "

Disable splitting of two-page spreads.
They will be rotated instead.

")) self.RotateBox.setText(_translate("KCC", "Horizontal mode")) From b5bc2f8e00dde644d65395080d90ce5ead4611a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jastrz=C4=99bski?= Date: Sun, 4 Jan 2015 10:49:59 +0100 Subject: [PATCH 11/12] Updated README + version bump --- README.md | 380 +++++++++++++++++++++++---------------------- kcc-c2e.py | 2 +- kcc-c2p.py | 2 +- kcc.iss | 2 +- kcc.py | 2 +- kcc/KCC_gui.py | 2 +- kcc/__init__.py | 2 +- kcc/comic2ebook.py | 2 +- kcc/comic2panel.py | 2 +- kcc/image.py | 2 +- setup.py | 2 +- setup.sh | 2 +- 12 files changed, 204 insertions(+), 198 deletions(-) diff --git a/README.md b/README.md index 98f9811..6660277 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,7 @@ _KC2_ in no way is a replacement for **KCC** so you can be quite confident we'll ### Issues / new features / donations If you have general questions about usage, feedback etc. please [post it here](http://www.mobileread.com/forums/showthread.php?t=207461). If you have some **technical** problems using KCC please [file an issue here](https://github.com/ciromattia/kcc/issues/new). -If you can fix an open issue, fork & make a pull request. -If you want more chances an issue is fixes or your wanted feature added, consider [placing a bounty](https://www.bountysource.com/trackers/65571-ciromattia-kcc)! +If you can fix an open issue, fork & make a pull request. If you find **KCC** valuable you can consider donating to the authors: - Ciro Mattia Gonano: @@ -32,7 +31,7 @@ You can find the latest released binary at the following links: ## INPUT FORMATS **KCC** can understand and convert, at the moment, the following input types: -- Folders containing: PNG, JPG, GIF, TIFF or BMP files +- Folders containing: PNG, JPG or GIF files - CBZ, ZIP - CBR, RAR *(With `unrar` executable)* - CB7, 7Z *(With `7za` executable)* @@ -46,19 +45,19 @@ You can find the latest released binary at the following links: ### For running from source: - Python 3.3+ - [PyQt5](http://www.riverbankcomputing.co.uk/software/pyqt/download5) 5.2.0+ -- [Pillow](http://pypi.python.org/pypi/Pillow/) 2.5.0+ +- [Pillow](http://pypi.python.org/pypi/Pillow/) 2.7.0+ - [psutil](https://pypi.python.org/pypi/psutil) 2.0+ - [python-slugify](http://pypi.python.org/pypi/python-slugify) On Debian based distributions these two commands should install all dependencies: ``` -sudo apt-get install python3 python3-dev python3-pip python3-pyqt5 libtiff-dev libpng-dev libjpeg-dev p7zip-full unrar +sudo apt-get install python3 python3-dev python3-pip python3-pyqt5 libpng-dev libjpeg-dev p7zip-full unrar sudo pip3 install pillow python-slugify psutil ``` ### For freezing code: -- Windows - [py2exe](https://pypi.python.org/pypi/py2exe) 0.9.2+ -- OS X - [py2app](https://bitbucket.org/ronaldoussoren/py2app) 0.8.0+ +- Windows - [py2exe](https://pypi.python.org/pypi/py2exe) 0.9.2.2+ +- OS X - [py2app](https://bitbucket.org/ronaldoussoren/py2app) 0.9.0+ ## USAGE @@ -143,7 +142,7 @@ This script born as a cross-platform alternative to `KindleComicParser` by **Dc5 The app relies and includes the following scripts: - `DualMetaFix` script by **K. Hendricks**. Released with GPL-3 License. - - `rarfile.py` script © 2005-2011 **Marko Kreen** . Released with ISC License. + - `rarfile.py` script © 2005-2014 **Marko Kreen** . Released with ISC License. - `image.py` class from **Alex Yatskov**'s [Mangle](https://github.com/FooSoft/mangle/) with subsequent [proDOOMman](https://github.com/proDOOMman/Mangle)'s and [Birua](https://github.com/Birua/Mangle)'s patches. - Icon is by **Nikolay Verin** ([http://ncrow.deviantart.com/](http://ncrow.deviantart.com/)) and released under [CC BY-NC-SA 3.0](http://creativecommons.org/licenses/by-nc-sa/3.0/) License. @@ -159,113 +158,115 @@ The app relies and includes the following scripts: * [Kobo Aura H2O](http://kcc.iosphe.re/Samples/Ubunchu!-KoAH2O.cbz) ## CHANGELOG -####1.0 -* Initial version +####4.4: +* Improved speed and quality of conversion +* Added RAR5 support +* Dropped BMP and TIFF support +* Fixed some WebToon mode bugs +* Fixed CBR parsing on OSX -####1.1 -* Added support for CBZ/CBR files in comic2ebook.py +####4.3.1: +* Fixed Kindle Voyage profile +* Fixed some bugs in OS X release +* CLI version now support multiple input files at once +* Disabled MCB support +* Other minor tweaks -####1.1.1 -* Added support for CBZ/CBR files in Kindle Comic Converter +####4.3: +* Added profiles for Kindle Voyage and Kobo Aura H2O +* Added missing features to CLI version +* Other minor bug fixes -####1.2 -* Comic optimizations! Split pages not target-oriented (landscape with portrait target or portrait with landscape target), add palette and other image optimizations from Mangle. WARNING: PIL is required for all image mangling! +####4.2.1: +* Improved margin color detection +* Fixed random crashes of MOBI processing step +* Fixed resizing problems in high quality mode +* Fixed some MCD support bugs +* Default output format for Kindle DX is now CBZ -####1.3 -* Fixed an issue in OPF generation for device resolution -* Reworked options system (call with -h option to get the inline help) +####4.2: +* Added [Manga Cover Database](http://manga.joentjuh.nl/) support +* Officially dropped Windows XP support +* Fixed _Other_ profile +* Fixed problems with page order on stock KOBO CBZ reader +* Many other small bug fixes and tweaks -####1.4 -* Added some options for controlling image optimization -* Further optimization (ImageOps, page numbering cut, autocontrast) +####4.1: +* Thanks to code contributed by Kevin Hendricks speed of MOBI creation was greatly increased +* Improved performance on Windows +* Improved MOBI splitting and changed maximal size of output file +* Fixed _No optimization_ mode +* Multiple small tweaks nad minor bug fixes -####1.4.1 -* Fixed a serious bug on resizing when img ratio was bigger than device one +####4.0.2: +* Fixed some Windows and OSX specific bugs +* Fixed problem with marigns when using HQ mode -####1.5 -* Added subfolder support for multiple chapters. +####4.0.1: +* Fixed file lock problems that plagued some Windows users +* Fixed content server failing to start on Windows +* Improved performance of WebToon splitter +* Tweaked margin color detection -####2.0 -* GUI! AppleScript is gone and Tk is used to provide cross-platform GUI support. +####4.0: +* KCC now use Python 3.3 and Qt 5.2 +* Full UTF-8 awareness +* CBZ output now support Manga mode +* Improved Panel View support and margin color detection +* Added drag&drop support +* Output directory can be now selected +* Windows release now have auto-updater +* Names of chapters on Kindle should be now more user friendly +* Fixed OSX file association support +* Many extensive internal changes and tweaks -####2.1 -* Added basic error reporting +####3.7.2: +* Fixed problems with HQ mode -####2.2: -* Added (valid!) EPUB 2.0 output -* Rename .zip files to .cbz to avoid overwriting +####3.7.1: +* Hotfixed Kobo profiles -####2.3 -* Fixed win32 EPUB generation, folder handling, filenames with spaces and subfolders +####3.7: +* Added profiles for KOBO devices +* Improved Panel View support +* Improved WebToon splitter +* Improved margin color autodetection +* Tweaked EPUB output +* Fixed stretching option +* GUI tweaks and minor bugfixes -####2.4 -* Use temporary directory as workdir (fixes converting from external volumes and zipfiles renaming) -* Fixed "add folders" from GUI. +####3.6.2: +* Fixed previous PNG output fix +* Fixed Panel View anomalies -####2.5 -* Added --black-borders option to set added borders black when page's ratio is not the device's one (#11). -* Fixes EPUB containing zipped itself (#10) +####3.6.1: +* Fixed PNG output -####2.6 -* Added --rotate option to rotate landscape images instead of splitting them (#16, #24) -* Added --output option to customize EPUB output dir/file (#22) -* Add rendition:layout and rendition:orientation EPUB meta tags (supported by new kindlegen 2.8) -* Fixed natural sorting for files (#18) +####3.6: +* Increased quality of Panel View zoom +* Creation of multipart MOBI output is now faster on machines with 4GB+ RAM +* Automatic gamma correction now distinguishes color and grayscale images +* Added ComicRack metadata parser +* Implemented new method to detect border color in non-webtoon comics +* Upscaling is now enabled by default for Kindle Fire HD/HDX +* Windows nad Linux releases now have tray icon +* Fixed Kindle Fire HDX 7" output +* Increased target resolution for Kindle DX/DXG CBZ output -####2.7 -* Lots of GUI improvements (#27, #13) -* Added gamma support within --gamma option (defaults to profile-specified gamma) (#26, #27) -* Added --nodithering option to prevent dithering optimizations (#27) -* EPUB margins support (#30) -* Fixed no file added if file has no spaces on Windows (#25) -* Gracefully exit if unrar missing (#15) -* Do not call kindlegen if source EPUB is bigger than 320MB (#17) -* Get filetype from magic number (#14) -* PDF conversion works again +####3.5: +* Added simple content server - Converted files can be now delivered wireless +* Added proper Windows installer +* Improved multiprocessing speed +* GUI tweaks and minor bug fixes -####2.8 -* Updated rarfile library -* Panel View support + HQ support (#36) - new option: --nopanelviewhq -* Split profiles for K4NT and K4T -* Rewrite of Landscape Mode support (huge readability improvement for KPW) -* Upscale use now BILINEAR method -* Added generic CSS file -* Optimized archive extraction for zip/rar files (#40) - -####2.9 -* Added support for generating a plain CBZ (skipping all the EPUB/MOBI generation) (#45) -* Prevent output file overwriting the source one: if a duplicate name is detected, append _kcc to the name -* Rarfile library updated to 2.6 -* Added GIF, TIFF and BMP to supported formats (#42) -* Filenames slugifications (#28, #31, #9, #8) - -####2.10: -* Multiprocessing support -* Kindle Fire support (color EPUB/MOBI) -* Panel View support for horizontal content -* Fixed panel order for horizontal pages when --rotate is enabled -* Disabled cropping and page number cutting for blank pages -* Fixed some slugify issues with specific file naming conventions (#50, #51) - -####3.0: -* New QT GUI -* Merge with AWKCC -* Added ultra quality mode -* Added support for custom width/height -* Added option to disable color conversion - -####3.1: -* Added profile: Kindle for Android -* Add file/directory dialogs now support multiselect -* Many small fixes and tweaks - -####3.2: -* Too big EPUB files are now splitted before conversion to MOBI -* Added experimental parser of manga webtoons -* Improved error handling - -####3.2.1: -* Hotfixed crash occurring on OS with Russian locale +####3.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 ####3.3: * Margins are now automatically omitted in Panel View mode @@ -281,112 +282,117 @@ The app relies and includes the following scripts: * 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 +####3.2: +* Too big EPUB files are now splitted before conversion to MOBI +* Added experimental parser of manga webtoons +* Improved error handling -####3.5: -* Added simple content server - Converted files can be now delivered wireless -* Added proper Windows installer -* Improved multiprocessing speed -* GUI tweaks and minor bug fixes +####3.2.1: +* Hotfixed crash occurring on OS with Russian locale -####3.6: -* Increased quality of Panel View zoom -* Creation of multipart MOBI output is now faster on machines with 4GB+ RAM -* Automatic gamma correction now distinguishes color and grayscale images -* Added ComicRack metadata parser -* Implemented new method to detect border color in non-webtoon comics -* Upscaling is now enabled by default for Kindle Fire HD/HDX -* Windows nad Linux releases now have tray icon -* Fixed Kindle Fire HDX 7" output -* Increased target resolution for Kindle DX/DXG CBZ output +####3.1: +* Added profile: Kindle for Android +* Add file/directory dialogs now support multiselect +* Many small fixes and tweaks -####3.6.1: -* Fixed PNG output +####3.0: +* New QT GUI +* Merge with AWKCC +* Added ultra quality mode +* Added support for custom width/height +* Added option to disable color conversion -####3.6.2: -* Fixed previous PNG output fix -* Fixed Panel View anomalies +####2.10: +* Multiprocessing support +* Kindle Fire support (color EPUB/MOBI) +* Panel View support for horizontal content +* Fixed panel order for horizontal pages when --rotate is enabled +* Disabled cropping and page number cutting for blank pages +* Fixed some slugify issues with specific file naming conventions (#50, #51) -####3.7: -* Added profiles for KOBO devices -* Improved Panel View support -* Improved WebToon splitter -* Improved margin color autodetection -* Tweaked EPUB output -* Fixed stretching option -* GUI tweaks and minor bugfixes +####2.9 +* Added support for generating a plain CBZ (skipping all the EPUB/MOBI generation) (#45) +* Prevent output file overwriting the source one: if a duplicate name is detected, append _kcc to the name +* Rarfile library updated to 2.6 +* Added GIF, TIFF and BMP to supported formats (#42) +* Filenames slugifications (#28, #31, #9, #8) -####3.7.1: -* Hotfixed Kobo profiles +####2.8 +* Updated rarfile library +* Panel View support + HQ support (#36) - new option: --nopanelviewhq +* Split profiles for K4NT and K4T +* Rewrite of Landscape Mode support (huge readability improvement for KPW) +* Upscale use now BILINEAR method +* Added generic CSS file +* Optimized archive extraction for zip/rar files (#40) -####3.7.2: -* Fixed problems with HQ mode +####2.7 +* Lots of GUI improvements (#27, #13) +* Added gamma support within --gamma option (defaults to profile-specified gamma) (#26, #27) +* Added --nodithering option to prevent dithering optimizations (#27) +* EPUB margins support (#30) +* Fixed no file added if file has no spaces on Windows (#25) +* Gracefully exit if unrar missing (#15) +* Do not call kindlegen if source EPUB is bigger than 320MB (#17) +* Get filetype from magic number (#14) +* PDF conversion works again -####4.0: -* KCC now use Python 3.3 and Qt 5.2 -* Full UTF-8 awareness -* CBZ output now support Manga mode -* Improved Panel View support and margin color detection -* Added drag&drop support -* Output directory can be now selected -* Windows release now have auto-updater -* Names of chapters on Kindle should be now more user friendly -* Fixed OSX file association support -* Many extensive internal changes and tweaks +####2.6 +* Added --rotate option to rotate landscape images instead of splitting them (#16, #24) +* Added --output option to customize EPUB output dir/file (#22) +* Add rendition:layout and rendition:orientation EPUB meta tags (supported by new kindlegen 2.8) +* Fixed natural sorting for files (#18) -####4.0.1: -* Fixed file lock problems that plagued some Windows users -* Fixed content server failing to start on Windows -* Improved performance of WebToon splitter -* Tweaked margin color detection +####2.5 +* Added --black-borders option to set added borders black when page's ratio is not the device's one (#11). +* Fixes EPUB containing zipped itself (#10) -####4.0.2: -* Fixed some Windows and OSX specific bugs -* Fixed problem with marigns when using HQ mode +####2.4 +* Use temporary directory as workdir (fixes converting from external volumes and zipfiles renaming) +* Fixed "add folders" from GUI. -####4.1: -* Thanks to code contributed by Kevin Hendricks speed of MOBI creation was greatly increased -* Improved performance on Windows -* Improved MOBI splitting and changed maximal size of output file -* Fixed _No optimization_ mode -* Multiple small tweaks nad minor bug fixes +####2.3 +* Fixed win32 EPUB generation, folder handling, filenames with spaces and subfolders -####4.2: -* Added [Manga Cover Database](http://manga.joentjuh.nl/) support -* Officially dropped Windows XP support -* Fixed _Other_ profile -* Fixed problems with page order on stock KOBO CBZ reader -* Many other small bug fixes and tweaks +####2.2: +* Added (valid!) EPUB 2.0 output +* Rename .zip files to .cbz to avoid overwriting -####4.2.1: -* Improved margin color detection -* Fixed random crashes of MOBI processing step -* Fixed resizing problems in high quality mode -* Fixed some MCD support bugs -* Default output format for Kindle DX is now CBZ +####2.1 +* Added basic error reporting -####4.3: -* Added profiles for Kindle Voyage and Kobo Aura H2O -* Added missing features to CLI version -* Other minor bug fixes +####2.0 +* GUI! AppleScript is gone and Tk is used to provide cross-platform GUI support. -####4.3.1: -* Fixed Kindle Voyage profile -* Fixed some bugs in OS X release -* CLI version now support multiple input files at once -* Disabled MCB support -* Other minor tweaks +####1.5 +* Added subfolder support for multiple chapters. + +####1.4.1 +* Fixed a serious bug on resizing when img ratio was bigger than device one + +####1.4 +* Added some options for controlling image optimization +* Further optimization (ImageOps, page numbering cut, autocontrast) + +####1.3 +* Fixed an issue in OPF generation for device resolution +* Reworked options system (call with -h option to get the inline help) + +####1.2 +* Comic optimizations! Split pages not target-oriented (landscape with portrait target or portrait with landscape target), add palette and other image optimizations from Mangle. WARNING: PIL is required for all image mangling! + +####1.1.1 +* Added support for CBZ/CBR files in Kindle Comic Converter + +####1.1 +* Added support for CBZ/CBR files in comic2ebook.py + +####1.0 +* Initial version ## KNOWN ISSUES Please check [wiki page](https://github.com/ciromattia/kcc/wiki/Known-issues). ## COPYRIGHT -Copyright (c) 2012-2014 Ciro Mattia Gonano and Paweł Jastrzębski. +Copyright (c) 2012-2015 Ciro Mattia Gonano and Paweł Jastrzębski. **KCC** is released under ISC LICENSE; see LICENSE.txt for further details. diff --git a/kcc-c2e.py b/kcc-c2e.py index 5bc3680..cbc5f20 100755 --- a/kcc-c2e.py +++ b/kcc-c2e.py @@ -18,7 +18,7 @@ # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -__version__ = '4.3.1' +__version__ = '4.4' __license__ = 'ISC' __copyright__ = '2012-2015, Ciro Mattia Gonano , Pawel Jastrzebski ' __docformat__ = 'restructuredtext en' diff --git a/kcc-c2p.py b/kcc-c2p.py index 53216a4..674e67f 100755 --- a/kcc-c2p.py +++ b/kcc-c2p.py @@ -18,7 +18,7 @@ # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -__version__ = '4.3.1' +__version__ = '4.4' __license__ = 'ISC' __copyright__ = '2012-2015, Ciro Mattia Gonano , Pawel Jastrzebski ' __docformat__ = 'restructuredtext en' diff --git a/kcc.iss b/kcc.iss index f05ab56..8c6b275 100644 --- a/kcc.iss +++ b/kcc.iss @@ -1,5 +1,5 @@ #define MyAppName "Kindle Comic Converter" -#define MyAppVersion "4.3.1" +#define MyAppVersion "4.4" #define MyAppPublisher "Ciro Mattia Gonano, Paweł Jastrzębski" #define MyAppURL "http://kcc.iosphe.re/" #define MyAppExeName "KCC.exe" diff --git a/kcc.py b/kcc.py index 119cd13..edd3151 100755 --- a/kcc.py +++ b/kcc.py @@ -18,7 +18,7 @@ # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -__version__ = '4.3.1' +__version__ = '4.4' __license__ = 'ISC' __copyright__ = '2012-2015, Ciro Mattia Gonano , Pawel Jastrzebski ' __docformat__ = 'restructuredtext en' diff --git a/kcc/KCC_gui.py b/kcc/KCC_gui.py index 74dc7f6..ddf1e6c 100644 --- a/kcc/KCC_gui.py +++ b/kcc/KCC_gui.py @@ -17,7 +17,7 @@ # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -__version__ = '4.3.1' +__version__ = '4.4' __license__ = 'ISC' __copyright__ = '2012-2015, Ciro Mattia Gonano , Pawel Jastrzebski ' __docformat__ = 'restructuredtext en' diff --git a/kcc/__init__.py b/kcc/__init__.py index 72fa985..7b32d0a 100644 --- a/kcc/__init__.py +++ b/kcc/__init__.py @@ -1,4 +1,4 @@ -__version__ = '4.3.1' +__version__ = '4.4' __license__ = 'ISC' __copyright__ = '2012-2015, Ciro Mattia Gonano , Pawel Jastrzebski ' __docformat__ = 'restructuredtext en' \ No newline at end of file diff --git a/kcc/comic2ebook.py b/kcc/comic2ebook.py index 2a9aade..8cb2edd 100755 --- a/kcc/comic2ebook.py +++ b/kcc/comic2ebook.py @@ -18,7 +18,7 @@ # PERFORMANCE OF THIS SOFTWARE. # -__version__ = '4.3.1' +__version__ = '4.4' __license__ = 'ISC' __copyright__ = '2012-2015, Ciro Mattia Gonano , Pawel Jastrzebski ' __docformat__ = 'restructuredtext en' diff --git a/kcc/comic2panel.py b/kcc/comic2panel.py index 16a88be..a9462ca 100644 --- a/kcc/comic2panel.py +++ b/kcc/comic2panel.py @@ -18,7 +18,7 @@ # PERFORMANCE OF THIS SOFTWARE. # -__version__ = '4.3.1' +__version__ = '4.4' __license__ = 'ISC' __copyright__ = '2012-2015, Ciro Mattia Gonano , Pawel Jastrzebski ' __docformat__ = 'restructuredtext en' diff --git a/kcc/image.py b/kcc/image.py index f8cc4af..228bbae 100755 --- a/kcc/image.py +++ b/kcc/image.py @@ -16,7 +16,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -__version__ = '4.3.1' +__version__ = '4.4' __license__ = 'ISC' __copyright__ = '2012-2015, Ciro Mattia Gonano , Pawel Jastrzebski ' __docformat__ = 'restructuredtext en' diff --git a/setup.py b/setup.py index 99bd3f5..a75f07f 100755 --- a/setup.py +++ b/setup.py @@ -14,7 +14,7 @@ if version_info[0] != 3: exit(1) NAME = "KindleComicConverter" -VERSION = "4.3.1" +VERSION = "4.4" MAIN = "kcc.py" if platform == "darwin": diff --git a/setup.sh b/setup.sh index 20708fa..01ea98f 100755 --- a/setup.sh +++ b/setup.sh @@ -1,7 +1,7 @@ #!/bin/bash # Linux Python package build script -VERSION="4.3.1" +VERSION="4.4" cp kcc.py __main__.py zip kcc.zip __main__.py kcc/*.py From bfba66d47dbb766f34035fac063223376ce23df4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jastrz=C4=99bski?= Date: Sun, 4 Jan 2015 14:23:03 +0100 Subject: [PATCH 12/12] Improved KindleGen detection --- kcc/KCC_gui.py | 75 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 30 deletions(-) diff --git a/kcc/KCC_gui.py b/kcc/KCC_gui.py index ddf1e6c..2a3780e 100644 --- a/kcc/KCC_gui.py +++ b/kcc/KCC_gui.py @@ -931,15 +931,19 @@ class KCCGUI(KCC_ui.Ui_KCC): self.addMessage('Target resolution is not set!', 'error') self.needClean = True return - if str(GUI.FormatBox.currentText()) == 'MOBI' and not GUI.KindleGen: - self.addMessage('Cannot find ' - 'KindleGen! MOBI conversion is not possible!', 'error') - if sys.platform.startswith('win'): - self.addMessage('Download it and place EXE in KCC directory.', 'error') - else: - self.addMessage('Download it, and place executable in /usr/local/bin directory.', 'error') - self.needClean = True - return + if str(GUI.FormatBox.currentText()) == 'MOBI' and not self.KindleGen: + self.detectKindleGen() + if not self.KindleGen: + GUI.JobList.clear() + self.addMessage('Cannot find KindleGen!' + ' MOBI conversion is unavailable!', 'error') + if sys.platform.startswith('win'): + self.addMessage('Download it and place EXE in KCC directory.', 'error') + else: + self.addMessage('Download it and place executable in /usr/local/bin directory.', 'error') + self.needClean = True + return self.worker.start() def hideProgressBar(self): @@ -1027,6 +1031,36 @@ class KCCGUI(KCC_ui.Ui_KCC): self.saveSettings(None) sys.exit(0) + def detectKindleGen(self, startup=False): + if not sys.platform.startswith('win'): + try: + os.chmod('/usr/local/bin/kindlegen', 0o755) + except Exception: + pass + kindleGenExitCode = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, shell=True) + if kindleGenExitCode.wait() == 0: + self.KindleGen = True + versionCheck = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, shell=True) + for line in versionCheck.stdout: + line = line.decode("utf-8") + if 'Amazon kindlegen' in line: + versionCheck = line.split('V')[1].split(' ')[0] + if tuple(map(int, (versionCheck.split(".")))) < tuple(map(int, ('2.9'.split(".")))): + self.addMessage('Your KindleGen is outdated! Creating MOBI might fail.' + ' Please update KindleGen from Amazon\'s website.', 'warning') + break + else: + self.KindleGen = False + if startup: + self.addMessage('Cannot find ' + 'KindleGen! MOBI conversion will be unavailable!', 'error') + if sys.platform.startswith('win'): + self.addMessage('Download it and place EXE in KCC directory.', 'error') + else: + self.addMessage('Download it and place executable in /usr/local/bin directory.', 'error') + # noinspection PyArgumentList def __init__(self, KCCAplication, KCCWindow): global APP, MW, GUI @@ -1057,6 +1091,7 @@ class KCCGUI(KCC_ui.Ui_KCC): self.tray = SystemTrayIcon() self.conversionAlive = False self.needClean = True + self.KindleGen = False self.GammaValue = 1.0 self.completedWork = {} self.targetDirectory = '' @@ -1158,27 +1193,6 @@ class KCCGUI(KCC_ui.Ui_KCC): self.addMessage('Since you are new user of KCC please see few ' 'important tips.', 'info') - if not sys.platform.startswith('win'): - try: - os.chmod('/usr/local/bin/kindlegen', 0o755) - except Exception: - pass - kindleGenExitCode = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, shell=True) - if kindleGenExitCode.wait() == 0: - self.KindleGen = True - versionCheck = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, shell=True) - for line in versionCheck.stdout: - line = line.decode("utf-8") - if 'Amazon kindlegen' in line: - versionCheck = line.split('V')[1].split(' ')[0] - if tuple(map(int, (versionCheck.split(".")))) < tuple(map(int, ('2.9'.split(".")))): - self.addMessage('Your kindlegen is outdated! Creating MOBI might fail.' - ' Please update kindlegen from Amazon\'s website.', 'warning') - break - else: - self.KindleGen = False rarExitCode = Popen('unrar', stdout=PIPE, stderr=STDOUT, shell=True) rarExitCode = rarExitCode.wait() if rarExitCode == 0 or rarExitCode == 7: @@ -1195,6 +1209,7 @@ class KCCGUI(KCC_ui.Ui_KCC): self.sevenza = False self.addMessage('Cannot find 7za!' ' Processing of CB7/7Z files will be disabled.', 'warning') + self.detectKindleGen(True) APP.messageFromOtherInstance.connect(self.handleMessage) GUI.BasicModeButton.clicked.connect(self.modeBasic)