Ejemplo n.º 1
0
    def browseColor(self):
        """
        Show the color dialog.

        :rtype: None
        """
        color = self.currentColor()
        if color:
            color = studioqt.Color.fromString(color)

        d = QtWidgets.QColorDialog(self)
        d.setCurrentColor(color)

        standardColors = self.browserColors()

        if standardColors:
            index = -1
            for standardColor in standardColors:
                index += 1

                try:
                    # Support for new qt5 signature
                    standardColor = QtGui.QColor(standardColor)
                    d.setStandardColor(index, standardColor)
                except:
                    # Support for new qt4 signature
                    standardColor = QtGui.QColor(standardColor).rgba()
                    d.setStandardColor(index, standardColor)

        d.currentColorChanged.connect(self._colorChanged)

        if d.exec_():
            self._colorChanged(d.selectedColor())
        else:
            self._colorChanged(color)
Ejemplo n.º 2
0
    def __init__(self, *args):
        QtWidgets.QWidget.__init__(self, *args)

        self._dpi = 1
        self._padding = self.DEFAULT_PADDING

        w, h = self.DEFAULT_ZOOM_AMOUNT, self.DEFAULT_ZOOM_AMOUNT

        self._iconSize = QtCore.QSize(w, h)
        self._itemSizeHint = QtCore.QSize(w, h)

        self._zoomAmount = self.DEFAULT_ZOOM_AMOUNT
        self._labelDisplayOption = self.LABEL_DISPLAY_OPTION

        self._dataset = None
        self._treeWidget = TreeWidget(self)

        self._listView = ListView(self)
        self._listView.setTreeWidget(self._treeWidget)
        self._listView.installEventFilter(self)

        self._delegate = ItemDelegate()
        self._delegate.setItemsWidget(self)

        self._listView.setItemDelegate(self._delegate)
        self._treeWidget.setItemDelegate(self._delegate)
        self._treeWidget.installEventFilter(self)

        self._toastWidget = ToastWidget(self)
        self._toastWidget.hide()
        self._toastEnabled = True

        self._textColor = QtGui.QColor(255, 255, 255, 200)
        self._textSelectedColor = QtGui.QColor(255, 255, 255, 200)
        self._itemBackgroundColor = QtGui.QColor(255, 255, 255, 30)
        self._backgroundHoverColor = QtGui.QColor(255, 255, 255, 35)
        self._backgroundSelectedColor = QtGui.QColor(30, 150, 255)

        layout = QtWidgets.QHBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self._treeWidget)
        layout.addWidget(self._listView)

        header = self.treeWidget().header()
        header.sortIndicatorChanged.connect(self._sortIndicatorChanged)

        self.setLayout(layout)

        self.listView().itemClicked.connect(self._itemClicked)
        self.listView().itemDoubleClicked.connect(self._itemDoubleClicked)

        self.treeWidget().itemClicked.connect(self._itemClicked)
        self.treeWidget().itemDoubleClicked.connect(self._itemDoubleClicked)

        self.itemMoved = self._listView.itemMoved
        self.itemDropped = self._listView.itemDropped
        self.itemSelectionChanged = self._treeWidget.itemSelectionChanged
Ejemplo n.º 3
0
    def backgroundSelectedColor(self):
        """
        Return the background color when the item is selected.

        :rtype: QtWidgets.QtColor
        """
        return QtGui.QColor(0, 0, 0, 0)
Ejemplo n.º 4
0
    def __init__(self, *args):
        QtWidgets.QListView.__init__(self, *args)
        ItemViewMixin.__init__(self)

        self._treeWidget = None
        self._rubberBand = None
        self._rubberBandStartPos = None
        self._rubberBandColor = QtGui.QColor(QtCore.Qt.white)
        self._customSortOrder = []

        self._drag = None
        self._dragStartPos = None
        self._dragStartIndex = None
        self._dropEnabled = True

        self.setSpacing(5)

        self.setMouseTracking(True)
        self.setSelectionRectVisible(True)
        self.setViewMode(QtWidgets.QListView.IconMode)
        self.setResizeMode(QtWidgets.QListView.Adjust)
        self.setSelectionMode(QtWidgets.QListWidget.ExtendedSelection)
        self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)

        self.setAcceptDrops(True)
        self.setDragEnabled(True)
        self.setDragDropMode(QtWidgets.QAbstractItemView.DragDrop)

        self.clicked.connect(self._indexClicked)
        self.doubleClicked.connect(self._indexDoubleClicked)
Ejemplo n.º 5
0
    def paintBackground(self, painter, option, index):
        """
        Draw the background for the item.

        :type painter: QtWidgets.QPainter
        :type option: QtWidgets.QStyleOptionViewItem
        :type index: QtCore.QModelIndex
        :rtype: None
        """
        super(GroupItem, self).paintBackground(painter, option, index)

        painter.setPen(QtGui.QPen(QtCore.Qt.NoPen))
        visualRect = self.visualRect(option)

        text = self.name()
        metrics = QtGui.QFontMetricsF(self._font)
        textWidth = metrics.width(text)

        padding = (25 * self.dpi())

        visualRect.setX(textWidth + padding)
        visualRect.setY(visualRect.y() + (visualRect.height() / 2))
        visualRect.setHeight(2 * self.dpi())
        visualRect.setWidth(visualRect.width() - padding)

        color = QtGui.QColor(
            self.textColor().red(),
            self.textColor().green(),
            self.textColor().blue(), 10
        )
        painter.setBrush(QtGui.QBrush(color))

        painter.drawRect(visualRect)
Ejemplo n.º 6
0
    def setBadge(self, x, y, w, h, color=None):
        """
        Set a for the icon.
        
        :type x: int 
        :type y: int 
        :type w: int
        :type h: int 
        :type color: QtGui.QColor or None
        """
        color = color or QtGui.QColor(240, 100, 100)

        size = self.actualSize(QtCore.QSize(256, 256))
        pixmap = self.pixmap(size)

        painter = QtGui.QPainter(pixmap)

        pen = QtGui.QPen(color)
        pen.setWidth(0)
        painter.setPen(pen)

        painter.setBrush(color)
        painter.setRenderHint(QtGui.QPainter.Antialiasing)

        painter.drawEllipse(x, y, w, h)
        painter.end()

        icon = QtGui.QIcon(pixmap)
        self.swap(icon)
Ejemplo n.º 7
0
    def backgroundHoverColor(self):
        """
        Return the background color when the mouse is over the item.

        :rtype: QtWidgets.QtColor
        """
        return QtGui.QColor(0, 0, 0, 0)
Ejemplo n.º 8
0
    def backgroundColor(self):
        """
        Return the background color for the item.

        :rtype: QtWidgets.QtColor
        """
        return QtGui.QColor(0, 0, 0, 0)
Ejemplo n.º 9
0
def example():
    """
    Example:

        import studiolibrary.widgets.colorpicker
        reload(studiolibrary.widgets.colorpicker)
        studiolibrary.widgets.colorpicker.example()
    """
    def _colorChanged(color):
        print("colorChanged:", color)

    style = """   
        #colorButton {
            margin: 5px;
            min-width: 100px;
            min-height: 100px;
        }
        
        #browseColorButton {
            margin: 5px;
            font-size: 45px;
            min-width: 100px;
            min-height: 100px;
        }
    """

    colors = [
        "rgb(230, 60, 60, 255)",
        "rgb(255, 90, 40)",
        "rgb(255, 125, 100, 255)",
        "rgb(250, 200, 0, 255)",
        "rgb(80, 200, 140, 255)",
        "rgb(50, 180, 240, 255)",
        "rgb(110, 110, 240, 255)",
    ]

    browserColors = []
    browserColors_ = [
        # Top row, Bottom row
        (230, 60, 60), (250, 80, 130),
        (255, 90, 40), (240, 100, 170),
        (255, 125, 100), (240, 200, 150),
        (250, 200, 0), (225, 200, 40),
        (80, 200, 140), (80, 225, 120),
        (50, 180, 240), (100, 200, 245),
        (130, 110, 240), (180, 160, 255),
        (180, 110, 240), (210, 110, 255)
    ]

    for colorR, colorG, colorB in browserColors_:
        for i in range(0, 3):
            color = QtGui.QColor(colorR, colorG, colorB)
            browserColors.append(color)

    picker = ColorPickerWidget()
    picker.setColors(colors)
    picker.setStyleSheet(style)
    picker.setBrowserColors(browserColors)
    picker.colorChanged.connect(_colorChanged)
    picker.show()
