From 5782698dda2baf3039a8f6fde08c3998058284cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A1lm=C3=A1n=20Tarnay?= Date: Fri, 2 Apr 2010 07:18:18 +0200 Subject: [PATCH 1/5] Lots of fixes/changes there - ImageRow - Recompress fixed - Adding a file again recompresses it - Status indicators - cli working again - more crash resistant --- src/trimage/trimage.py | 127 ++++++++++++++++++++++++++--------------- 1 file changed, 81 insertions(+), 46 deletions(-) diff --git a/src/trimage/trimage.py b/src/trimage/trimage.py index a8963c4..0a8b4cd 100755 --- a/src/trimage/trimage.py +++ b/src/trimage/trimage.py @@ -132,19 +132,11 @@ class StartQT4(QMainWindow): # this is a fix for file dialog differentiating between cases "Image files (*.png *.jpg *.jpeg *.PNG *.JPG *.JPEG)") - imagelist = [] - for i, image in enumerate(images): - imagelist.append(unicode(image)) - - self.delegator(imagelist) + self.delegator([unicode(fullpath) for fullpath in images]) def recompress_files(self): """Send each file in the current file list to compress_file again.""" - newimagelist = [] - for image in self.imagelist: - newimagelist.append(image[4]) - self.imagelist = [] - self.delegator(newimagelist) + self.delegator([row.image.fullpath for row in self.imagelist]) """ Compress functions @@ -155,14 +147,21 @@ class StartQT4(QMainWindow): Recieve all images, check them and send them to the worker thread. """ delegatorlist = [] - for image in images: - image=Image(image) - if image.valid: - delegatorlist.append(image) - self.imagelist.append(("Compressing...", "", "", "", image, - QIcon(QPixmap(self.ui.get_image("pixmaps/compressing.gif"))))) - else: - print >>sys.stderr, u"[error] %s not a supported image file" % image.fullpath + for fullpath in images: + try: # do not add already existing images again, recompress them instead + image=(i.image for i in self.imagelist + if i.image.fullpath == fullpath).next() + if image.compressed: + image.reset() + image.recompression=True + delegatorlist.append(image) + except StopIteration: + image=Image(fullpath) + if image.valid: + delegatorlist.append(image) + self.imagelist.append(ImageRow(image,QIcon(QPixmap(self.ui.get_image("pixmaps/compressing.gif"))))) + else: + print >>sys.stderr, u"[error] %s not a supported image file" % image.fullpath self.update_table() self.thread.compress_file(delegatorlist, self.showapp, self.verbose, @@ -267,7 +266,7 @@ class TriTableModel(QAbstractTableModel): return QVariant(data) elif index.column() == 0 and role == Qt.DecorationRole: # decorate column 0 with an icon of the image itself - f_icon = self.imagelist[index.row()][5] + f_icon = self.imagelist[index.row()][4] return QVariant(f_icon) else: return QVariant() @@ -278,18 +277,51 @@ class TriTableModel(QAbstractTableModel): role == Qt.DecorationRole): return QVariant(self.header[col]) 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 + } + for i,n in enumerate(['shortname','oldfilesizestr','newfilesizestr','ratiostr','icon']): + d[i]=d[n] + + self.d = d + + def statusStr(self): + if self.image.failed: + return "ERROR: %s" + if self.image.compressing: + return "In Progress..." + if not self.image.compressed and self.image.recompression: + return "Queued for recompression..." + if not self.image.compressed: + return "Queued..." + return "%s" + + def __getitem__(self, key): + return self.d[key](self.image) class Image: def __init__(self, fullpath): self.valid = False + self.reset() self.fullpath = fullpath if path.isfile(self.fullpath): self.filetype = determinetype(self.fullpath) if self.filetype in ["jpeg", "png"]: oldfile = QFileInfo(self.fullpath) self.shortname = oldfile.fileName() - self.oldfilesize = oldfile.size() - self.icon = QIcon(self.fullpath) + self.oldfilesize = oldfile.size() + self.icon = QIcon(self.fullpath) self.valid = True def _determinetype(self): @@ -300,19 +332,35 @@ class Image: self.filetype=None return self.filetype + def reset(self): + self.failed = False + self.compressed = False + self.compressing = False + self.recompression= False + def compress(self): if not self.valid: raise "Tried to compress invalid image (unsupported format or not file)" + self.reset() + self.compressing=True runString = { "jpeg": u"jpegoptim -f --strip-all '%(file)s'", "png" : u"optipng -force -o7 '%(file)s'&&advpng -z4 '%(file)s'"} - retcode = call(runString[self.filetype] % {"file": self.fullpath}, - shell = True, stdout=PIPE) + try: + retcode = call(runString[self.filetype] % {"file": self.fullpath}, + shell = True, stdout=PIPE) + except: + retcode = -1 if retcode == 0: self.newfilesize = QFile(self.fullpath).size() + self.compressed=True + else: + self.failed=True + self.compressing=False self.retcode=retcode return self + class Worker(QThread): def __init__(self, parent=None): @@ -336,31 +384,18 @@ class Worker(QThread): def run(self): """Compress the given file, get data from it and call update_table.""" tp = self.threadpool - while self.showapp or not (tp.__active_workers==0 and tp.__jobs.empty()): + while self.showapp or not (tp._ThreadPool__active_worker_count==0 and tp._ThreadPool__jobs.empty()): image = self.toDisplay.get() - if image.retcode==0: - #calculate ratio and make a nice string - oldfilesizestr = size(image.oldfilesize, system=alternative) - newfilesizestr = size(image.newfilesize, system=alternative) - ratio = 100 - (float(image.newfilesize) / float(image.oldfilesize) * 100) - ratiostr = "%.1f%%" % ratio + self.emit(SIGNAL("updateUi")) - # append current image to list - for i, listitem in enumerate(self.imagelist): - if listitem[4] == image: - self.imagelist.remove(listitem) - self.imagelist.insert(i, (image.shortname, oldfilesizestr, - newfilesizestr, ratiostr, image.fullpath, image.icon)) - - self.emit(SIGNAL("updateUi")) - - if not self.showapp and self.verbose: - # we work via the commandline - print("File: " + image.fullpath + ", Old Size: " - + oldfilesizestr + ", New Size: " + newfilesizestr - + ", Ratio: " + ratiostr) - else: - print >>sys.stderr, u"[error] %s could not be compressed" % image.fullpath + if not self.showapp and self.verbose: # we work via the commandline + if image.retcode==0: + ir=ImageRow(image) + print("File: " + ir['fullpath'] + ", Old Size: " + + ir['oldfilesizestr'] + ", New Size: " + ir['newfilesizestr'] + + ", Ratio: " + ir['ratiostr']) + else: + print >>sys.stderr, u"[error] %s could not be compressed" % image.fullpath class TrimageTableView(QTableView): From 97956d7e14c85e462aedf12d00562f0693c53793 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A1lm=C3=A1n=20Tarnay?= Date: Fri, 2 Apr 2010 07:22:50 +0200 Subject: [PATCH 2/5] removed multiprocessing from todo --- resources/todo | 4 ---- 1 file changed, 4 deletions(-) diff --git a/resources/todo b/resources/todo index 43dbe42..a215d43 100644 --- a/resources/todo +++ b/resources/todo @@ -15,10 +15,6 @@ todo app wise todo else - figure out how to make mac and win versions (someone else :) <- via gui2exe -todo later -- use multiprocessing lib to take advantage of multicore/multi-CPU to compress - multiple files simultaneously (threads have issues in Python; see "GIL") - =========================================== later versions: animate compressing.gif From cf9d98027c56930cb57286ed48991d7e4b3db581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A1lm=C3=A1n=20Tarnay?= Date: Fri, 2 Apr 2010 07:24:00 +0200 Subject: [PATCH 3/5] changed hint text for recompress button to indicate that it recompresses all --- resources/window.ui | 2 +- src/trimage/ui.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/window.ui b/resources/window.ui index 066032f..bf5310d 100644 --- a/resources/window.ui +++ b/resources/window.ui @@ -127,7 +127,7 @@ PointingHandCursor - Recompress selected images + Recompress all images &Recompress diff --git a/src/trimage/ui.py b/src/trimage/ui.py index d644299..86caee8 100644 --- a/src/trimage/ui.py +++ b/src/trimage/ui.py @@ -153,7 +153,7 @@ class Ui_trimage(object): "Drag and drop images onto the table", None, QApplication.UnicodeUTF8)) self.recompress.setToolTip(QApplication.translate("trimage", - "Recompress selected images", None, QApplication.UnicodeUTF8)) + "Recompress all images", None, QApplication.UnicodeUTF8)) self.recompress.setText(QApplication.translate("trimage", "&Recompress", None, QApplication.UnicodeUTF8)) self.recompress.setShortcut(QApplication.translate("trimage", From 51691351d354268f5c8a1a736770bf02234c7b80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A1lm=C3=A1n=20Tarnay?= Date: Fri, 2 Apr 2010 07:25:10 +0200 Subject: [PATCH 4/5] swapped my first name and last name --- website/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/index.html b/website/index.html index b439856..2bd205d 100644 --- a/website/index.html +++ b/website/index.html @@ -123,7 +123,7 @@
  • Neil Wallace
  • Jeroen Goudsmit
  • -
  • Kálmán Tarnay
  • +
  • Tarnay Kálmán
From 29be211a9df1aeee4a55644479fa3249525aafac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A1lm=C3=A1n=20Tarnay?= Date: Fri, 2 Apr 2010 07:27:16 +0200 Subject: [PATCH 5/5] license --- trimage | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trimage b/trimage index 05e6139..6906ad3 100644 --- a/trimage +++ b/trimage @@ -1,6 +1,6 @@ #!/usr/bin/env python # -#Copyright (c) 2010 Kilian Valkhof, Paul Chaplin +#Copyright (c) 2010 Kilian Valkhof, Paul Chaplin, Tarnay Kálmán # #Permission is hereby granted, free of charge, to any person #obtaining a copy of this software and associated documentation