import shiboken2
from PySide2 import QtCore, QtGui, QtWidgets


class RectangleHoverEffect(QtCore.QObject):
    def __init__(self, rectangle, parent):
        super().__init__(parent)
        if not isinstance(rectangle, QtWidgets.QWidget):
            raise TypeError(f"{rectangle} must be a QWidget")
        if rectangle.parent() is None:
            raise ValueError(f"{rectangle} must have a parent")
        self.m_rectangle = rectangle
        self.m_rectangle.parent().installEventFilter(self)
        self.m_animation = QtCore.QPropertyAnimation(
            self,
            targetObject=self.m_rectangle,
            propertyName=b"pos",
            duration=300,
            easingCurve=QtCore.QEasingCurve.OutQuad,
        )


    def eventFilter(self, obj, event):
        if shiboken2.isValid(self.m_rectangle):
            if self.m_rectangle.parent() is obj:
                y0 = self.m_rectangle.parent().height()
                y1 = self.m_rectangle.parent().height() - self.m_rectangle.height()

                if event.type() == QtCore.QEvent.MouseButtonPress:
                    self._start_animation(y0, y1)
                elif event.type() == QtCore.QEvent.MouseButtonRelease:
                    self._start_animation(y1, y0)
        return super().eventFilter(obj, event)

    def _start_animation(self, y0, y1):
        self.m_animation.setStartValue(QtCore.QPoint(0, y0))
        self.m_animation.setEndValue(QtCore.QPoint(0, y1))
        self.m_animation.start()


class ThumbWidget(QtWidgets.QFrame):
    def __init__(self, title, pixmap, parent=None):
        super().__init__(parent)
        self.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.setFrameShadow(QtWidgets.QFrame.Raised)

        pixmap_label = QtWidgets.QLabel(pixmap=pixmap, scaledContents=True)
        title_label = QtWidgets.QLabel(title)
        title_label.setStyleSheet("""color: #FFFFFF""")
        font = QtGui.QFont()
        font.setFamily("SF Pro Display")
        font.setPointSize(16)
        font.setWeight(75)
        font.setBold(True)
        title_label.setFont(font)

        background_label = QtWidgets.QLabel(pixmap_label)
        background_label.setStyleSheet("background: #32353B;")
        background_label.setFixedSize(self.width(), 50)
        background_label.move(0, self.height())

        background_lay = QtWidgets.QVBoxLayout(background_label)
        background_lay.addWidget(title_label)

        self.setFixedSize(256, 256)
        lay = QtWidgets.QVBoxLayout(self)
        lay.setContentsMargins(0, 0, 0, 0)
        lay.setSpacing(0)
        lay.addWidget(pixmap_label)

        effect = RectangleHoverEffect(background_label, self)


class ProductMainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.product_listwidget = QtWidgets.QListWidget(
            viewMode=QtWidgets.QListWidget.IconMode,
            iconSize=QtCore.QSize(256, 256),
            resizeMode=QtWidgets.QListWidget.Adjust,
            movement=QtWidgets.QListWidget.Static,
        )
        self.product_listwidget.setGridSize(QtCore.QSize(256 + 5, 256 + 5))

        for i in range(6):
            item = QtWidgets.QListWidgetItem()
            item_widget = ThumbWidget(f"Title {i}", QtGui.QPixmap("E:/code/android.png"))
            item.setSizeHint(QtCore.QSize(256, 256))
            self.product_listwidget.addItem(item)
            self.product_listwidget.setItemWidget(item, item_widget)

        central_widget = QtWidgets.QWidget()
        self.setCentralWidget(central_widget)
        lay = QtWidgets.QVBoxLayout(central_widget)
        lay.addWidget(self.product_listwidget)

        self.resize(960, 480)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = ProductMainWindow()
    w.show()
    sys.exit(app.exec_())