Ejemplo n.º 10
0
    def setBackgroundSelectedColor(self, color):
        """
        Set the background color when an item is selected.

        :type color: QtWidgets.QtColor
        """
        self._backgroundSelectedColor = color
        self._listView.setRubberBandColor(QtGui.QColor(200, 200, 200, 255))
Ejemplo n.º 11
0
    def createColorDialog(
        self,
        parent,
        standardColors=None,
        currentColor=None,
    ):
        """
        Create a new instance of the color dialog.

        :type parent: QtWidgets.QWidget
        :type standardColors: list[int]
        :rtype: QtWidgets.QColorDialog
        """
        dialog = QtWidgets.QColorDialog(parent)

        if standardColors:
            index = -1
            for colorR, colorG, colorB in standardColors:
                index += 1

                color = QtGui.QColor(colorR, colorG, colorB).rgba()

                try:
                    # Support for new qt5 signature
                    color = QtGui.QColor(color)
                    dialog.setStandardColor(index, color)
                except:
                    # Support for new qt4 signature
                    color = QtGui.QColor(color).rgba()
                    dialog.setStandardColor(index, color)

        # PySide2 doesn't support d.open(), so we need to pass a blank slot.
        dialog.open(self, QtCore.SLOT("blankSlot()"))

        if currentColor:
            dialog.setCurrentColor(currentColor)

        return dialog
Ejemplo n.º 12
0
    def drawIconBorder(self, painter, pixmapRect):
        """
        Draw a border around the icon.

        :type painter: QtWidgets.QPainter
        :type pixmapRect: QtWidgets.QRect
        :rtype: None
        """
        pixmapRect = QtCore.QRect(pixmapRect)
        pixmapRect.setX(pixmapRect.x() - 5)
        pixmapRect.setY(pixmapRect.y() - 5)
        pixmapRect.setWidth(pixmapRect.width() + 5)
        pixmapRect.setHeight(pixmapRect.height() + 5)

        color = QtGui.QColor(255, 255, 255, 10)
        painter.setPen(QtGui.QPen(QtCore.Qt.NoPen))
        painter.setBrush(QtGui.QBrush(color))

        painter.drawRect(pixmapRect)
Ejemplo n.º 13
0
 def setIconColor():
     menuBarWidget.setIconColor(QtGui.QColor(255, 255, 0))
