Merge pull request #7 from Leonidas-from-XIV/cbz-support

CBZ support
This commit is contained in:
Alex Yatskov 2011-10-30 07:10:07 -07:00
commit ab3f968adc
6 changed files with 107 additions and 6 deletions

3
.gitignore vendored
View File

@ -1 +1,4 @@
*.pyc *.pyc
*.pyo
*.mngl
*.cbz

View File

@ -24,10 +24,11 @@ from about import DialogAbout
from options import DialogOptions from options import DialogOptions
from convert import DialogConvert from convert import DialogConvert
class Book: class Book(object):
DefaultDevice = 'Kindle 3' DefaultDevice = 'Kindle 3'
DefaultOverwrite = True DefaultOverwrite = True
DefaultImageFlags = ImageFlags.Orient | ImageFlags.Resize | ImageFlags.Quantize DefaultImageFlags = ImageFlags.Orient | ImageFlags.Resize | ImageFlags.Quantize
DefaultOutputFormat = 'image+cbz'
def __init__(self): def __init__(self):
@ -38,6 +39,7 @@ class Book:
self.device = Book.DefaultDevice self.device = Book.DefaultDevice
self.overwrite = Book.DefaultOverwrite self.overwrite = Book.DefaultOverwrite
self.imageFlags = Book.DefaultImageFlags self.imageFlags = Book.DefaultImageFlags
self.outputFormat = Book.DefaultOutputFormat
def save(self, filename): def save(self, filename):
@ -50,6 +52,7 @@ class Book:
root.setAttribute('overwrite', 'true' if self.overwrite else 'false') root.setAttribute('overwrite', 'true' if self.overwrite else 'false')
root.setAttribute('device', self.device) root.setAttribute('device', self.device)
root.setAttribute('imageFlags', self.imageFlags) root.setAttribute('imageFlags', self.imageFlags)
root.setAttribute('outputFormat', self.outputFormat)
for filenameImg in self.images: for filenameImg in self.images:
itemImg = document.createElement('image') itemImg = document.createElement('image')
@ -89,13 +92,14 @@ class Book:
self.title = root.attribute('title', 'Untitled') self.title = root.attribute('title', 'Untitled')
self.overwrite = root.attribute('overwrite', 'true' if Book.DefaultOverwrite else 'false') == 'true' self.overwrite = root.attribute('overwrite', 'true' if Book.DefaultOverwrite else 'false') == 'true'
self.device = root.attribute('device', Book.DefaultDevice) self.device = root.attribute('device', Book.DefaultDevice)
self.outputFormat = root.attribute('outputFormat', 'image+cbz')
self.imageFlags = int(root.attribute('imageFlags', str(Book.DefaultImageFlags))) self.imageFlags = int(root.attribute('imageFlags', str(Book.DefaultImageFlags)))
self.filename = filename self.filename = filename
self.modified = False self.modified = False
self.images = [] self.images = []
items = root.elementsByTagName('image') items = root.elementsByTagName('image')
if items == None: if items is None:
return return
for i in xrange(0, len(items)): for i in xrange(0, len(items)):

39
mangle/cbz.py Normal file
View File

@ -0,0 +1,39 @@
# Copyright (C) 2011 Marek Kubica <marek@xivilization.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
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()

View File

