def startImageCycling(self, index): """ Start frame cycling on a cell at <index> :parameters: index : QtCore.QModelIndex the model index to start frame cycling on """ if self.__imageCyclingEnabled and index.isValid( ) and index != self.__cycleIndex: # stop cycling on old index self.stopImageCycling() newRect = self._thumbnailRect(index) if newRect.isValid(): filename = str(index.data()) if not common.imageFormatIsAnimatable( filename) or not os.path.isfile(filename): return scaledImage = index.data(role=self.ROLE_SCALED_IMAGE) # On OSX 10.9 PyQt 4.10 replaces null QImages with QPyNullVariants when retreiving them from a model if scaledImage is None or not isinstance( scaledImage, QtGui.QImage) or scaledImage.isNull(): return # make the index widget ( QLabel displaying a QMovie ) movieLabel = QtGui.QLabel() movie = QtGui.QMovie(filename, parent=movieLabel) movie.setCacheMode(QtGui.QMovie.CacheAll) # QMovie bug?, jumpToNextFrame() will only return False for static images after it has been called more than once movie.jumpToNextFrame() # if there is no frame 1, then it is a static image, so abort. # this must be done after it has been set and started playing # or the QMovie has no frame attributes if movie.jumpToNextFrame() is False: self.stopImageCycling() return # movieLabel.setFrameStyle( QtGui.QFrame.Box ) movieLabel.setSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) newSize = scaledImage.size() movie.setScaledSize(newSize) movieLabel.setFixedSize(newSize) movieLabel.setMovie(movie) # start playing movie.start() self.__cycleIndex = QtCore.QPersistentModelIndex(index) # set the new index widget self._view.setIndexWidget(index, movieLabel) # move to center of cell movieLabel.move( movieLabel.pos().x() + ((newRect.width() / 2) - (newSize.width() / 2)), movieLabel.pos().y())
def __init__(self, view): """ Initialiser :parameters: view : QtGui.QAbstractItemView The view that this delegate acts upon """ super(Delegate, self).__init__(view) self._view = view self.__viewStyle = None self.__shadedSortColumn = False self.__imageCellAspectRatio = 16.0 / 9 self.__imageLoader = ImageLoader() self.__imageLoader.imageLoaded.connect(self.__imageLoaded) # image cycling self.__cycleIndex = QtCore.QPersistentModelIndex(QtCore.QModelIndex()) self.__imageCyclingEnabled = True
def stopImageCycling(self): """ Stop frame cycling on a cell at <index> :parameters: index : QtCore.QModelIndex the model index to stop frame cycling on """ cycleIndex = QtCore.QModelIndex(self.__cycleIndex) indexWidget = self._view.indexWidget(cycleIndex) if indexWidget is not None: # index widget could be set to something different in subclasses, so we can't be sure movie = indexWidget.movie() if hasattr(indexWidget, 'movie') else None if movie is not None: movie.stop() indexWidget.close() self._view.setIndexWidget(cycleIndex, None) self.__cycleIndex = QtCore.QPersistentModelIndex( QtCore.QModelIndex())
def _paintImage(self, painter, option, index): """ Draw an image in the cell :parameters: painter : QtGui.QPainter painter to draw the image with option : QtGui.QStyleOption style information index : QtCore.QModelIndex index if the cell to draw """ # using old method for now imageFile = index.data() if not imageFile: return model = index.model() # only load an image where one hasn't already been loaded origImage = image = index.data(role=common.ROLE_IMAGE) origScaledImage = scaledImage = index.data(role=self.ROLE_SCALED_IMAGE) origFailedImage = failedImage = index.data(role=self.ROLE_FAILED_IMAGE) # On OSX 10.9 PyQt 4.10 replaces null QImages with QPyNullVariants when retreiving them from a model if image is not None and not isinstance(image, QtGui.QImage): image = QtGui.QImage() if scaledImage is not None and not isinstance(scaledImage, QtGui.QImage): scaledImage = QtGui.QImage() if not failedImage: if image is None: # if it's a null image or a loading image, load it. scaledImage = image = self.__imageLoader.loadImage( imageFile, None, QtCore.QPersistentModelIndex(index)) # if it's not a null image or a loading image... if not image.isNull(): if scaledImage is None: scaledImage = image scaledImageSize = scaledImage.size() targetSize = option.rect.size().boundedTo(image.size()) targetSize.setHeight( int(targetSize.width() / self.__imageCellAspectRatio)) if scaledImageSize.width() != targetSize.width( ) and scaledImageSize.height() != targetSize.height(): scaledImage = image.scaled(targetSize, QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation) else: failedImage = True # if <image> is null, set scaled image to null as well # this would make null images show up as failed, we could maybe have a more neutral icon? # scaledImage = self.__imageLoader._imageMissingLrg # update model data dataUpdateMap = {} if origImage is not image: dataUpdateMap[common.ROLE_IMAGE] = image if origScaledImage is not scaledImage: dataUpdateMap[self.ROLE_SCALED_IMAGE] = scaledImage if origFailedImage != failedImage: dataUpdateMap[self.ROLE_FAILED_IMAGE] = failedImage if dataUpdateMap: model.setItemData(index, dataUpdateMap) # center the image in the cell targetRect = scaledImage.rect() targetRect.moveCenter(option.rect.center()) # draw the image painter.save() painter.drawImage(targetRect, scaledImage) # Image cycling icon ( test ) # if common.imageFormatIsAnimatable( imageFile ) and os.path.isfile( imageFile ): # animIcon = QtGui.QImage( common.ICON_CLAPBOARD_SML ) # animIconSize = animIcon.size() # brPoint = targetRect.bottomRight() - QtCore.QPoint( animIconSize.width(), animIconSize.height() ) # painter.drawImage( brPoint, animIcon ) # TODO proper icon painter.restore()