Ejemplo n.º 14
0
class Theme(QtCore.QObject):

    updated = QtCore.Signal()

    DEFAULT_DARK_COLOR = QtGui.QColor(60, 60, 60)
    DEFAULT_LIGHT_COLOR = QtGui.QColor(220, 220, 220)

    DEFAULT_ACCENT_COLOR = QtGui.QColor(0, 175, 255)
    DEFAULT_BACKGROUND_COLOR = QtGui.QColor(60, 60, 80)

    def __init__(self):
        QtCore.QObject.__init__(self)

        self._dpi = 1

        self._name = "Default"
        self._accentColor = None
        self._backgroundColor = None

        self.setAccentColor(self.DEFAULT_ACCENT_COLOR)
        self.setBackgroundColor(self.DEFAULT_BACKGROUND_COLOR)

    def settings(self):
        """
        Return a dictionary of settings for the current Theme.

        :rtype: dict
        """
        settings = {}

        settings["name"] = self.name()

        accentColor = self.accentColor()
        settings["accentColor"] = accentColor.toString()

        backgroundColor = self.backgroundColor()
        settings["backgroundColor"] = backgroundColor.toString()

        return settings

    def setSettings(self, settings):
        """
        Set a dictionary of settings for the current Theme.

        :type settings: dict
        :rtype: None
        """
        name = settings.get("name")
        self.setName(name)

        color = settings.get("accentColor")
        if color:
            color = studioqt.Color.fromString(color)
            self.setAccentColor(color)

        color = settings.get("backgroundColor")
        if color:
            color = studioqt.Color.fromString(color)
            self.setBackgroundColor(color)

    def dpi(self):
        """
        Return the dpi for the Theme

        :rtype: float
        """
        return self._dpi

    def setDpi(self, dpi):
        """
        Set the dpi for the Theme

        :type dpi: float
        :rtype: None
        """
        self._dpi = dpi

    def name(self):
        """
        Return the name for the Theme

        :rtype: str
        """
        return self._name

    def setName(self, name):
        """
        Set the name for the Theme

        :type name: str
        :rtype: None
        """
        self._name = name

    def isDark(self):
        """
        Return True if the current theme is dark.

        rtype: bool
        """
        # The luminance for digital formats are (0.299, 0.587, 0.114)
        red = self.backgroundColor().redF() * 0.299
        green = self.backgroundColor().greenF() * 0.587
        blue = self.backgroundColor().blueF() * 0.114

        darkness = red + green + blue

        if darkness < 0.6:
            return True

        return False

    def setDark(self):
        """
        Set the current theme to the default dark color.
        
        :rtype: None 
        """
        self.setBackgroundColor(self.DEFAULT_DARK_COLOR)

    def setLight(self):
        """
        Set the current theme to the default light color.

        :rtype: None 
        """
        self.setBackgroundColor(self.DEFAULT_LIGHT_COLOR)

    def iconColor(self):
        """
        Return the icon color for the theme.

        :rtype: studioqt.Color 
        """
        return self.forgroundColor()

    def accentForgroundColor(self):
        """
        Return the foreground color for the accent color.

        :rtype: studioqt.Color 
        """
        return studioqt.Color(255, 255, 255, 255)

    def forgroundColor(self):
        """
        Return the foreground color for the theme.

        :rtype: studioqt.Color 
        """
        if self.isDark():
            return studioqt.Color(250, 250, 250, 225)
        else:
            return studioqt.Color(0, 40, 80, 180)

    def itemBackgroundColor(self):
        """
        Return the item background color.

        :rtype: studioqt.Color 
        """
        if self.isDark():
            return studioqt.Color(255, 255, 255, 20)
        else:
            return studioqt.Color(255, 255, 255, 120)

    def itemBackgroundHoverColor(self):
        """
        Return the item background color when the mouse hovers over the item.

        :rtype: studioqt.Color 
        """
        return studioqt.Color(255, 255, 255, 60)

    def accentColor(self):
        """
        Return the accent color for the theme.

        :rtype: studioqt.Color or None
        """
        return self._accentColor

    def backgroundColor(self):
        """
        Return the background color for the theme.

        :rtype: studioqt.Color or None
        """
        return self._backgroundColor

    def setAccentColor(self, color):
        """
        Set the accent color for the theme.

        :type color: studioqt.Color | QtGui.QColor
        """
        if isinstance(color, basestring):
            color = studioqt.Color.fromString(color)

        if isinstance(color, QtGui.QColor):
            color = studioqt.Color.fromColor(color)

        self._accentColor = color

        self.updated.emit()

    def setBackgroundColor(self, color):
        """
        Set the background color for the theme.

        :type color: studioqt.Color | QtGui.QColor
        """
        if isinstance(color, basestring):
            color = studioqt.Color.fromString(color)

        if isinstance(color, QtGui.QColor):
            color = studioqt.Color.fromColor(color)

        self._backgroundColor = color

        self.updated.emit()

    def createColorDialog(
        self,
        parent,
        standardColors=None,
        currentColor=None,
    ):
        """
        Create a new instance of the color dialog.

        :type parent: QtWidgets.QWidget
        :type standardColors: list[int]
        :rtype: QtWidgets.QColorDialog
        """
        dialog = QtWidgets.QColorDialog(parent)

        if standardColors:
            index = -1
            for colorR, colorG, colorB in standardColors:
                index += 1

                color = QtGui.QColor(colorR, colorG, colorB).rgba()

                try:
                    # Support for new qt5 signature
                    color = QtGui.QColor(color)
                    dialog.setStandardColor(index, color)
                except:
                    # Support for new qt4 signature
                    color = QtGui.QColor(color).rgba()
                    dialog.setStandardColor(index, color)

        # PySide2 doesn't support d.open(), so we need to pass a blank slot.
        dialog.open(self, QtCore.SLOT("blankSlot()"))

        if currentColor:
            dialog.setCurrentColor(currentColor)

        return dialog

    def browseAccentColor(self, parent=None):
        """
        Show the color dialog for changing the accent color.
        
        :type parent: QtWidgets.QWidget
        :rtype: None
        """
        standardColors = [(230, 60, 60), (210, 40, 40), (190, 20, 20),
                          (250, 80, 130), (230, 60, 110), (210, 40, 90),
                          (255, 90, 40), (235, 70, 20), (215, 50, 0),
                          (240, 100, 170), (220, 80, 150), (200, 60, 130),
                          (255, 125, 100), (235, 105, 80), (215, 85, 60),
                          (240, 200, 150), (220, 180, 130), (200, 160, 110),
                          (250, 200, 0), (230, 180, 0), (210, 160, 0),
                          (225, 200, 40), (205, 180, 20), (185, 160, 0),
                          (80, 200, 140), (60, 180, 120), (40, 160, 100),
                          (80, 225, 120), (60, 205, 100), (40, 185, 80),
                          (50, 180, 240), (30, 160, 220), (10, 140, 200),
                          (100, 200, 245), (80, 180, 225), (60, 160, 205),
                          (130, 110, 240), (110, 90, 220), (90, 70, 200),
                          (180, 160, 255), (160, 140, 235), (140, 120, 215),
                          (180, 110, 240), (160, 90, 220), (140, 70, 200),
                          (210, 110, 255), (190, 90, 235), (170, 70, 215)]

        currentColor = self.accentColor()

        dialog = self.createColorDialog(parent, standardColors, currentColor)
        dialog.currentColorChanged.connect(self.setAccentColor)

        if dialog.exec_():
            self.setAccentColor(dialog.selectedColor())
        else:
            self.setAccentColor(currentColor)

    def browseBackgroundColor(self, parent=None):
        """
        Show the color dialog for changing the background color.

        :type parent: QtWidgets.QWidget
        :rtype: None
        """
        standardColors = [(0, 0, 0), (20, 20, 20), (40, 40, 40), (60, 60, 60),
                          (80, 80, 80), (100, 100, 100), (20, 20, 30),
                          (40, 40, 50), (60, 60, 70), (80, 80, 90),
                          (100, 100, 110), (120, 120, 130), (0, 30, 60),
                          (20, 50, 80), (40, 70, 100), (60, 90, 120),
                          (80, 110, 140), (100, 130, 160), (0, 60, 60),
                          (20, 80, 80), (40, 100, 100), (60, 120, 120),
                          (80, 140, 140), (100, 160, 160), (0, 60, 30),
                          (20, 80, 50), (40, 100, 70), (60, 120, 90),
                          (80, 140, 110), (100, 160, 130), (60, 0, 10),
                          (80, 20, 30), (100, 40, 50), (120, 60, 70),
                          (140, 80, 90), (160, 100, 110), (60, 0, 40),
                          (80, 20, 60), (100, 40, 80), (120, 60, 100),
                          (140, 80, 120), (160, 100, 140), (40, 15, 5),
                          (60, 35, 25), (80, 55, 45), (100, 75, 65),
                          (120, 95, 85), (140, 115, 105)]

        currentColor = self.backgroundColor()

        dialog = self.createColorDialog(parent, standardColors, currentColor)
        dialog.currentColorChanged.connect(self.setBackgroundColor)

        if dialog.exec_():
            self.setBackgroundColor(dialog.selectedColor())
        else:
            self.setBackgroundColor(currentColor)

    def options(self):
        """
        Return the variables used to customise the style sheet.

        :rtype: dict
        """
        accentColor = self.accentColor()
        accentForegroundColor = self.accentForgroundColor()

        foregroundColor = self.forgroundColor()
        backgroundColor = self.backgroundColor()

        itemBackgroundColor = self.itemBackgroundColor()
        itemBackgroundHoverColor = self.itemBackgroundHoverColor()

        if self.isDark():
            darkness = "white"
        else:
            darkness = "black"

        resourceDirname = studiolibrary.resource.RESOURCE_DIRNAME
        resourceDirname = resourceDirname.replace("\\", "/")

        options = {
            "DARKNESS": darkness,
            "RESOURCE_DIRNAME": resourceDirname,
            "ACCENT_COLOR": accentColor.toString(),
            "ACCENT_COLOR_R": str(accentColor.red()),
            "ACCENT_COLOR_G": str(accentColor.green()),
            "ACCENT_COLOR_B": str(accentColor.blue()),
            "ACCENT_FOREGROUND_COLOR": accentForegroundColor.toString(),
            "FOREGROUND_COLOR": foregroundColor.toString(),
            "FOREGROUND_COLOR_R": str(foregroundColor.red()),
            "FOREGROUND_COLOR_G": str(foregroundColor.green()),
            "FOREGROUND_COLOR_B": str(foregroundColor.blue()),
            "BACKGROUND_COLOR": backgroundColor.toString(),
            "BACKGROUND_COLOR_R": str(backgroundColor.red()),
            "BACKGROUND_COLOR_G": str(backgroundColor.green()),
            "BACKGROUND_COLOR_B": str(backgroundColor.blue()),
            "ITEM_TEXT_COLOR": foregroundColor.toString(),
            "ITEM_TEXT_SELECTED_COLOR": accentForegroundColor.toString(),
            "ITEM_BACKGROUND_COLOR": itemBackgroundColor.toString(),
            "ITEM_BACKGROUND_HOVER_COLOR": itemBackgroundHoverColor.toString(),
            "ITEM_BACKGROUND_SELECTED_COLOR": accentColor.toString(),
        }

        return options

    def styleSheet(self):
        """
        Return the style sheet for this theme.

        :rtype: str
        """
        options = self.options()
        path = studiolibrary.resource.get("css", "default.css")
        styleSheet = studioqt.StyleSheet.fromPath(path,
                                                  options=options,
                                                  dpi=self.dpi())
        return styleSheet.data()