@ -13,10 +13,12 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import os import os, shutil
from PyQt4 import QtGui, QtCore from PyQt4 import QtGui, QtCore
import image import image
import cbz
class DialogConvert(QtGui.QProgressDialog): class DialogConvert(QtGui.QProgressDialog):
@ -31,14 +33,30 @@ class DialogConvert(QtGui.QProgressDialog):
self.setMaximum(len(self.book.images)) self.setMaximum(len(self.book.images))
self.setValue(0) 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): def showEvent(self, event):
if self.timer == None: if self.timer is None:
self.timer = QtCore.QTimer() self.timer = QtCore.QTimer()
self.connect(self.timer, QtCore.SIGNAL('timeout()'), self.onTimer) self.connect(self.timer, QtCore.SIGNAL('timeout()'), self.onTimer)
self.timer.start(0) self.timer.start(0)
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): def onTimer(self):
index = self.value() index = self.value()
directory = os.path.join(unicode(self.directory), unicode(self.book.title)) directory = os.path.join(unicode(self.directory), unicode(self.book.title))
@ -80,6 +98,8 @@ class DialogConvert(QtGui.QProgressDialog):
try: try:
if self.book.overwrite or not os.path.isfile(target): if self.book.overwrite or not os.path.isfile(target):
image.convertImage(source, target, str(self.book.device), self.book.imageFlags) image.convertImage(source, target, str(self.book.device), self.book.imageFlags)
if self.archive is not None:
self.archive.addFile(target)
except RuntimeError, error: except RuntimeError, error:
result = QtGui.QMessageBox.critical( result = QtGui.QMessageBox.critical(
self, self,

View File

@ -25,6 +25,8 @@ class DialogOptions(QtGui.QDialog):
def __init__(self, parent, book): def __init__(self, parent, book):
QtGui.QDialog.__init__(self, parent) QtGui.QDialog.__init__(self, parent)
self.book = book 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) ui = uic.loadUi(os.path.join(resources.get_ui_path(), 'options.ui'), self)
self.connect(self, QtCore.SIGNAL('accepted()'), self.onAccept) self.connect(self, QtCore.SIGNAL('accepted()'), self.onAccept)
self.moveOptionsToDialog() self.moveOptionsToDialog()
@ -37,6 +39,7 @@ class DialogOptions(QtGui.QDialog):
def moveOptionsToDialog(self): def moveOptionsToDialog(self):
self.lineEditTitle.setText(self.book.title or 'Untitled') self.lineEditTitle.setText(self.book.title or 'Untitled')
self.comboBoxDevice.setCurrentIndex(max(self.comboBoxDevice.findText(self.book.device), 0)) self.comboBoxDevice.setCurrentIndex(max(self.comboBoxDevice.findText(self.book.device), 0))
self.comboBoxFormat.setCurrentIndex(self.formats.get(self.book.outputFormat, self.formats['image+cbz']))
self.checkboxOverwrite.setChecked(self.book.overwrite) self.checkboxOverwrite.setChecked(self.book.overwrite)
self.checkboxOrient.setChecked(self.book.imageFlags & ImageFlags.Orient) self.checkboxOrient.setChecked(self.book.imageFlags & ImageFlags.Orient)
self.checkboxResize.setChecked(self.book.imageFlags & ImageFlags.Resize) self.checkboxResize.setChecked(self.book.imageFlags & ImageFlags.Resize)
@ -47,6 +50,7 @@ class DialogOptions(QtGui.QDialog):
def moveDialogToOptions(self): def moveDialogToOptions(self):
title = self.lineEditTitle.text() title = self.lineEditTitle.text()
device = self.comboBoxDevice.itemText(self.comboBoxDevice.currentIndex()) device = self.comboBoxDevice.itemText(self.comboBoxDevice.currentIndex())
outputFormat = self.reverse_formats[self.comboBoxFormat.currentIndex()]
overwrite = self.checkboxOverwrite.isChecked() overwrite = self.checkboxOverwrite.isChecked()
imageFlags = 0 imageFlags = 0
@ -63,7 +67,8 @@ class DialogOptions(QtGui.QDialog):
self.book.title != title or self.book.title != title or
self.book.device != device or self.book.device != device or
self.book.overwrite != overwrite or self.book.overwrite != overwrite or
self.book.imageFlags != imageFlags self.book.imageFlags != imageFlags or
self.book.outputFormat != outputFormat
) )
if modified: if modified:
@ -72,3 +77,4 @@ class DialogOptions(QtGui.QDialog):
self.book.device = device self.book.device = device
self.book.overwrite = overwrite self.book.overwrite = overwrite
self.book.imageFlags = imageFlags self.book.imageFlags = imageFlags
self.book.outputFormat = outputFormat

View File

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>350</width> <width>350</width>
<height>350</height> <height>363</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -44,6 +44,9 @@
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
<item> <item>
<layout class="QFormLayout" name="formLayout_2"> <layout class="QFormLayout" name="formLayout_2">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="label_2"> <widget class="QLabel" name="label_2">
<property name="text"> <property name="text">
@ -80,6 +83,32 @@
</item> </item>
</widget> </widget>
</item> </item>
<item row="1" column="0">
<widget class="QLabel" name="labelFormat">
<property name="text">
<string>Format</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="comboBoxFormat">
<item>
<property name="text">
<string>Images &amp; CBZ</string>
</property>
</item>
<item>
<property name="text">
<string>Images only</string>
</property>
</item>
<item>
<property name="text">
<string>CBZ only</string>
</property>
</item>
</widget>
</item>
</layout> </layout>
</item> </item>
<item> <item>