diff --git a/meshroom/ui/components/thumbnail.py b/meshroom/ui/components/thumbnail.py index db918bec..c646df9c 100644 --- a/meshroom/ui/components/thumbnail.py +++ b/meshroom/ui/components/thumbnail.py @@ -49,8 +49,10 @@ class ThumbnailCache(QObject): maxThumbnailsOnDisk = 100000 # Signal to notify listeners that a thumbnail was created and written on disk - # This signal has one argument: the url of the image that the thumbnail is associated to - thumbnailCreated = Signal(QUrl) + # This signal has two argument: + # - the url of the image that the thumbnail is associated to + # - an identifier for the caller, e.g. the component that sent the request (useful for faster dispatch in QML) + thumbnailCreated = Signal(QUrl, int) # Thread pool for running createThumbnail asynchronously on a fixed number of worker threads pool = ThreadPool(processes=3) @@ -93,15 +95,16 @@ class ThumbnailCache(QObject): path = os.path.join(ThumbnailCache.thumbnailDir, f'{digest}.jpg') return path - @Slot(QUrl, result=QUrl) - def thumbnail(self, imgSource): + @Slot(QUrl, int, result=QUrl) + def thumbnail(self, imgSource, callerID): """Retrieve the filepath of the thumbnail corresponding to a given image. If the thumbnail does not exist on disk, it will be created asynchronously. - When this is done, the createdThumbnail signal is emitted. + When this is done, the thumbnailCreated signal is emitted. Args: imgSource (QUrl): location of the input image + callerID (int): identifier for the object that requested the thumbnail Returns: QUrl: location of the corresponding thumbnail if it exists, otherwise None @@ -121,14 +124,15 @@ class ThumbnailCache(QObject): # Thumbnail does not exist # create it in a worker thread to avoid UI freeze - ThumbnailCache.pool.apply_async(self.createThumbnail, args=(imgSource,)) + ThumbnailCache.pool.apply_async(self.createThumbnail, args=(imgSource,callerID,)) return None - def createThumbnail(self, imgSource): + def createThumbnail(self, imgSource, callerID): """Load an image, resize it to thumbnail dimensions and save the result in the cache directory. Args: imgSource (QUrl): location of the input image + callerID (int): identifier for the object that requested the thumbnail """ imgPath = imgSource.toLocalFile() path = ThumbnailCache.thumbnailPath(imgPath) @@ -155,7 +159,7 @@ class ThumbnailCache(QObject): logging.error(f'[ThumbnailCache] Error when writing thumbnail: {writer.errorString()}') # Notify listeners - self.thumbnailCreated.emit(imgSource) + self.thumbnailCreated.emit(imgSource, callerID) @staticmethod def clean(): diff --git a/meshroom/ui/qml/ImageGallery/ImageDelegate.qml b/meshroom/ui/qml/ImageGallery/ImageDelegate.qml index ac770669..734b8f71 100644 --- a/meshroom/ui/qml/ImageGallery/ImageDelegate.qml +++ b/meshroom/ui/qml/ImageGallery/ImageDelegate.qml @@ -11,6 +11,7 @@ Item { id: root property variant viewpoint + property int cellID property bool isCurrentItem: false property alias source: _viewpoint.source property alias metadata: _viewpoint.metadata @@ -34,7 +35,7 @@ Item { // update thumbnail location // can be called from the GridView when a new thumbnail has been written on disk function updateThumbnail() { - thumbnail.source = ThumbnailCache.thumbnail(root.source); + thumbnail.source = ThumbnailCache.thumbnail(root.source, cellID); } onSourceChanged: { updateThumbnail(); diff --git a/meshroom/ui/qml/ImageGallery/ImageGallery.qml b/meshroom/ui/qml/ImageGallery/ImageGallery.qml index ac519c91..8ad0da94 100644 --- a/meshroom/ui/qml/ImageGallery/ImageGallery.qml +++ b/meshroom/ui/qml/ImageGallery/ImageGallery.qml @@ -203,12 +203,10 @@ Panel { // Update grid item when corresponding thumbnail is computed Connections { target: ThumbnailCache - function onThumbnailCreated(imgSource) { - for (let i = 0; i < grid.count; i++) { - let item = grid.itemAtIndex(i); // item is an ImageDelegate - if (item && item.source == imgSource) { - item.updateThumbnail(); - } + function onThumbnailCreated(imgSource, callerID) { + let item = grid.itemAtIndex(callerID); // item is an ImageDelegate + if (item && item.source == imgSource) { + item.updateThumbnail(); } } } @@ -257,6 +255,7 @@ Panel { id: imageDelegate viewpoint: object.value + cellID: DelegateModel.filteredIndex width: grid.cellWidth height: grid.cellHeight readOnly: m.readOnly