Ejemplo n.º 15
0
class Item(QtWidgets.QTreeWidgetItem):
    """The Item is used to hold rows of information for an item view."""

    ICON_PATH = None
    TYPE_ICON_PATH = None

    ThreadPool = QtCore.QThreadPool()
    THUMBNAIL_PATH = ""

    MAX_ICON_SIZE = 256

    DEFAULT_FONT_SIZE = 12
    DEFAULT_PLAYHEAD_COLOR = QtGui.QColor(255, 255, 255, 220)

    THUMBNAIL_COLUMN = 0
    ENABLE_THUMBNAIL_THREAD = True
    PAINT_SLIDER = False

    _globalSignals = GlobalSignals()
    sliderChanged = _globalSignals.sliderChanged

    def __init__(self, *args):
        QtWidgets.QTreeWidgetItem.__init__(self, *args)

        self._url = None
        self._path = None
        self._size = None
        self._rect = None
        self._textColumnOrder = []

        self._data = {}
        self._itemData = {}

        self._icon = {}
        self._fonts = {}
        self._thread = None
        self._pixmap = {}
        self._pixmapRect = None
        self._pixmapScaled = None

        self._iconPath = None
        self._typePixmap = None

        self._thumbnailIcon = None

        self._underMouse = False
        self._searchText = None
        self._infoWidget = None

        self._groupItem = None
        self._groupColumn = 0

        self._mimeText = None
        self._itemsWidget = None
        self._stretchToWidget = None

        self._dragEnabled = True

        self._imageSequence = None
        self._imageSequencePath = ""

        self._sliderDown = False
        self._sliderValue = 0.0
        self._sliderPreviousValue = 0.0
        self._sliderPosition = None
        self._sliderEnabled = False

        self._worker = ImageWorker()
        self._worker.setAutoDelete(False)
        self._worker.signals.triggered.connect(self._thumbnailFromImage)
        self._workerStarted = False

    def __eq__(self, other):
        return id(other) == id(self)

    def __ne__(self, other):
        return id(other) != id(self)

    def __del__(self):
        """
        Make sure the sequence is stopped when deleted.

        :rtype: None
        """
        self.stop()

    def columnFromLabel(self, label):
        if self.treeWidget():
            return self.treeWidget().columnFromLabel(label)
        else:
            return None

    def labelFromColumn(self, column):
        if self.treeWidget():
            return self.treeWidget().labelFromColumn(column)
        else:
            return None

    def mimeText(self):
        """
        Return the mime text for drag and drop.

        :rtype: str
        """
        return self._mimeText or self.text(0)

    def setMimeText(self, text):
        """
        Set the mime text for drag and drop.

        :type text: str
        :rtype: None
        """
        self._mimeText = text

    def setHidden(self, value):
        """
        Set the item hidden.

        :type value: bool
        :rtype: None
        """
        QtWidgets.QTreeWidgetItem.setHidden(self, value)
        row = self.treeWidget().indexFromItem(self).row()
        self.itemsWidget().listView().setRowHidden(row, value)

    def setDragEnabled(self, value):
        """
        Set True if the item can be dragged.

        :type value: bool
        :rtype: None
        """
        self._dragEnabled = value

    def dragEnabled(self):
        """
        Return True if the item can be dragged.

        :rtype: bool
        """
        return self._dragEnabled

    def setIcon(self, column, icon, color=None):
        """
        Set the icon to be displayed in the given column.

        :type column: int or str
        :type icon: QtGui.QIcon
        :type color: QtGui.QColor or None
        :rtype: None
        """
        # Safe guard for when the class is being used without the gui.
        isAppRunning = bool(QtWidgets.QApplication.instance())
        if not isAppRunning:
            return

        if isinstance(icon, basestring):
            if not os.path.exists(icon):
                color = color or studioqt.Color(255, 255, 255, 20)
                icon = studiolibrary.resource.icon("image", color=color)
            else:
                icon = QtGui.QIcon(icon)

        if isinstance(column, basestring):
            self._icon[column] = icon
        else:
            self._pixmap[column] = None
            QtWidgets.QTreeWidgetItem.setIcon(self, column, icon)

        self.updateIcon()

    def setItemData(self, data):
        """
        Set the given dictionary as the data for the item.

        :type data: dict
        :rtype: None
        """
        self._itemData = data

    def itemData(self):
        """
        Return the item data for this item.

        :rtype: dict
        """
        return self._itemData

    def setName(self, text):
        """
        Set the name that is shown under the icon and in the Name column.

        :type text: str
        :rtype: None 
        """
        itemData = self.itemData()
        itemData['icon'] = text
        itemData['name'] = text

    def name(self):
        """
        Return text for the Name column.

        :rtype: str
        """
        return self.itemData().get("name")

    def displayText(self, label):
        """
        Return the sort data for the given column.

        :type label: str
        :rtype: str
        """
        return unicode(self.itemData().get(label, ''))

    def sortText(self, label):
        """
        Return the sort data for the given column.

        :type label: str
        :rtype: str
        """
        return unicode(self.itemData().get(label, ''))

    def update(self):
        """
        Refresh the visual state of the icon.

        :rtype: None 
        """
        self.updateIcon()
        self.updateFrame()

    def updateIcon(self):
        """
        Clear the pixmap cache for the item.

        :rtype: None 
        """
        self.clearCache()

    def clearCache(self):
        """Clear the thumbnail cache."""
        self._pixmap = {}
        self._pixmapRect = None
        self._pixmapScaled = None
        self._thumbnailIcon = None

    def dpi(self):
        """
        Used for high resolution devices.

        :rtype: int
        """
        if self.itemsWidget():
            return self.itemsWidget().dpi()
        else:
            return 1

    def clicked(self):
        """
        Triggered when an item is clicked.

        :rtype: None
        """
        pass

    def takeFromTree(self):
        """
        Takes this item from the tree.
        """
        tree = self.treeWidget()
        parent = self.parent()

        if parent:
            parent.takeChild(parent.indexOfChild(self))
        else:
            tree.takeTopLevelItem(tree.indexOfTopLevelItem(self))

    def selectionChanged(self):
        """
        Triggered when an item has been either selected or deselected.

        :rtype: None
        """
        self.resetSlider()

    def doubleClicked(self):
        """
        Triggered when an item is double clicked.

        :rtype: None
        """
        pass

    def setGroupItem(self, groupItem):
        """
        Set the group item that this item is a child to.

        :type groupItem: groupitem.GroupItem
        """
        self._groupItem = groupItem

    def groupItem(self):
        """
        Get the group item that this item is a child to.

        :rtype: groupitem.GroupItem
        """
        return self._groupItem

    def itemsWidget(self):
        """
        Returns the items widget that contains the items.

        :rtype: ItemsWidget
        """
        itemsWidget = None

        if self.treeWidget():
            itemsWidget = self.treeWidget().parent()

        return itemsWidget

    def url(self):
        """
        Return the url object for the given item.

        :rtype: QtCore.QUrl or None
        """
        if not self._url:
            self._url = QtCore.QUrl(self.text(0))
        return self._url

    def setUrl(self, url):
        """
        Set the url object for the item.

        :type: QtCore.QUrl or None
        :rtype: None
        """
        self._url = url

    def searchText(self):
        """
        Return the search string used for finding the item.

        :rtype: str
        """
        if not self._searchText:
            self._searchText = unicode(self._data)

        return self._searchText

    def setStretchToWidget(self, widget):
        """
        Set the width of the item to the width of the given widget.

        :type widget: QtWidgets.QWidget
        :rtype: None
        """
        self._stretchToWidget = widget

    def stretchToWidget(self):
        """
        Return the sretchToWidget.

        :rtype: QtWidgets.QWidget
        """
        return self._stretchToWidget

    def setSize(self, size):
        """
        Set the size for the item.

        :type size: QtCore.QSize
        :rtype: None
        """
        self._size = size

    def sizeHint(self, column=0):
        """
        Return the current size of the item.

        :type column: int
        :rtype: QtCore.QSize
        """
        if self.stretchToWidget():
            if self._size:
                size = self._size
            else:
                size = self.itemsWidget().iconSize()

            w = self.stretchToWidget().width()
            h = size.height()
            return QtCore.QSize(w - 20, h)

        if self._size:
            return self._size
        else:
            iconSize = self.itemsWidget().iconSize()

            if self.isLabelUnderItem():
                w = iconSize.width()
                h = iconSize.width() + self.textHeight()
                iconSize = QtCore.QSize(w, h)

            return iconSize

    def setPixmap(self, column, pixmap):
        """
        Set the pixmap to be displayed in the given column.

        :type column: int
        :type pixmap: QtWidgets.QPixmap
        :rtype: None
        """
        self._pixmap[column] = pixmap

    def thumbnailPath(self):
        """
        Return the thumbnail path on disk.

        :rtype: None or str
        """
        return ""

    def _thumbnailFromImage(self, image):
        """
        Called after the given image object has finished loading.

        :type image: QtGui.QImage
        :rtype: None  
        """
        self.clearCache()

        pixmap = QtGui.QPixmap()
        pixmap.convertFromImage(image)
        icon = QtGui.QIcon(pixmap)

        self._thumbnailIcon = icon
        if self.itemsWidget():
            self.itemsWidget().update()

    def defaultThumbnailPath(self):
        """
        Get the default thumbnail path.
        
        :rtype: str 
        """
        return self.THUMBNAIL_PATH

    def defaultThumbnailIcon(self):
        """
        Get the default thumbnail icon.
        
        :rtype: QtGui.QIcon 
        """
        return QtGui.QIcon(self.defaultThumbnailPath())

    def thumbnailIcon(self):
        """
        Return the thumbnail icon.

        :rtype: QtGui.QIcon
        """
        thumbnailPath = self.thumbnailPath()

        if not self._thumbnailIcon:
            if self.ENABLE_THUMBNAIL_THREAD and not self._workerStarted:
                self._workerStarted = True
                self._worker.setPath(thumbnailPath)

                self.ThreadPool.start(self._worker)

                self._thumbnailIcon = self.defaultThumbnailIcon()
            else:
                self._thumbnailIcon = QtGui.QIcon(thumbnailPath)

        return self._thumbnailIcon

    def icon(self, column):
        """
        Overriding the icon method to add support for the thumbnail icon.

        :type column: int
        :rtype: QtGui.QIcon
        """
        icon = QtWidgets.QTreeWidgetItem.icon(self, column)

        if not icon and column == self.THUMBNAIL_COLUMN:
            icon = self.thumbnailIcon()

        return icon

    def pixmap(self, column):
        """
        Return the pixmap for the given column.

        :type column: int
        :rtype: QtWidgets.QPixmap
        """

        if not self._pixmap.get(column):

            icon = self.icon(column)
            if icon:
                size = QtCore.QSize(self.MAX_ICON_SIZE, self.MAX_ICON_SIZE)
                iconSize = icon.actualSize(size)
                self._pixmap[column] = icon.pixmap(iconSize)

        return self._pixmap.get(column)

    def padding(self):
        """
        Return the padding/border size for the item.

        :rtype: int
        """
        return self.itemsWidget().padding()

    def textHeight(self):
        """
        Return the height of the text for the item.

        :rtype: int
        """
        return self.itemsWidget().itemTextHeight()

    def isTextVisible(self):
        """
        Check if the label should be displayed.

        :rtype: bool
        """
        return self.labelDisplayOption() != LabelDisplayOption.Hide

    def isLabelOverItem(self):
        """
        Check if the label should be displayed over the item.

        :rtype: bool
        """
        return self.labelDisplayOption() == LabelDisplayOption.Over

    def isLabelUnderItem(self):
        """
        Check if the label should be displayed under the item.

        :rtype: bool
        """
        return self.labelDisplayOption() == LabelDisplayOption.Under

    def labelDisplayOption(self):
        """
        Return True if the text is visible.

        :rtype: bool
        """
        return self.itemsWidget().labelDisplayOption()

    def textAlignment(self, column):
        """
        Return the text alignment for the label in the given column.

        :type column: int
        :rtype: QtCore.Qt.AlignmentFlag
        """
        if self.itemsWidget().isIconView():
            return QtCore.Qt.AlignCenter
        else:
            return QtWidgets.QTreeWidgetItem.textAlignment(self, column)

    # -----------------------------------------------------------------------
    # Support for mouse and key events
    # -----------------------------------------------------------------------

    def underMouse(self):
        """Return True if the item is under the mouse cursor."""
        return self._underMouse

    def contextMenu(self, menu):
        """
        Return the context menu for the item.

        Reimplement in a subclass to return a custom context menu for the item.

        :rtype: QtWidgets.QMenu
        """
        pass

    def dropEvent(self, event):
        """
        Reimplement in a subclass to receive drop events for the item.

        :type event: QtWidgets.QDropEvent
        :rtype: None
        """

    def mouseLeaveEvent(self, event):
        """
        Reimplement in a subclass to receive mouse leave events for the item.

        :type event: QtWidgets.QMouseEvent
        :rtype: None
        """
        self._underMouse = False
        self.stop()

    def mouseEnterEvent(self, event):
        """
        Reimplement in a subclass to receive mouse enter events for the item.

        :type event: QtWidgets.QMouseEvent
        :rtype: None
        """
        self._underMouse = True
        self.play()

    def mouseMoveEvent(self, event):
        """
        Reimplement in a subclass to receive mouse move events for the item.

        :type event: QtWidgets.QMouseEvent
        :rtype: None
        """
        self.sliderEvent(event)
        self.imageSequenceEvent(event)

    def mousePressEvent(self, event):
        """
        Reimplement in a subclass to receive mouse press events for the item.

        :type event: QtWidgets.QMouseEvent
        :rtype: None
        """
        if event.button() == QtCore.Qt.MidButton:
            if self.isSliderEnabled():
                self.setSliderDown(True)
                self._sliderPosition = event.pos()

    def mouseReleaseEvent(self, event):
        """
        Reimplement in a subclass to receive mouse release events for the item.

        :type event: QtWidgets.QMouseEvent
        :rtype: None
        """
        if self.isSliderDown():
            self._sliderPosition = None
            self._sliderPreviousValue = self.sliderValue()

    def keyPressEvent(self, event):
        """
        Reimplement in a subclass to receive key press events for the item.

        :type event: QtWidgets.QKeyEvent
        :rtype: None
        """
        pass

    def keyReleaseEvent(self, event):
        """
        Reimplement in a subclass to receive key release events for the item.

        :type event: QtWidgets.QKeyEvent
        :rtype: None
        """
        pass

    # -----------------------------------------------------------------------
    # Support for custom painting
    # -----------------------------------------------------------------------

    def textColor(self):
        """
        Return the text color for the item.

        :rtype: QtWidgets.QtColor
        """
        # This will be changed to use the palette soon.
        # Note: There were problems with older versions of Qt's palette (Maya 2014).
        # Eg:
        # return self.itemsWidget().palette().color(self.itemsWidget().foregroundRole())
        return self.itemsWidget().textColor()

    def textSelectedColor(self):
        """
        Return the selected text color for the item.

        :rtype: QtWidgets.QtColor
        """
        return self.itemsWidget().textSelectedColor()

    def backgroundColor(self):
        """
        Return the background color for the item.

        :rtype: QtWidgets.QtColor
        """
        return self.itemsWidget().itemBackgroundColor()

    def backgroundHoverColor(self):
        """
        Return the background color when the mouse is over the item.

        :rtype: QtWidgets.QtColor
        """
        return self.itemsWidget().backgroundHoverColor()

    def backgroundSelectedColor(self):
        """
        Return the background color when the item is selected.

        :rtype: QtWidgets.QtColor
        """
        return self.itemsWidget().backgroundSelectedColor()

    def rect(self):
        """
        Return the rect for the current paint frame.

        :rtype: QtCore.QRect
        """
        return self._rect

    def setRect(self, rect):
        """
        Set the rect for the current paint frame.

        :type rect: QtCore.QRect
        :rtype: None
        """
        self._rect = rect

    def visualRect(self, option):
        """
        Return the visual rect for the item.

        :type option: QtWidgets.QStyleOptionViewItem
        :rtype: QtCore.QRect
        """
        return QtCore.QRect(option.rect)

    def paintRow(self, painter, option, index):
        """
        Paint performs low-level painting for the item.

        :type painter: QtWidgets.QPainter
        :type option: QtWidgets.QStyleOptionViewItem
        :type index: QtCore.QModelIndex
        :rtype: None
        """
        QtWidgets.QTreeWidget.drawRow(self.treeWidget(), painter, option,
                                      index)

    def paint(self, painter, option, index):
        """
        Paint performs low-level painting for the item.

        :type painter: QtWidgets.QPainter
        :type option: QtWidgets.QStyleOptionViewItem
        :type index: QtCore.QModelIndex
        :rtype: None
        """
        self.setRect(QtCore.QRect(option.rect))

        painter.save()

        try:
            self.paintBackground(painter, option, index)

            self.paintIcon(painter, option, index)

            if index.column() == 0 and self.sliderValue() != 0:
                self.paintSlider(painter, option, index)

            if self.isTextVisible():
                self.paintText(painter, option, index)

            if index.column() == 0:
                self.paintTypeIcon(painter, option)

            if index.column() == 0 and self.imageSequence():
                self.paintPlayhead(painter, option)

        finally:
            painter.restore()

    def paintBackground(self, painter, option, index):
        """
        Draw the background for the item.

        :type painter: QtWidgets.QPainter
        :type option: QtWidgets.QStyleOptionViewItem
        :type index: QtCore.QModelIndex
        """
        isSelected = option.state & QtWidgets.QStyle.State_Selected
        isMouseOver = option.state & QtWidgets.QStyle.State_MouseOver
        painter.setPen(QtGui.QPen(QtCore.Qt.NoPen))

        visualRect = self.visualRect(option)

        if isSelected:
            color = self.backgroundSelectedColor()
            painter.setBrush(QtGui.QBrush(color))
        elif isMouseOver:
            color = self.backgroundHoverColor()
            painter.setBrush(QtGui.QBrush(color))
        else:
            color = self.backgroundColor()
            painter.setBrush(QtGui.QBrush(color))

        if not self.itemsWidget().isIconView():
            spacing = 1 * self.dpi()
            height = visualRect.height() - spacing
            visualRect.setHeight(height)

        painter.drawRect(visualRect)

    def paintSlider(self, painter, option, index):
        """
        Draw the virtual slider for the item.

        :type painter: QtWidgets.QPainter
        :type option: QtWidgets.QStyleOptionViewItem
        :type index: QtCore.QModelIndex
        """
        if not self.PAINT_SLIDER:
            return

        if not self.itemsWidget().isIconView():
            return

        # Draw slider background
        painter.setPen(QtGui.QPen(QtCore.Qt.NoPen))

        rect = self.visualRect(option)

        color = self.itemsWidget().backgroundColor().toRgb()
        color.setAlpha(75)
        painter.setBrush(QtGui.QBrush(color))

        height = rect.height()

        ratio = self.sliderValue()

        if ratio < 0:
            width = 0
        elif ratio > 100:
            width = rect.width()
        else:
            width = rect.width() * (float(ratio) / 100)

        rect.setWidth(width)
        rect.setHeight(height)

        painter.drawRect(rect)

        # Draw slider value
        rect = self.visualRect(option)
        rect.setY(rect.y() + (4 * self.dpi()))

        color = self.itemsWidget().textColor().toRgb()
        color.setAlpha(220)
        pen = QtGui.QPen(color)
        align = QtCore.Qt.AlignTop | QtCore.Qt.AlignHCenter

        painter.setPen(pen)
        painter.drawText(rect, align, str(self.sliderValue()) + "%")

    def iconRect(self, option):
        """
        Return the icon rect for the item.

        :type option: QtWidgets.QStyleOptionViewItem
        :rtype: QtCore.QRect
        """
        padding = self.padding()
        rect = self.visualRect(option)
        width = rect.width()
        height = rect.height()

        if self.isLabelUnderItem():
            height -= self.textHeight()

        width -= padding
        height -= padding

        rect.setWidth(width)
        rect.setHeight(height)

        x = 0
        x += float(padding) / 2
        x += float((width - rect.width())) / 2

        y = float((height - rect.height())) / 2
        y += float(padding) / 2

        rect.translate(x, y)
        return rect

    def scalePixmap(self, pixmap, rect):
        """
        Scale the given pixmap to the give rect size.
        
        This method will cache the scaled pixmap if called with the same size.

        :type pixmap: QtGui.QPixmap
        :type rect: QtCore.QRect
        :rtype: QtGui.QPixmap
        """
        rectChanged = True

        if self._pixmapRect:
            widthChanged = self._pixmapRect.width() != rect.width()
            heightChanged = self._pixmapRect.height() != rect.height()

            rectChanged = widthChanged or heightChanged

        if not self._pixmapScaled or rectChanged:

            self._pixmapScaled = pixmap.scaled(
                rect.width(),
                rect.height(),
                QtCore.Qt.KeepAspectRatio,
                QtCore.Qt.SmoothTransformation,
            )

            self._pixmapRect = rect

        return self._pixmapScaled

    def paintIcon(self, painter, option, index, align=None):
        """
        Draw the icon for the item.

        :type painter: QtWidgets.QPainter
        :type option: QtWidgets.QStyleOptionViewItem
        :rtype: None
        """
        column = index.column()
        pixmap = self.pixmap(column)

        if not pixmap:
            return

        rect = self.iconRect(option)
        pixmap = self.scalePixmap(pixmap, rect)

        pixmapRect = QtCore.QRect(rect)
        pixmapRect.setWidth(pixmap.width())
        pixmapRect.setHeight(pixmap.height())

        align = QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter

        x, y = 0, 0

        isAlignBottom = align == QtCore.Qt.AlignBottom | QtCore.Qt.AlignLeft \
                        or align == QtCore.Qt.AlignBottom | QtCore.Qt.AlignHCenter \
                        or align == QtCore.Qt.AlignBottom | QtCore.Qt.AlignRight

        isAlignHCenter = align == QtCore.Qt.AlignHCenter \
                         or align == QtCore.Qt.AlignCenter \
                         or align == QtCore.Qt.AlignHCenter | QtCore.Qt.AlignBottom \
                         or align == QtCore.Qt.AlignHCenter | QtCore.Qt.AlignTop

        isAlignVCenter = align == QtCore.Qt.AlignVCenter \
                         or align == QtCore.Qt.AlignCenter \
                         or align == QtCore.Qt.AlignVCenter | QtCore.Qt.AlignLeft \
                         or align == QtCore.Qt.AlignVCenter | QtCore.Qt.AlignRight

        if isAlignHCenter:
            x += float(rect.width() - pixmap.width()) / 2

        if isAlignVCenter:
            y += float(rect.height() - pixmap.height()) / 2

        elif isAlignBottom:
            y += float(rect.height() - pixmap.height())

        pixmapRect.translate(x, y)
        painter.drawPixmap(pixmapRect, pixmap)

    def drawIconBorder(self, painter, pixmapRect):
        """
        Draw a border around the icon.

        :type painter: QtWidgets.QPainter
        :type pixmapRect: QtWidgets.QRect
        :rtype: None
        """
        pixmapRect = QtCore.QRect(pixmapRect)
        pixmapRect.setX(pixmapRect.x() - 5)
        pixmapRect.setY(pixmapRect.y() - 5)
        pixmapRect.setWidth(pixmapRect.width() + 5)
        pixmapRect.setHeight(pixmapRect.height() + 5)

        color = QtGui.QColor(255, 255, 255, 10)
        painter.setPen(QtGui.QPen(QtCore.Qt.NoPen))
        painter.setBrush(QtGui.QBrush(color))

        painter.drawRect(pixmapRect)

    def fontSize(self):
        """
        Return the font size for the item.

        :rtype: int
        """
        return self.DEFAULT_FONT_SIZE

    def font(self, column):
        """
        Return the font for the given column.

        :type column: int
        :rtype: QtWidgets.QFont
        """
        default = QtWidgets.QTreeWidgetItem.font(self, column)

        font = self._fonts.get(column, default)

        font.setPixelSize(self.fontSize() * self.dpi())
        return font

    def setFont(self, column, font):
        """
        Set the font for the given column.

        :type column: int
        :type font: QtWidgets.QFont
        :rtype: Noen
        """
        self._fonts[column] = font

    def paintText(self, painter, option, index):
        """
        Draw the text for the item.

        :type painter: QtWidgets.QPainter
        :type option: QtWidgets.QStyleOptionViewItem
        :rtype: None
        """
        column = index.column()

        if column == 0 and self.itemsWidget().isTableView():
            return

        self._paintText(painter, option, column)

    def textWidth(self, column):
        text = self.text(column)

        font = self.font(column)
        metrics = QtGui.QFontMetricsF(font)
        textWidth = metrics.width(text)
        return textWidth

    def _paintText(self, painter, option, column):

        if self.itemsWidget().isIconView():
            text = self.name()
        else:
            label = self.labelFromColumn(column)
            text = self.displayText(label)

        isSelected = option.state & QtWidgets.QStyle.State_Selected

        if isSelected:
            color = self.textSelectedColor()
        else:
            color = self.textColor()

        visualRect = self.visualRect(option)

        width = visualRect.width()
        height = visualRect.height()

        padding = self.padding()
        x = padding / 2
        y = padding / 2

        visualRect.translate(x, y)
        visualRect.setWidth(width - padding)
        visualRect.setHeight(height - padding)

        font = self.font(column)
        align = self.textAlignment(column)
        metrics = QtGui.QFontMetricsF(font)

        if text:
            textWidth = metrics.width(text)
        else:
            textWidth = 1

        # # Check if the current text fits within the rect.
        if textWidth > visualRect.width() - padding:
            visualWidth = visualRect.width()
            text = metrics.elidedText(text, QtCore.Qt.ElideRight, visualWidth)
            align = QtCore.Qt.AlignLeft

        align = align | QtCore.Qt.AlignVCenter

        rect = QtCore.QRect(visualRect)

        if self.itemsWidget().isIconView():

            if self.isLabelOverItem() or self.isLabelUnderItem():
                padding = 8 if padding < 8 else padding

                height = metrics.height() + (padding / 2)
                y = (rect.y() + rect.height()) - height

                rect.setY(y)
                rect.setHeight(height)

            if self.isLabelOverItem():
                color2 = self.itemsWidget().backgroundColor().toRgb()
                color2.setAlpha(200)

                painter.setPen(QtCore.Qt.NoPen)
                painter.setBrush(QtGui.QBrush(color2))
                painter.drawRect(rect)

        pen = QtGui.QPen(color)
        painter.setPen(pen)
        painter.setFont(font)
        painter.drawText(rect, align, text)

    # ------------------------------------------------------------------------
    # Support for middle mouse slider
    # ------------------------------------------------------------------------

    def setSliderEnabled(self, enabled):
        """
        Set if middle mouse slider is enabled.

        :type enabled: bool
        """
        self._sliderEnabled = enabled

    def isSliderEnabled(self):
        """
        Return true if middle mouse slider is enabled.

        :rtype: bool
        """
        return self._sliderEnabled

    def sliderEvent(self, event):
        """
        Called when the mouse moves while the middle mouse button is held down.

        :param event: QtGui.QMouseEvent
        """
        if self.isSliderDown():
            value = (event.pos().x() - self.sliderPosition().x()) / 1.5
            value = math.ceil(value) + self.sliderPreviousValue()
            try:
                self.setSliderValue(value)
            except Exception:
                self.setSliderDown(False)

    def resetSlider(self):
        """Reset the slider value to zero."""
        self._sliderValue = 0.0
        self._sliderPreviousValue = 0.0

    def setSliderDown(self, down):
        """Called when the middle mouse button is released."""
        self._sliderDown = down
        if not down:
            self._sliderPosition = None
            self._sliderPreviousValue = self.sliderValue()

    def isSliderDown(self):
        """
        Return True if blending.

        :rtype: bool
        """
        return self._sliderDown

    def setSliderValue(self, value):
        """
        Set the blend value.

        :type value: float
        :rtype: bool
        """
        if self.isSliderEnabled():

            self._sliderValue = value

            if self.PAINT_SLIDER:
                self.update()

            self.sliderChanged.emit(value)

            if self.PAINT_SLIDER:
                self.update()

            logger.debug("Blending:" + str(value))

    def sliderValue(self):
        """
        Return the blend value.

        :rtype: float
        """
        return self._sliderValue

    def sliderPreviousValue(self):
        """
        :rtype: float
        """
        return self._sliderPreviousValue

    def sliderPosition(self):
        """
        :rtype: QtGui.QPoint
        """
        return self._sliderPosition

    # ------------------------------------------------------------------------
    # Support animated image sequence
    # ------------------------------------------------------------------------

    def imageSequenceEvent(self, event):
        """
        :type event: QtCore.QEvent
        :rtype: None
        """
        if self.imageSequence():
            if studioqt.isControlModifier():
                if self.rect():
                    x = event.pos().x() - self.rect().x()
                    width = self.rect().width()
                    percent = 1.0 - (float(width - x) / float(width))
                    frame = int(self.imageSequence().frameCount() * percent)
                    self.imageSequence().jumpToFrame(frame)
                    self.updateFrame()

    def resetImageSequence(self):
        self._imageSequence = None

    def imageSequence(self):
        """
        :rtype: studioqt.ImageSequence
        """
        return self._imageSequence

    def setImageSequence(self, value):
        """
        :type value: studioqt.ImageSequence
        """
        self._imageSequence = value

    def setImageSequencePath(self, path):
        """
        :type path: str
        """
        self._imageSequencePath = path

    def imageSequencePath(self):
        """
        :rtype: str
        """
        return self._imageSequencePath

    def stop(self):
        """Stop playing the image sequence movie."""
        if self.imageSequence():
            self.imageSequence().stop()

    def play(self):
        """Start playing the image sequence movie."""
        self.resetImageSequence()
        path = self.imageSequencePath() or self.thumbnailPath()

        movie = None

        if os.path.isfile(path) and path.lower().endswith(".gif"):

            movie = QtGui.QMovie(path)
            movie.setCacheMode(QtGui.QMovie.CacheAll)
            movie.frameChanged.connect(self._frameChanged)

        elif os.path.isdir(path):

            if not self.imageSequence():
                movie = studioqt.ImageSequence(path)
                movie.frameChanged.connect(self._frameChanged)

        if movie:
            self.setImageSequence(movie)
            self.imageSequence().start()

    def _frameChanged(self, frame):
        """Triggered when the movie object updates to the given frame."""
        if not studioqt.isControlModifier():
            self.updateFrame()

    def updateFrame(self):
        """Triggered when the movie object updates the current frame."""
        if self.imageSequence():
            pixmap = self.imageSequence().currentPixmap()
            self.setIcon(0, pixmap)

    def playheadColor(self):
        """
        Return the playhead color.

        :rtype: QtGui.Color
        """
        return self.DEFAULT_PLAYHEAD_COLOR

    def paintPlayhead(self, painter, option):
        """
        Paint the playhead if the item has an image sequence.

        :type painter: QtWidgets.QPainter
        :type option: QtWidgets.QStyleOptionViewItem
        :rtype: None
        """
        imageSequence = self.imageSequence()

        if imageSequence and self.underMouse():

            count = imageSequence.frameCount()
            current = imageSequence.currentFrameNumber()

            if count > 0:
                percent = float((count + current) + 1) / count - 1
            else:
                percent = 0

            r = self.iconRect(option)
            c = self.playheadColor()

            painter.setPen(QtCore.Qt.NoPen)
            painter.setBrush(QtGui.QBrush(c))

            if percent <= 0:
                width = 0
            elif percent >= 1:
                width = r.width()
            else:
                width = (percent * r.width()) - 1

            height = 3 * self.dpi()
            y = r.y() + r.height() - (height - 1)

            painter.drawRect(r.x(), y, width, height)

    def typeIconPath(self):
        """
        Return the type icon path on disc.

        :rtype: path or None
        """
        if self.TYPE_ICON_PATH is None:
            return self.ICON_PATH

        return self.TYPE_ICON_PATH

    def typePixmap(self):
        """
        Return the type pixmap for the plugin.

        :rtype: QtWidgets.QPixmap
        """
        if not self._typePixmap:
            iconPath = self.typeIconPath()
            if iconPath and os.path.exists(iconPath):
                self._typePixmap = QtGui.QPixmap(iconPath)
        return self._typePixmap

    def typeIconRect(self, option):
        """
        Return the type icon rect.

        :rtype: QtGui.QRect
        """
        padding = 2 * self.dpi()
        r = self.iconRect(option)

        x = r.x() + padding
        y = r.y() + padding
        rect = QtCore.QRect(x, y, 13 * self.dpi(), 13 * self.dpi())

        return rect

    def paintTypeIcon(self, painter, option):
        """
        Draw the item type icon at the top left.

        :type painter: QtWidgets.QPainter
        :type option: QtWidgets.QStyleOptionViewItem
        :rtype: None
        """
        rect = self.typeIconRect(option)
        typePixmap = self.typePixmap()
        if typePixmap:
            painter.setOpacity(0.5)
            painter.drawPixmap(rect, typePixmap)
            painter.setOpacity(1)
