[PyKDE] QIconView to display Thumbnails.
Gordon Tyler
gordon at doxxx.net
Mon Jan 13 17:13:01 GMT 2003
(CC'ing the list just in case somebody else finds this useful)
Olivier Roulet wrote:
> That is in fact the design I started to use but then
> for other reasons I changed to a queuing mechanisme.
> And with your current version you do not get any
> troubles with more than 500<> picture ?
I haven't tried with a directory of that size. Most of my directories
are at most 50 images.
> May I ask if it is possible to see you code ? .
> I do not make any commercial application :-)
> It is just for personal use.
Sure. I was going to release it open source at some point when I was
happy with it.
Here are some snippets from my code. I didn't send the whole thing
because it's almost a thousand lines and most of it's entirely unrelated
to the problem at hand.
ThumbnailView is a QIconView subclass which, given a directory, will
display a list of thumbnails for all the image files in that directory.
It caches the thumbnail images for faster loading the next time that
same directory is used. ThumbnailView.setDirectory is what starts the
whole process.
You'll notice that there's a lot of qApp.lock and unlock calls.
Basically, any time the code has to interact with a Qt object that could
possibly be in use by the Qt event loop on the main thread, it has to
call QApplication.lock to stop the event processing thread from doing
anything and then unlock once it's done. Without this, the app _will_
segfault. The lock/unlock sections also have to be fairly fine-grained
otherwise the responsiveness of the app (which is what I was trying to
gain with a background loading thread) is badly affected.
######################################################
class ThumbnailLoaderThread(QThread):
def __init__(self, view):
QThread.__init__(self)
self.view = view
def run(self):
self.view.loadThumbnails()
class ThumbnailView(QIconView):
def __init__(self, parent):
QIconView.__init__(self, parent)
self.unknownIcon = QPixmap(QImage(os.path.join(DATA_DIR,
"unknown.png")))
# ... more init stuff ...
def setDirectory(self, directory):
if self.tlt: # thumbnail loader thread
self.cancelLoadingThumbnails()
qApp.unlock()
self.tlt.wait()
qApp.lock()
self.clear()
self.directory = directory
if not directory:
return
if not os.path.exists(directory):
return
files = os.listdir(directory)
for file in files:
path = os.path.join(directory, file)
if os.path.isfile(path) and file[-3:].upper() in
SUPPORTED_FORMATS:
self.addThumbnail(path)
qApp.processEvents()
self.tlt = ThumbnailLoaderThread(self)
self.tlt.start()
self.tlt.wait(100) # this is very necessary, otherwise it segfaults
def addThumbnail(self, path):
item = QIconViewItem(self, os.path.basename(path),
self.unknownIcon)
item.setKey(path)
def loadThumbnails(self):
self.cancelLoadingThumbnailsFlag = False
qApp.lock()
self.emit(PYSIGNAL("startedLoading"), (self.count(),))
qApp.unlock()
item = self.firstItem()
i = 0
while item:
path = str(item.key())
if os.path.isfile(path):
if self.cancelLoadingThumbnailsFlag:
break
# try to load a cached thumbnail image
thumbnail = self.loadThumbnail(path)
if not thumbnail:
if self.cancelLoadingThumbnailsFlag:
break
# make a new thumbnail image
thumbnail = self.makeThumbnail(path)
if self.cancelLoadingThumbnailsFlag:
break
if thumbnail:
# cache the thumbnail image to disk
self.saveThumbnail(thumbnail, path)
if self.cancelLoadingThumbnailsFlag:
break
if thumbnail:
# Set the current QListViewItem's pixmap
icon = QPixmap()
icon.convertFromImage(thumbnail)
qApp.lock()
item.setPixmap(icon)
qApp.unlock()
item = item.nextItem()
i += 1
qApp.lock()
self.emit(PYSIGNAL("loadedThumbnail"), (i, path))
qApp.unlock()
qApp.lock()
self.emit(PYSIGNAL("finishedLoading"), ())
if not self.cancelLoadingThumbnailsFlag:
# Select the first item
first = self.firstItem()
if first and self.currentItem() and not
self.currentItem().isSelecte
d():
self.setSelected(first, True, False)
qApp.unlock()
######################################################
Ciao,
Gordon
More information about the PyQt
mailing list