From e86128dee1236e6cc63f67911010ac0136ffb12d Mon Sep 17 00:00:00 2001 From: Marek Kubica Date: Sun, 30 Oct 2011 12:38:01 +0900 Subject: [PATCH 1/3] Mangle can now write CBZ files, CBZ-only is not yet implemented --- mangle/book.py | 8 +++++-- mangle/cbz.py | 39 ++++++++++++++++++++++++++++++++++ mangle/convert.py | 17 ++++++++++++++- mangle/options.py | 2 ++ mangle/resources/ui/options.ui | 31 ++++++++++++++++++++++++++- 5 files changed, 93 insertions(+), 4 deletions(-) create mode 100644 mangle/cbz.py diff --git a/mangle/book.py b/mangle/book.py index be34e85..9efdd6b 100644 --- a/mangle/book.py +++ b/mangle/book.py @@ -24,10 +24,11 @@ from about import DialogAbout from options import DialogOptions from convert import DialogConvert -class Book: +class Book(object): DefaultDevice = 'Kindle 3' DefaultOverwrite = True DefaultImageFlags = ImageFlags.Orient | ImageFlags.Resize | ImageFlags.Quantize + DefaultOutputFormat = 'image+cbz' def __init__(self): @@ -38,6 +39,7 @@ class Book: self.device = Book.DefaultDevice self.overwrite = Book.DefaultOverwrite self.imageFlags = Book.DefaultImageFlags + self.outputFormat = Book.DefaultOutputFormat def save(self, filename): @@ -50,6 +52,7 @@ class Book: root.setAttribute('overwrite', 'true' if self.overwrite else 'false') root.setAttribute('device', self.device) root.setAttribute('imageFlags', self.imageFlags) + root.setAttribute('outputFormat', self.outputFormat) for filenameImg in self.images: itemImg = document.createElement('image') @@ -89,13 +92,14 @@ class Book: self.title = root.attribute('title', 'Untitled') self.overwrite = root.attribute('overwrite', 'true' if Book.DefaultOverwrite else 'false') == 'true' self.device = root.attribute('device', Book.DefaultDevice) + self.outputFormat = root.attribute('outputFormat', 'image+cbz') self.imageFlags = int(root.attribute('imageFlags', str(Book.DefaultImageFlags))) self.filename = filename self.modified = False self.images = [] items = root.elementsByTagName('image') - if items == None: + if items is None: return for i in xrange(0, len(items)): diff --git a/mangle/cbz.py b/mangle/cbz.py new file mode 100644 index 0000000..f3cd9d8 --- /dev/null +++ b/mangle/cbz.py @@ -0,0 +1,39 @@ +# Copyright (C) 2011 Marek Kubica +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +import os.path +from zipfile import ZipFile, ZIP_STORED + + +class Archive(object): + def __init__(self, path): + outputDirectory = os.path.dirname(path) + outputFileName = '%s.cbz' % os.path.basename(path) + outputPath = os.path.join(outputDirectory, outputFileName) + self.zipfile = ZipFile(outputPath, 'w', ZIP_STORED) + + def addFile(self, filename): + arcname = os.path.basename(filename) + self.zipfile.write(filename, arcname) + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.close() + + def close(self): + self.zipfile.close() diff --git a/mangle/convert.py b/mangle/convert.py index 3cd2f05..b8478c3 100644 --- a/mangle/convert.py +++ b/mangle/convert.py @@ -17,11 +17,13 @@ import os from PyQt4 import QtGui, QtCore import image +import cbz class DialogConvert(QtGui.QProgressDialog): def __init__(self, parent, book, directory): QtGui.QProgressDialog.__init__(self) + #self.setAutoReset(False) self.book = book self.directory = directory @@ -31,14 +33,25 @@ class DialogConvert(QtGui.QProgressDialog): self.setMaximum(len(self.book.images)) self.setValue(0) + self.archive = None + if 'cbz' in self.book.outputFormat: + # TODO: switch to API 2, to get rid of the unicode conversions + self.archive = cbz.Archive( + os.path.join(unicode(self.directory), unicode(self.book.title))) + def showEvent(self, event): - if self.timer == None: + if self.timer is None: self.timer = QtCore.QTimer() self.connect(self.timer, QtCore.SIGNAL('timeout()'), self.onTimer) self.timer.start(0) + def closeEvent(self, event): + print "closeEvent" + self.closing.emit() + event.accept() + def onTimer(self): index = self.value() directory = os.path.join(unicode(self.directory), unicode(self.book.title)) @@ -80,6 +93,8 @@ class DialogConvert(QtGui.QProgressDialog): try: if self.book.overwrite or not os.path.isfile(target): image.convertImage(source, target, str(self.book.device), self.book.imageFlags) + if self.archive is not None: + self.archive.addFile(target) except RuntimeError, error: result = QtGui.QMessageBox.critical( self, diff --git a/mangle/options.py b/mangle/options.py index 86926f0..38549da 100644 --- a/mangle/options.py +++ b/mangle/options.py @@ -37,6 +37,8 @@ class DialogOptions(QtGui.QDialog): def moveOptionsToDialog(self): self.lineEditTitle.setText(self.book.title or 'Untitled') self.comboBoxDevice.setCurrentIndex(max(self.comboBoxDevice.findText(self.book.device), 0)) + formats = {'image+cbz' : 0, 'image' : 1, 'cbz' : 2} + self.comboBoxFormat.setCurrentIndex(formats.get(self.book.outputFormat, formats['image+cbz'])) self.checkboxOverwrite.setChecked(self.book.overwrite) self.checkboxOrient.setChecked(self.book.imageFlags & ImageFlags.Orient) self.checkboxResize.setChecked(self.book.imageFlags & ImageFlags.Resize) diff --git a/mangle/resources/ui/options.ui b/mangle/resources/ui/options.ui index 102b1ad..901b7c5 100644 --- a/mangle/resources/ui/options.ui +++ b/mangle/resources/ui/options.ui @@ -7,7 +7,7 @@ 0 0 350 - 350 + 363 @@ -44,6 +44,9 @@ + + QFormLayout::AllNonFixedFieldsGrow + @@ -80,6 +83,32 @@ + + + + Format + + + + + + + + Images & CBZ + + + + + Images only + + + + + CBZ only + + + + From ee8d8ddef78d823d2f3449bcbb75d528b093c8b4 Mon Sep 17 00:00:00 2001 From: Marek Kubica Date: Sun, 30 Oct 2011 12:38:52 +0900 Subject: [PATCH 2/3] Ignore mngl and cbz files --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 0d20b64..d2aa64e 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ *.pyc +*.pyo +*.mngl +*.cbz From fa5c378cb8828d55603d5fda913f71fee6bdaf25 Mon Sep 17 00:00:00 2001 From: Marek Kubica Date: Sun, 30 Oct 2011 18:24:48 +0900 Subject: [PATCH 3/3] Made CBZ-only format work properly --- mangle/convert.py | 17 +++++++++++------ mangle/options.py | 10 +++++++--- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/mangle/convert.py b/mangle/convert.py index b8478c3..d51a300 100644 --- a/mangle/convert.py +++ b/mangle/convert.py @@ -13,7 +13,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import os +import os, shutil + from PyQt4 import QtGui, QtCore import image @@ -23,7 +24,6 @@ import cbz class DialogConvert(QtGui.QProgressDialog): def __init__(self, parent, book, directory): QtGui.QProgressDialog.__init__(self) - #self.setAutoReset(False) self.book = book self.directory = directory @@ -47,10 +47,15 @@ class DialogConvert(QtGui.QProgressDialog): self.timer.start(0) - def closeEvent(self, event): - print "closeEvent" - self.closing.emit() - event.accept() + def hideEvent(self, event): + """Called when the dialog finishes processing.""" + # close the archive if we created a CBZ file + if self.archive is not None: + self.archive.close() + # remove image directory if the user didn't wish for images + if 'image' not in self.book.outputFormat: + path = os.path.join(unicode(self.directory), unicode(self.book.title)) + shutil.rmtree(path) def onTimer(self): index = self.value() diff --git a/mangle/options.py b/mangle/options.py index 38549da..87855b1 100644 --- a/mangle/options.py +++ b/mangle/options.py @@ -25,6 +25,8 @@ class DialogOptions(QtGui.QDialog): def __init__(self, parent, book): QtGui.QDialog.__init__(self, parent) self.book = book + self.formats = {'image+cbz' : 0, 'image' : 1, 'cbz' : 2} + self.reverse_formats = dict((v,k) for k, v in self.formats.iteritems()) ui = uic.loadUi(os.path.join(resources.get_ui_path(), 'options.ui'), self) self.connect(self, QtCore.SIGNAL('accepted()'), self.onAccept) self.moveOptionsToDialog() @@ -37,8 +39,7 @@ class DialogOptions(QtGui.QDialog): def moveOptionsToDialog(self): self.lineEditTitle.setText(self.book.title or 'Untitled') self.comboBoxDevice.setCurrentIndex(max(self.comboBoxDevice.findText(self.book.device), 0)) - formats = {'image+cbz' : 0, 'image' : 1, 'cbz' : 2} - self.comboBoxFormat.setCurrentIndex(formats.get(self.book.outputFormat, formats['image+cbz'])) + self.comboBoxFormat.setCurrentIndex(self.formats.get(self.book.outputFormat, self.formats['image+cbz'])) self.checkboxOverwrite.setChecked(self.book.overwrite) self.checkboxOrient.setChecked(self.book.imageFlags & ImageFlags.Orient) self.checkboxResize.setChecked(self.book.imageFlags & ImageFlags.Resize) @@ -49,6 +50,7 @@ class DialogOptions(QtGui.QDialog): def moveDialogToOptions(self): title = self.lineEditTitle.text() device = self.comboBoxDevice.itemText(self.comboBoxDevice.currentIndex()) + outputFormat = self.reverse_formats[self.comboBoxFormat.currentIndex()] overwrite = self.checkboxOverwrite.isChecked() imageFlags = 0 @@ -65,7 +67,8 @@ class DialogOptions(QtGui.QDialog): self.book.title != title or self.book.device != device or self.book.overwrite != overwrite or - self.book.imageFlags != imageFlags + self.book.imageFlags != imageFlags or + self.book.outputFormat != outputFormat ) if modified: @@ -74,3 +77,4 @@ class DialogOptions(QtGui.QDialog): self.book.device = device self.book.overwrite = overwrite self.book.imageFlags = imageFlags + self.book.outputFormat = outputFormat