Ejemplo n.º 16
0
    def fa(cls, path, **kwargs):
        """
        Create a new icon with the given path, options and state.
        
        Example:
            icon = studioqt.Icon.fa(
                path,
                color="rgb(255,255,255)"
                color_disabled="rgb(0,200,200,20)",
            )

        :type path: str
        :type kwargs: dict
        
        :rtype: studioqt.Icon 
        """
        color = kwargs.get('color', QtGui.QColor(0, 0, 0))

        pixmap = studioqt.Pixmap(path)
        pixmap.setColor(color)

        valid_options = [
            'active',
            'selected',
            'disabled',
            'on',
            'off',
            'on_active',
            'on_selected',
            'on_disabled',
            'off_active',
            'off_selected',
            'off_disabled',
            'color',
            'color_on',
            'color_off',
            'color_active',
            'color_selected',
            'color_disabled',
            'color_on_selected',
            'color_on_active',
            'color_on_disabled',
            'color_off_selected',
            'color_off_active',
            'color_off_disabled',
        ]

        default = {
            "on_active": kwargs.get("active", studioqt.Pixmap(path)),
            "off_active": kwargs.get("active", studioqt.Pixmap(path)),
            "on_disabled": kwargs.get("disabled", studioqt.Pixmap(path)),
            "off_disabled": kwargs.get("disabled", studioqt.Pixmap(path)),
            "on_selected": kwargs.get("selected", studioqt.Pixmap(path)),
            "off_selected": kwargs.get("selected", studioqt.Pixmap(path)),
            "color_on_active": kwargs.get("color_active", color),
            "color_off_active": kwargs.get("color_active", color),
            "color_on_disabled": kwargs.get("color_disabled", color),
            "color_off_disabled": kwargs.get("color_disabled", color),
            "color_on_selected": kwargs.get("color_selected", color),
            "color_off_selected": kwargs.get("color_selected", color),
        }

        default.update(kwargs)
        kwargs = copy.copy(default)

        for option in valid_options:
            if 'color' in option:
                kwargs[option] = kwargs.get(option, color)
            else:
                svg_path = kwargs.get(option, path)
                kwargs[option] = studioqt.Pixmap(svg_path)

        options = {
            QtGui.QIcon.On: {
                QtGui.QIcon.Normal: (kwargs['color_on'], kwargs['on']),
                QtGui.QIcon.Active: (kwargs['color_on_active'], kwargs['on_active']),
                QtGui.QIcon.Disabled: (kwargs['color_on_disabled'], kwargs['on_disabled']),
                QtGui.QIcon.Selected: (kwargs['color_on_selected'], kwargs['on_selected'])
            },

            QtGui.QIcon.Off: {
                QtGui.QIcon.Normal: (kwargs['color_off'], kwargs['off']),
                QtGui.QIcon.Active: (kwargs['color_off_active'], kwargs['off_active']),
                QtGui.QIcon.Disabled: (kwargs['color_off_disabled'], kwargs['off_disabled']),
                QtGui.QIcon.Selected: (kwargs['color_off_selected'], kwargs['off_selected'])
            }
        }

        icon = cls(pixmap)

        for state in options:
            for mode in options[state]:
                color, pixmap = options[state][mode]

                pixmap = studioqt.Pixmap(pixmap)
                pixmap.setColor(color)

                icon.addPixmap(pixmap, mode, state)

        return icon
