pep8 rewriting, version update, todo editing

This commit is contained in:
Kilian Valkhof 2010-04-02 13:51:19 +02:00
parent 0f5092e10b
commit 1106ca482c
4 changed files with 73 additions and 52 deletions

View file

@ -33,3 +33,11 @@ later versions:
again would currently try to recompress all 100, when only 10 would be again would currently try to recompress all 100, when only 10 would be
worthy of trying to compress further. worthy of trying to compress further.
1.1.0 changes:
- use multiprocessing for images
- more robust file handling
- re-adding images now results in recompressing them
- compressing message now shows filename
- wider array of status messages in the table

View file

@ -3,7 +3,7 @@
from distutils.core import setup from distutils.core import setup
setup(name = "trimage", setup(name = "trimage",
version = "1.0.0b3", version = "1.1.0b",
description = "Trimage image compressor - A cross-platform tool for optimizing PNG and JPG files", description = "Trimage image compressor - A cross-platform tool for optimizing PNG and JPG files",
author = "Kilian Valkhof, Paul Chaplin", author = "Kilian Valkhof, Paul Chaplin",
author_email = "help@trimage.org", author_email = "help@trimage.org",

View file

@ -18,7 +18,7 @@ from multiprocessing import cpu_count
from ui import Ui_trimage from ui import Ui_trimage
VERSION = "1.0.0b3" VERSION = "1.1.0b"
class StartQT4(QMainWindow): class StartQT4(QMainWindow):
@ -148,20 +148,21 @@ class StartQT4(QMainWindow):
""" """
delegatorlist = [] delegatorlist = []
for fullpath in images: for fullpath in images:
try: # do not add already existing images again, recompress them instead try: # recompress images already in the list
image=(i.image for i in self.imagelist image = (i.image for i in self.imagelist
if i.image.fullpath == fullpath).next() if i.image.fullpath == fullpath).next()
if image.compressed: if image.compressed:
image.reset() image.reset()
image.recompression=True image.recompression = True
delegatorlist.append(image) delegatorlist.append(image)
except StopIteration: except StopIteration:
image=Image(fullpath) image = Image(fullpath)
if image.valid: if image.valid:
delegatorlist.append(image) delegatorlist.append(image)
self.imagelist.append(ImageRow(image,QIcon(QPixmap(self.ui.get_image("pixmaps/compressing.gif"))))) icon = QIcon(QPixmap(self.ui.get_image("pixmaps/compressing.gif")))
self.imagelist.append(ImageRow(image, icon))
else: else:
print >>sys.stderr, u"[error] %s not a supported image file" % image.fullpath print >> sys.stderr, u"[error] %s not a supported image file" % image.fullpath
self.update_table() self.update_table()
self.thread.compress_file(delegatorlist, self.showapp, self.verbose, self.thread.compress_file(delegatorlist, self.showapp, self.verbose,
@ -237,6 +238,7 @@ class StartQT4(QMainWindow):
else: else:
raise raise
class TriTableModel(QAbstractTableModel): class TriTableModel(QAbstractTableModel):
def __init__(self, parent, imagelist, header, *args): def __init__(self, parent, imagelist, header, *args):
@ -278,29 +280,38 @@ class TriTableModel(QAbstractTableModel):
return QVariant(self.header[col]) return QVariant(self.header[col])
return QVariant() return QVariant()
class ImageRow:
def __init__(self, image, waitingIcon=None):
self.image=image
d={
'shortname': lambda i: self.statusStr() % i.shortname,
'oldfilesizestr': lambda i: size(i.oldfilesize, system=alternative) if i.compressed else "",
'newfilesizestr': lambda i: size(i.newfilesize, system=alternative) if i.compressed else "",
'ratiostr': lambda i:
"%.1f%%" % (100 - (float(i.newfilesize) / i.oldfilesize * 100)) if i.compressed else "",
'icon': lambda i: i.icon if i.compressed else waitingIcon,
'fullpath': lambda i: i.fullpath, #only used by cli class ImageRow:
def __init__(self, image, waitingIcon=None):
""" Build the information visible in the table image row. """
self.image = image
d = {
'shortname': lambda i: self.statusStr() % i.shortname,
'oldfilesizestr': lambda i: size(i.oldfilesize, system=alternative)
if i.compressed else "",
'newfilesizestr': lambda i: size(i.newfilesize, system=alternative)
if i.compressed else "",
'ratiostr': lambda i:
"%.1f%%" % (100 - (float(i.newfilesize) / i.oldfilesize * 100))
if i.compressed else "",
'icon': lambda i: i.icon if i.compressed else waitingIcon,
'fullpath': lambda i: i.fullpath, #only used by cli
} }
for i,n in enumerate(['shortname','oldfilesizestr','newfilesizestr','ratiostr','icon']): names = ['shortname', 'oldfilesizestr', 'newfilesizestr',
d[i]=d[n] 'ratiostr', 'icon']
for i, n in enumerate(names):
d[i] = d[n]
self.d = d self.d = d
def statusStr(self): def statusStr(self):
""" Set the status message. """
if self.image.failed: if self.image.failed:
return "ERROR: %s" return "ERROR: %s"
if self.image.compressing: if self.image.compressing:
return "In Progress..." message = "Compressing %s..."
return message
if not self.image.compressed and self.image.recompression: if not self.image.compressed and self.image.recompression:
return "Queued for recompression..." return "Queued for recompression..."
if not self.image.compressed: if not self.image.compressed:
@ -310,7 +321,9 @@ class ImageRow:
def __getitem__(self, key): def __getitem__(self, key):
return self.d[key](self.image) return self.d[key](self.image)
class Image: class Image:
def __init__(self, fullpath): def __init__(self, fullpath):
""" gather image information. """ """ gather image information. """
self.valid = False self.valid = False
@ -327,40 +340,41 @@ class Image:
def _determinetype(self): def _determinetype(self):
""" Determine the filetype of the file using imghdr. """ """ Determine the filetype of the file using imghdr. """
filetype=determinetype(self.fullpath) filetype = determinetype(self.fullpath)
if filetype in ["jpeg", "png"]: if filetype in ["jpeg", "png"]:
self.filetype=filetype self.filetype = filetype
else: else:
self.filetype=None self.filetype = None
return self.filetype return self.filetype
def reset(self): def reset(self):
self.failed = False self.failed = False
self.compressed = False self.compressed = False
self.compressing = False self.compressing = False
self.recompression= False self.recompression = False
def compress(self): def compress(self):
""" Compress the image and return it to the thread. """ """ Compress the image and return it to the thread. """
if not self.valid: if not self.valid:
raise "Tried to compress invalid image (unsupported format or not file)" raise "Tried to compress invalid image (unsupported format or not \
file)"
self.reset() self.reset()
self.compressing=True self.compressing = True
runString = { runString = {
"jpeg": u"jpegoptim -f --strip-all '%(file)s'", "jpeg": u"jpegoptim -f --strip-all '%(file)s'",
"png" : u"optipng -force -o7 '%(file)s'&&advpng -z4 '%(file)s'"} "png": u"optipng -force -o7 '%(file)s'&&advpng -z4 '%(file)s'"}
try: try:
retcode = call(runString[self.filetype] % {"file": self.fullpath}, retcode = call(runString[self.filetype] % {"file": self.fullpath},
shell = True, stdout=PIPE) shell=True, stdout=PIPE)
except: except:
retcode = -1 retcode = -1
if retcode == 0: if retcode == 0:
self.newfilesize = QFile(self.fullpath).size() self.newfilesize = QFile(self.fullpath).size()
self.compressed=True self.compressed = True
else: else:
self.failed=True self.failed = True
self.compressing=False self.compressing = False
self.retcode=retcode self.retcode = retcode
return self return self
@ -368,7 +382,7 @@ class Worker(QThread):
def __init__(self, parent=None): def __init__(self, parent=None):
QThread.__init__(self, parent) QThread.__init__(self, parent)
self.toDisplay=Queue() self.toDisplay = Queue()
self.threadpool = ThreadPool(max_workers=cpu_count()) self.threadpool = ThreadPool(max_workers=cpu_count())
def __del__(self): def __del__(self):
@ -377,8 +391,10 @@ class Worker(QThread):
def compress_file(self, images, showapp, verbose, imagelist): def compress_file(self, images, showapp, verbose, imagelist):
"""Start the worker thread.""" """Start the worker thread."""
for image in images: for image in images:
time.sleep(0.05) #FIXME: Workaround http://code.google.com/p/pythonthreadpool/issues/detail?id=5 #FIXME:http://code.google.com/p/pythonthreadpool/issues/detail?id=5
self.threadpool.add_job(image.compress, None, return_callback=self.toDisplay.put) time.sleep(0.05)
self.threadpool.add_job(image.compress, None,
return_callback=self.toDisplay.put)
self.showapp = showapp self.showapp = showapp
self.verbose = verbose self.verbose = verbose
self.imagelist = imagelist self.imagelist = imagelist
@ -387,19 +403,20 @@ class Worker(QThread):
def run(self): def run(self):
"""Compress the given file, get data from it and call update_table.""" """Compress the given file, get data from it and call update_table."""
tp = self.threadpool tp = self.threadpool
while self.showapp or not (tp._ThreadPool__active_worker_count==0 and tp._ThreadPool__jobs.empty()): while self.showapp or not (tp._ThreadPool__active_worker_count == 0 and
tp._ThreadPool__jobs.empty()):
image = self.toDisplay.get() image = self.toDisplay.get()
self.emit(SIGNAL("updateUi")) self.emit(SIGNAL("updateUi"))
if not self.showapp and self.verbose: # we work via the commandline if not self.showapp and self.verbose: # we work via the commandline
if image.retcode==0: if image.retcode == 0:
ir=ImageRow(image) ir = ImageRow(image)
print("File: " + ir['fullpath'] + ", Old Size: " print("File: " + ir['fullpath'] + ", Old Size: "
+ ir['oldfilesizestr'] + ", New Size: " + ir['newfilesizestr'] + ir['oldfilesizestr'] + ", New Size: "
+ ", Ratio: " + ir['ratiostr']) + ir['newfilesizestr'] + ", Ratio: " + ir['ratiostr'])
else: else:
print >>sys.stderr, u"[error] %s could not be compressed" % image.fullpath print >> sys.stderr, u"[error] %s could not be compressed" % image.fullpath
if __name__ == "__main__": if __name__ == "__main__":
app = QApplication(sys.argv) app = QApplication(sys.argv)

View file

@ -69,7 +69,7 @@
<body> <body>
<div id="wrap"> <div id="wrap">
<h1><img src="trimage-icon.png" alt=""> Trimage image compressor &ndash; 1.0.0b3 (beta)</h1> <h1><img src="trimage-icon.png" alt=""> Trimage image compressor &ndash; 1.1.0b (beta)</h1>
<span class="subtitle">A cross-platform tool for losslessly optimizing PNG and JPG files.</span> <span class="subtitle">A cross-platform tool for losslessly optimizing PNG and JPG files.</span>
<p class="tri">Trimage is a cross-platform GUI and command-line interface to optimize image <p class="tri">Trimage is a cross-platform GUI and command-line interface to optimize image
files via <a href="http://optipng.sourceforge.net/">optipng</a>, files via <a href="http://optipng.sourceforge.net/">optipng</a>,
@ -165,16 +165,12 @@
</div> </div>
<h2>Planned features</h2> <h2>Planned features</h2>
<p>Version 1.0.0 final:</p> <p>Version 1.1.0 final:</p>
<ul> <ul>
<li>Expand command line options</li> <li>Expand command line options</li>
<li>Make sure a compressed file is always smaller than the original one, or don't compress</li> <li>Make sure a compressed file is always smaller than the original one, or don't compress</li>
<li>General refactoring</li> <li>General refactoring</li>
</ul> </ul>
<p>Version 1.1.0</p>
<ul>
<li>Use multiprocessing instead of threading</li>
</ul>
<p>Beyond that</p> <p>Beyond that</p>
<ul> <ul>
<li>Deletion of rows in the table view</li> <li>Deletion of rows in the table view</li>