[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