class ImageSequenceWidget(QtWidgets.QToolButton):

    DEFAULT_PLAYHEAD_COLOR = QtGui.QColor(255, 255, 255, 220)

    def __init__(self,  *args):
        QtWidgets.QToolButton.__init__(self, *args)

        self._imageSequence = ImageSequence("")
        self._imageSequence.frameChanged.connect(self._frameChanged)

        self._toolBar = QtWidgets.QToolBar(self)
        self._toolBar.setStyleSheet(STYLE)

        studioqt.fadeOut(self._toolBar, duration=0)

        spacer = QtWidgets.QWidget()
        spacer.setMaximumWidth(4)
        spacer.setSizePolicy(
            QtWidgets.QSizePolicy.Expanding,
            QtWidgets.QSizePolicy.Preferred
        )
        self._toolBar.addWidget(spacer)

        spacer = QtWidgets.QWidget()
        spacer.setMaximumWidth(4)
        spacer.setSizePolicy(
            QtWidgets.QSizePolicy.Expanding,
            QtWidgets.QSizePolicy.Preferred
        )
        self._firstSpacer = self._toolBar.addWidget(spacer)

        self.setSize(150, 150)
        self.setMouseTracking(True)

    def hasFrames(self):
        """
        Check if the images sequence has any frames.

        :rtype: bool
        """
        return bool(self.firstFrame())

    def firstFrame(self):
        """
        Get the first frame in the image sequence.

        :rtype: str
        """
        return self._imageSequence.firstFrame()

    def isSequence(self):
        """
        Check if the image sequence has more than one frame.

        :rtype: bool
        """
        return bool(self._imageSequence.frameCount() > 1)

    def dirname(self):
        """
        Get the directory to the image sequence on disk.

        :rtype: str
        """
        return self._imageSequence.dirname()

    def addAction(self, path, text, tip, callback):
        """
        Add an action to the tool bar.
        
        :type path: str 
        :type text: str
        :type tip: str
        :type callback: func
        
        :rtype: QtWidgets.QAction
        """
        icon = studioqt.Icon.fa(
            path,
            color="rgb(250,250,250,160)",
            color_active="rgb(250,250,250,250)",
            color_disabled="rgb(0,0,0,20)"
        )

        action = QtWidgets.QAction(icon, text, self._toolBar)
        action.setToolTip(tip)
        # action.setStatusTip(tip)
        # action.setWhatsThis(tip)

        self._toolBar.insertAction(self._firstSpacer, action)
        action.triggered.connect(callback)

        return action

    def actions(self):
        """
        Get all the actions that are a child of the ToolBar.

        :rtype: list[QtWidgets.QAction] 
        """
        actions = []

        for child in self._toolBar.children():
            if isinstance(child, QtWidgets.QAction):
                actions.append(child)

        return actions

    def resizeEvent(self, event):
        """
        Called when the widget is resized.
        
        :type event: QtWidgets.QResizeEvent 
        """
        self.updateToolBar()

    def updateToolBar(self):
        """Update the tool bar size depending on the number of actions."""

        self._toolBar.setIconSize(QtCore.QSize(16, 16))

        count = (len(self.actions())) - 3
        width = (26 * count)

        self._toolBar.setGeometry(0, 0, width, 25)

        x = self.rect().center().x() - (self._toolBar.width()/2)
        y = self.height() - self._toolBar.height() - 12
        width = self._toolBar.width()

        self._toolBar.setGeometry(x, y,  width,  self._toolBar.height())

    def isControlModifier(self):
        """
        Check if the the control modifier is active.
        
        :rtype: bool
        """
        modifiers = QtWidgets.QApplication.keyboardModifiers()
        return modifiers == QtCore.Qt.ControlModifier

    def setSize(self, w, h):
        """
        Reimplemented so that the icon size is set at the same time.

        :type w: int
        :type h: int
        :rtype: None
        """
        self._size = QtCore.QSize(w, h)
        self.setIconSize(self._size)
        self.setFixedSize(self._size)

    def setPath(self, path):
        """
        Set a single frame image sequence.
        
        :type path: str
        """
        self._imageSequence.setPath(path)
        self.updateIcon()

    def setDirname(self, dirname):
        """
        This method has been deprecated.

        Please use setPath instead.

        :type dirname: str
        """
        self._imageSequence.setPath(dirname)
        self.updateIcon()

    def updateIcon(self):
        """Update the icon for the current frame."""
        if self._imageSequence.frames():
            icon = self._imageSequence.currentIcon()
            self.setIcon(icon)

    def enterEvent(self, event):
        """
        Start playing the image sequence when the mouse enters the widget.

        :type event: QtCore.QEvent
        :rtype: None
        """
        self._imageSequence.start()
        studioqt.fadeIn(self._toolBar, duration=300)

    def leaveEvent(self, event):
        """
        Stop playing the image sequence when the mouse leaves the widget.

        :type event: QtCore.QEvent
        :rtype: None
        """
        self._imageSequence.pause()
        studioqt.fadeOut(self._toolBar, duration=300)

    def mouseMoveEvent(self, event):
        """
        Reimplemented to add support for scrubbing.

        :type event: QtCore.QEvent
        :rtype: None
        """
        if self.isControlModifier() and self._imageSequence.frameCount() > 1:
            percent = 1.0 - (float(self.width() - event.pos().x()) / float(self.width()))
            frame = int(self._imageSequence.frameCount() * percent)
            self._imageSequence.jumpToFrame(frame)
            icon = self._imageSequence.currentIcon()
            self.setIcon(icon)

    def _frameChanged(self, frame=None):
        """
        Triggered when the image sequence changes frame.

        :type frame: int or None
        :rtype: None
        """
        if not self.isControlModifier():
            icon = self._imageSequence.currentIcon()
            self.setIcon(icon)

    def currentFilename(self):
        """
        Return the current image location.

        :rtype: str
        """
        return self._imageSequence.currentFilename()

    def playheadHeight(self):
        """
        Return the height of the playhead.

        :rtype: int
        """
        return 4

    def paintEvent(self, event):
        """
        Triggered on frame changed.

        :type event: QtCore.QEvent
        :rtype: None
        """
        QtWidgets.QToolButton.paintEvent(self, event)

        painter = QtGui.QPainter()
        painter.begin(self)

        if self.currentFilename() and self._imageSequence.frameCount() > 1:

            r = event.rect()

            playheadHeight = self.playheadHeight()
            playheadPosition = self._imageSequence.percent() * r.width()-1

            x = r.x()
            y = self.height() - playheadHeight

            painter.setPen(QtCore.Qt.NoPen)
            painter.setBrush(QtGui.QBrush(self.DEFAULT_PLAYHEAD_COLOR))
            painter.drawRect(x, y, playheadPosition, playheadHeight)

        painter.end()