def browseColor(self):
        """
        Show the color dialog.

        :rtype: None
        """
        color = self.currentColor()

        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)
示例#2
0
    def browseBackgroundColor(self):
        """
        :rtype: None
        """
        color = self.backgroundColor()
        d = QtWidgets.QColorDialog(self)
        d.setCurrentColor(color)
        colors = [(0, 0, 0), (20, 20, 30), (0, 30, 60), (0, 60, 60),
                  (0, 60, 30), (60, 0, 10), (60, 0, 40), (40, 15, 5)]
        index = -1
        for colorR, colorG, colorB in colors:
            for i in range(0, 6):
                index += 1
                try:
                    standardColor = QtGui.QColor(colorR, colorG, colorB)
                    d.setStandardColor(index, standardColor)
                except:
                    standardColor = QtGui.QColor(colorR, colorG, colorB).rgba()
                    d.setStandardColor(index, standardColor)

                colorR += 20
                colorB += 20
                colorG += 20

        d.currentColorChanged.connect(self.setBackgroundColor)
        d.open(self, QtCore.SLOT('blankSlot()'))
        if d.exec_():
            self.setBackgroundColor(d.selectedColor())
        else:
            self.setBackgroundColor(color)
示例#3
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._isItemTextVisible = True

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

        self._support_drag = self.DEFAULT_SUPPORT_DRAG
        self._listView = ListView(self._support_drag, self)
        self._listView.setTreeWidget(self._treeWidget)

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

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

        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._backgroundColor = 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
示例#4
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)
示例#5
0
 def createWidget(self, parent):
     """
     :type parent: QtWidgets.QMenu
     """
     height = 25
     spacing = 1
     options = self.library().theme().options()
     styleSheet = studioqt.StyleSheet.fromText(LibraryAction.STYLE_SHEET, options=options)
     actionWidget = QtWidgets.QFrame(parent)
     actionWidget.setObjectName('actionWidget')
     actionWidget.setStyleSheet(styleSheet.data())
     actionLabel = QtWidgets.QLabel(self.library().name(), actionWidget)
     actionLabel.setObjectName('actionLabel')
     actionLabel.setFixedHeight(height)
     iconColor = QtGui.QColor(255, 255, 255, 220)
     icon = studiolibrary.resource().icon('delete', color=iconColor)
     actionOption = QtWidgets.QPushButton('', actionWidget)
     actionOption.setObjectName('actionOption')
     actionOption.setIcon(icon)
     actionOption.setFixedHeight(height + spacing)
     actionOption.setFixedWidth(height)
     actionOption.clicked.connect(self.deleteLibrary)
     actionIcon = QtWidgets.QLabel('', actionWidget)
     actionIcon.setObjectName('actionIcon')
     actionIcon.setFixedWidth(10)
     actionIcon.setFixedHeight(height)
     actionLayout = QtWidgets.QHBoxLayout(actionWidget)
     actionLayout.setSpacing(0)
     actionLayout.setContentsMargins(0, 0, 0, 0)
     actionLayout.addWidget(actionIcon, stretch=1)
     actionLayout.addWidget(actionLabel, stretch=1)
     actionLayout.addWidget(actionOption, stretch=1)
     return actionWidget
示例#6
0
    def createBackgroundColorBar(self):
        """
        Create and setup the background color bar.

        :rtype: None
        """
        browserColors_ = [
            (0, 0, 0),
            (20, 20, 30),
            (0, 30, 60),
            (0, 60, 60),
            (0, 60, 30),
            (60, 0, 10),
            (60, 0, 40),
            (40, 15, 5),
        ]

        browserColors = []
        for colorR, colorG, colorB in browserColors_:
            for i in range(0, 6):

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

                colorR += 20
                colorB += 20
                colorG += 20

        hColorBar = studioqt.HColorBar()
        hColorBar.setColors(self.DEFAULT_BACKGROUND_COLORS)
        hColorBar.setCurrentColor(self.DEFAULT_BACKGROUND_COLOR)
        hColorBar.setBrowserColors(browserColors)
        hColorBar.colorChanged.connect(self._backgroundColorClicked)

        self.ui.backgroundColorBarFrame.layout().addWidget(hColorBar)
    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)
示例#8
0
    def __init__(self, supportDrag=True, *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(supportDrag)
        self.setDragEnabled(supportDrag)
        self.setDragDropMode(QtWidgets.QAbstractItemView.DragDrop)

        self.clicked.connect(self._indexClicked)
        self.doubleClicked.connect(self._indexDoubleClicked)
示例#9
0
    def backgroundColor(self):
        """
        Return the background color for the item.

        :rtype: QtWidgets.QtColor
        """
        return QtGui.QColor(0, 0, 0, 0)
示例#10
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)
示例#11
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
        """
        studioqt.CombinedWidgetItem.paintBackground(self, painter, option,
                                                    index)

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

        textWidth = self.textWidth(0)

        padding = (20 * 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(250, 250, 250, 20)
        painter.setBrush(QtGui.QBrush(color))

        painter.drawRect(visualRect)
示例#12
0
    def backgroundSelectedColor(self):
        """
        Return the background color when the item is selected.

        :rtype: QtWidgets.QtColor
        """
        return QtGui.QColor(0, 0, 0, 0)
示例#13
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))
示例#14
0
    def browseColor(self):
        """
        :rtype: None
        """
        color = self.color()
        d = QtWidgets.QColorDialog(self)
        d.setCurrentColor(color)
        colors = [(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)]
        index = -1
        for colorR, colorG, colorB in colors:
            for i in range(0, 3):
                index += 1
                if colorR < 0:
                    colorR = 0
                if colorG < 0:
                    colorG = 0
                if colorB < 0:
                    colorB = 0
                try:
                    standardColor = QtGui.QColor(colorR, colorG, colorB)
                    d.setStandardColor(index, standardColor)
                except:
                    standardColor = QtGui.QColor(colorR, colorG, colorB).rgba()
                    d.setStandardColor(index, standardColor)

                colorR -= 20
                colorB -= 20
                colorG -= 20

        d.currentColorChanged.connect(self.setColor)
        d.open(self, QtCore.SLOT('blankSlot()'))
        if d.exec_():
            self.setColor(d.selectedColor())
        else:
            self.setColor(color)
    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
示例#16
0
    def browseColor(self):
        """
        Show the color dialog.

        :rtype: None
        """
        color = self.currentColor()

        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)

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

        if d.exec_():
            self._colorChanged(d.selectedColor())
        else:
            self._colorChanged(color)
示例#17
0
    def createAccentColorBar(self):
        """
        Create and setup the accent color bar.

        :rtype: None
        """
        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),
        ]

        browserColors = []
        for colorR, colorG, colorB in browserColors_:
            for i in range(0, 3):

                colorR = colorR if colorR > 0 else 0
                colorG = colorG if colorG > 0 else 0
                colorB = colorB if colorB > 0 else 0

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

                colorR -= 20
                colorB -= 20
                colorG -= 20

        hColorBar = studioqt.HColorBar()
        hColorBar.setColors(self.DEFAULT_ACCENT_COLORS)
        hColorBar.setCurrentColor(self.DEFAULT_ACCENT_COLOR)
        hColorBar.setBrowserColors(browserColors)
        hColorBar.colorChanged.connect(self._accentColorChanged)

        self.ui.accentColorBarFrame.layout().addWidget(hColorBar)
示例#18
0
def example():
    """
    Example to show/test the HColorBar.

    :rtype: None
    """

    def _colorChanged(color):
        print "colorChanged:", color

    theme = studioqt.Theme()

    colors = [
        studioqt.Color(230, 60, 60, 255),
        studioqt.Color(255, 90, 40),
        studioqt.Color(255, 125, 100, 255),
        studioqt.Color(250, 200, 0, 255),
        studioqt.Color(80, 200, 140, 255),
        studioqt.Color(50, 180, 240, 255),
        studioqt.Color(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)

    colorBar = HColorBar()
    colorBar.setColors(colors)
    colorBar.setBrowserColors(browserColors)
    colorBar.colorChanged.connect(_colorChanged)
    colorBar.show()
示例#19
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)
示例#20
0
class LibraryItem(studioqt.CombinedWidgetItem):
    DEFAULT_PLAYHEAD_COLOR = QtGui.QColor(255, 255, 255, 220)
    itemSignal = ListWidgetItemSignal()

    def __init__(self):
        studioqt.CombinedWidgetItem.__init__(self)
        self._typePixmap = None
        self._typeIconPath = None
        self._imageSequence = None
        self._imageSequencePath = None
        self._blendValue = 0.0
        self._blendPreviousValue = 0.0
        self._blendPosition = None
        self._blendingEnabled = False
        self.blendChanged = self.itemSignal.blendChanged

    def __del__(self):
        self.stop()

    def setTypeIconPath(self, path):
        self._typeIconPath = path

    def typeIconPath(self):
        return self._typeIconPath

    def setBlendingEnabled(self, enabled):
        self._blendingEnabled = enabled

    def isBlendingEnabled(self):
        return self._blendingEnabled

    def blendingEvent(self, event):
        if self.isBlending():
            value = (event.pos().x() - self.blendPosition().x()) / 1.5
            value = math.ceil(value) + self.blendPreviousValue()
            try:
                self.setBlendValue(value)
            except Exception as msg:
                self.stopBlending()

    def startBlendingEvent(self, event):
        if self.isBlendingEnabled():
            if event.button() == QtCore.Qt.MidButton:
                self._blendPosition = event.pos()

    def stopBlending(self):
        self._blendPosition = None
        self._blendPreviousValue = self.blendValue()

    def resetBlending(self):
        """
        :rtype: None
        """
        self._blendValue = 0.0
        self._blendPreviousValue = 0.0

    def isBlending(self):
        """
        :rtype: bool | None
        """
        return self.blendPosition() is not None

    def setBlendValue(self, value):
        """
        :type value: float
        :rtype: bool
        """
        if self.isBlendingEnabled():
            self._blendValue = value
            self.blendChanged.emit(value)
            logger.debug('BLENDING:' + str(value))

    def blendValue(self):
        """
        :rtype: float
        """
        return self._blendValue

    def blendPreviousValue(self):
        """
        :rtype: float
        """
        return self._blendPreviousValue

    def blendPosition(self):
        """
        :rtype: QtGui.QPoint
        """
        return self._blendPosition

    def selectionChanged(self):
        """
        :rtype: QtGui.QPoint
        """
        self.resetBlending()

    def mouseEnterEvent(self, event):
        """
        :type event: QtGui.QEvent
        """
        studioqt.CombinedWidgetItem.mouseEnterEvent(self, event)
        self._imageSequence = None
        self.play()

    def mouseLeaveEvent(self, event):
        """
        :type event: QtGui.QEvent
        """
        studioqt.CombinedWidgetItem.mouseLeaveEvent(self, event)
        self.stop()

    def mousePressEvent(self, event):
        """
        :type event: QtCore.QEvent
        """
        studioqt.CombinedWidgetItem.mousePressEvent(self, event)
        if event.button() == QtCore.Qt.MidButton:
            self._blendPosition = event.pos()

    def mouseReleaseEvent(self, event):
        """
        :type event: QtCore.QEvent
        """
        if self.isBlending():
            self._blendPosition = None
            self._blendPreviousValue = self.blendValue()
            studioqt.CombinedWidgetItem.mouseReleaseEvent(self, event)

    def mouseMoveEvent(self, event):
        """
        :type event: QtCore.QEvent
        """
        studioqt.CombinedWidgetItem.mouseMoveEvent(self, event)
        self.blendingEvent(event)
        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().duration() * percent)
                    self.imageSequence().setCurrentFrame(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
        :rtype: None
        """
        self._imageSequencePath = path

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

    def stop(self):
        """
        :rtype: None
        """
        if self.imageSequence():
            self.imageSequence().stop()

    def play(self):
        """
        :rtype: None
        """
        if self.imageSequencePath():
            if not self.imageSequence():
                imageSequence = studioqt.ImageSequence()
                imageSequence.setDirname(self.imageSequencePath())
                imageSequence.frameChanged.connect(self._frameChanged)
                self.setImageSequence(imageSequence)
            self.imageSequence().start()

    def _frameChanged(self):
        """
        :rtype: None
        """
        if not studioqt.isControlModifier():
            self.updateFrame()

    def updateFrame(self):
        """
        :rtype: None
        """
        filename = self.imageSequence().currentFilename()
        icon = QtGui.QIcon(filename)
        self.setIcon(0, icon)

    def playheadColor(self):
        """
        :rtype: str
        """
        return self.DEFAULT_PLAYHEAD_COLOR

    def paintPlayhead(self, painter, option):
        """
        :type painter: QtGui.QPainter
        :param option:
        """
        if self.imageSequence().currentFilename():
            r = self.iconRect(option)
            c = self.playheadColor()
            imageSequence = self.imageSequence()
            painter.setPen(QtCore.Qt.NoPen)
            painter.setBrush(QtGui.QBrush(c))
            if imageSequence.percent() <= 0:
                width = 0
            elif imageSequence.percent() >= 1:
                width = r.width()
            else:
                width = imageSequence.percent() * r.width() - 1
            height = 3 * self.dpi()
            y = r.y() + r.height() - (height - 1)
            painter.drawRect(r.x(), y, width, height)

    def typeIconRect(self, option):
        """
        :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):
        """
        :type painter: QtGui.QPainter
        :type option:
        """
        rect = self.typeIconRect(option)
        if not self._typePixmap:
            path = self.typeIconPath()
            if path:
                self._typePixmap = QtGui.QPixmap(path)
        if self._typePixmap:
            painter.setOpacity(0.5)
            painter.drawPixmap(rect, self._typePixmap)
            painter.setOpacity(1)

    def paint(self, painter, option, index):
        """
        :type painter: QtGui.QPainter
        :type option:
        """
        studioqt.CombinedWidgetItem.paint(self, painter, option, index)
        painter.save()
        try:
            if index.column() == 0:
                self.paintTypeIcon(painter, option)
                if self.imageSequence():
                    self.paintPlayhead(painter, option)
        finally:
            painter.restore()
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().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()
示例#22
0
class Item(QtWidgets.QTreeWidgetItem):
    """The Item is used to hold rows of information for an item view."""

    SortRole = "SortRole"
    DataRole = "DataRole"

    ThreadPool = QtCore.QThreadPool()
    DefaultThumbnailPath = ""

    MAX_ICON_SIZE = 256

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

    THUMBNAIL_COLUMN = 0
    ENABLE_THUMBNAIL_THREAD = True

    _globalSignals = GlobalSignals()
    blendChanged = _globalSignals.blendChanged

    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 = ""
        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 = None

        self._blendValue = 0.0
        self._blendPreviousValue = 0.0
        self._blendPosition = None
        self._blendingEnabled = 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.resetBlending()

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

        :rtype: None
        """
        pass

    def setGroupItem(self, groupItem):
        self._groupItem = groupItem

    def groupItem(self):
        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.isTextVisible():
                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.DefaultThumbnailPath

    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):
        """
        Return True if the text is visible.

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

    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.blendingEvent(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:
            self._blendPosition = 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.isBlending():
            self._blendPosition = None
            self._blendPreviousValue = self.blendValue()

    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().backgroundColor()

    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
        """
        rect = QtCore.QRect(option.rect)
        return 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)

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

            self.paintIcon(painter, option, index)

            if index.column() == 0:
                if 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
        :rtype: None
        """
        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))

        painter.drawRect(visualRect)

    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.isTextVisible() and self.itemsWidget().isIconView():
            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

        if self.itemsWidget().isIconView():
            align = align | QtCore.Qt.AlignBottom
        else:
            align = align | QtCore.Qt.AlignVCenter

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

    # ------------------------------------------------------------------------
    # Support for middle mouse blending (slider)
    # ------------------------------------------------------------------------

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

        :type enabled: bool
        :rtype: None
        """
        self._blendingEnabled = enabled

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

        :rtype: None
        """
        return self._blendingEnabled

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

        :param event: QtGui.QMouseEvent
        :rtype: None
        """
        if self.isBlending():
            value = (event.pos().x() - self.blendPosition().x()) / 1.5
            value = math.ceil(value) + self.blendPreviousValue()
            try:
                self.setBlendValue(value)
            except Exception:
                self.stopBlending()

    def startBlendingEvent(self, event):
        """
        Called when the middle mouse button is pressed.

        :param event: QtGui.QMouseEvent
        :rtype: None
        """
        if self.isBlendingEnabled():
            if event.button() == QtCore.Qt.MidButton:
                self._blendPosition = event.pos()

    def stopBlending(self):
        """
        Called when the middle mouse button is released.

        :param event: QtGui.QMouseEvent
        :rtype: None
        """
        self._blendPosition = None
        self._blendPreviousValue = self.blendValue()

    def resetBlending(self):
        """
        Reset the blending value to zero.

        :rtype: None
        """
        self._blendValue = 0.0
        self._blendPreviousValue = 0.0

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

        :rtype: bool
        """
        return self.blendPosition() is not None

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

        :type value: float
        :rtype: bool
        """
        if self.isBlendingEnabled():
            self._blendValue = value
            self.blendChanged.emit(value)
            logger.debug("BLENDING:" + str(value))

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

        :rtype: float
        """
        return self._blendValue

    def blendPreviousValue(self):
        """
        :rtype: float
        """
        return self._blendPreviousValue

    def blendPosition(self):
        """
        :rtype: QtGui.QPoint
        """
        return self._blendPosition

    # ------------------------------------------------------------------------
    # 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
        :rtype: None
        """
        self._imageSequencePath = path

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

    def stop(self):
        """
        :rtype: None
        """
        if self.imageSequence():
            self.imageSequence().stop()

    def play(self):
        """
        :rtype: None
        """
        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)
示例#23
0
class CombinedWidgetItem(QtWidgets.QTreeWidgetItem):
    """
    Combined Widget items are used to hold rows of information for a
    combined widget.
    """
    MAX_ICON_SIZE = 256

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

    _globalSignals = GlobalSignals()
    blendChanged = _globalSignals.blendChanged

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

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

        self._text = {}
        self._sortText = {}
        self._displayText = {}

        self._icon = {}
        self._fonts = {}
        self._pixmap = {}
        self._pixmapRect = None
        self._iconPath = ""
        self._underMouse = False
        self._searchText = None
        self._infoWidget = None
        self._groupColumn = 0
        self._mimeText = None
        self._combinedWidget = None
        self._stretchToWidget = None

        self._dragEnabled = True

        self._imageSequence = None
        self._imageSequencePath = None

        self._blendValue = 0.0
        self._blendPreviousValue = 0.0
        self._blendPosition = None
        self._blendingEnabled = 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 toJson(self):
        """
        Return a dict of the current item text.

        :rtype: dict[]
        """
        return self._text

    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.combinedWidget().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 setData(self, column, role, value):
        """
        Reimplemented to set the search text to dirty.

        Set the value for the item's column and role to the given value.

        :type column: int or str
        :type role: int
        :type value: QtCore.QVariant
        :rtype: None
        """
        self._searchText = None
        QtWidgets.QTreeWidgetItem.setData(self, column, role, value)

    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
        :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 = studioqt.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)

    def data(self, column, role, **kwargs):
        """
        Reimplemented to add support for setting the sort data.

        :type column: int
        :type role: int
        :type kwargs: dict
        :rtype: object
        """
        if role == QtCore.Qt.DisplayRole:

            text = self.sortText(column)
            if not text:
                text = QtWidgets.QTreeWidgetItem.data(self, column, role)

        else:
            text = QtWidgets.QTreeWidgetItem.data(self, column, role)

        return text

    def setText(self, column, value, alignment=None):
        """
        Set the text to be displayed for the given column.

        :type column: int or str
        :type value: str
        :rtype: None
        """
        self.textColumnOrder.append(column)

        if isinstance(column, basestring):
            self._text[column] = value
        else:
            QtWidgets.QTreeWidgetItem.setText(self, column, unicode(value))

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

        :type column: int or str
        :rtype: str
        """
        # if isinstance(column, int):
        #     column = self.treeWidget().labelFromColumn(column)

        if isinstance(column, basestring):
            text = self._sortText.get(column)
            if not text:
                text = self._text.get(column, "")
        else:
            text = QtWidgets.QTreeWidgetItem.text(self, column)

        return text

    def setSortText(self, column, value):
        """
        Set the sort data for the given column.

        :type column: int
        :int value: str
        :rtype: None
        """
        self._sortText[column] = value

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

        :type column: int
        :rtype: str
        """

        if isinstance(column, int):
            column = self.treeWidget().labelFromColumn(column)

        text = self._sortText.get(column, None)
        if not text:
            text = self._text.get(column, "")

        return text

    def displayText(self, column):
        """
        Return the data to be displayed for the given column.

        :type column: int
        :rtype: str
        """
        if isinstance(column, basestring):
            text = self._text.get(column, "")

        else:
            # Check the text before the display role data
            label = self.treeWidget().labelFromColumn(column)
            text = self._text.get(label, "")

            if not text:
                text = QtWidgets.QTreeWidgetItem.data(self, column,
                                                      QtCore.Qt.DisplayRole)

        return text

    def updateData(self):
        """
        Update the text data to the corresponding column.

        :rtype: None
        """
        treeWidget = self.treeWidget()

        for label in self._text:
            column = treeWidget.columnFromLabel(label)

            if column < 0:
                treeWidget.addHeaderLabel(label)

            text = self._text[label]
            self.setText(column, text)

        for label in self._icon:
            column = treeWidget.columnFromLabel(label)
            self.setIcon(column, self._icon[label])

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

        :rtype: int
        """
        if self.combinedWidget():
            return self.combinedWidget().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
        """
        pass

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

        :rtype: None
        """
        pass

    def combinedWidget(self):
        """
        Returns the combined widget that contains the item.

        :rtype: CombinedWidget
        """
        combinedWidget = None

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

        return combinedWidget

    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:
            searchText = []
            for column in range(self.columnCount()):
                text = self.data(column, QtCore.Qt.DisplayRole)
                if text:
                    searchText.append(text)
            self._searchText = " ".join(searchText)

        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.combinedWidget().iconSize()

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

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

            if self.isTextVisible():
                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 ""

    def icon(self, column):
        icon = QtWidgets.QTreeWidgetItem.icon(self, column)
        if not icon and column == 0:
            iconPath = self.thumbnailPath()
            if iconPath:
                icon = QtGui.QIcon(iconPath)
        return icon

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

        :type column:
        :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.combinedWidget().padding()

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

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

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

        :rtype: bool
        """
        return self.combinedWidget().isItemTextVisible()

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

        :type column: int
        :rtype: QtCore.Qt.AlignmentFlag
        """
        if self.combinedWidget().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 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.blendingEvent(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:
            self._blendPosition = 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.isBlending():
            self._blendPosition = None
            self._blendPreviousValue = self.blendValue()

    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.combinedWidget().palette().color(self.combinedWidget().foregroundRole())
        return self.combinedWidget().textColor()

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

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

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

        :rtype: QtWidgets.QtColor
        """
        return self.combinedWidget().backgroundColor()

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

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

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

        :rtype: QtWidgets.QtColor
        """
        return self.combinedWidget().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
        """
        rect = QtCore.QRect(option.rect)
        return rect

    def repaint(self):
        self.update(self.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)

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

            self.paintIcon(painter, option, index)

            if index.column() == 0:
                if 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
        :rtype: None
        """
        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))

        painter.drawRect(visualRect)

    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.isTextVisible() and self.combinedWidget().isIconView():
            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 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 = pixmap.scaled(
            rect.width(),
            rect.height(),
            QtCore.Qt.KeepAspectRatio,
            QtCore.Qt.SmoothTransformation,
        )

        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 option: QtWidgets.QStyleOptionViewItem
        :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
        """
        font = self._fonts.get(column,
                               QtWidgets.QTreeWidgetItem.font(self, column))
        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.combinedWidget().isTableView():
            return

        self._paintText(painter, option, column)

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

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

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

        text = self.displayText(column)

        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:
            text = metrics.elidedText(text, QtCore.Qt.ElideRight,
                                      visualRect.width())
            align = QtCore.Qt.AlignLeft

        if self.combinedWidget().isIconView():
            align = align | QtCore.Qt.AlignBottom
        else:
            align = align | QtCore.Qt.AlignVCenter

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

    # ------------------------------------------------------------------------
    # Support for middle mouse blending (slider)
    # ------------------------------------------------------------------------

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

        :type enabled: bool
        :rtype: None
        """
        self._blendingEnabled = enabled

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

        :rtype: None
        """
        return self._blendingEnabled

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

        :param event: QtGui.QMouseEvent
        :rtype: None
        """
        if self.isBlending():
            value = (event.pos().x() - self.blendPosition().x()) / 1.5
            value = math.ceil(value) + self.blendPreviousValue()
            try:
                self.setBlendValue(value)
            except Exception, msg:
                self.stopBlending()
示例#24
0
class MenuBarWidget(QtWidgets.QFrame):

    ICON_COLOR = QtGui.QColor(255, 255, 255)

    SPACING = 4

    DEFAULT_EXPANDED_HEIGHT = 36
    DEFAULT_COLLAPSED_HEIGHT = 10

    def __init__(self, parent=None):
        QtWidgets.QFrame.__init__(self, parent)

        self._dpi = 1
        self._expanded = True
        self._expandedHeight = self.DEFAULT_EXPANDED_HEIGHT
        self._collapsedHeight = self.DEFAULT_COLLAPSED_HEIGHT

        layout = QtWidgets.QHBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(self.SPACING)

        self.setLayout(layout)

        self._leftToolBar = QtWidgets.QToolBar(self)
        self._rightToolBar = QtWidgets.QToolBar(self)

        self._leftToolBar.layout().setSpacing(self.SPACING)
        self._rightToolBar.layout().setSpacing(self.SPACING)

        self.layout().addWidget(self._leftToolBar)
        self.layout().addWidget(self._rightToolBar)

    def addAction(self,
                  name,
                  icon=None,
                  tip=None,
                  callback=None,
                  side="Right"):
        """
        Add a button/action to menu bar widget.

        :type name: str
        :type icon: QtWidget.QIcon
        :param tip: str
        :param side: str
        :param callback: func
        :rtype: QtWidget.QAction
        """

        # The method below is needed to fix an issue with PySide2.
        def _callback():
            callback()

        if side == "Left":
            action = self.addLeftAction(name)
        else:
            action = self.addRightAction(name)

        if icon:
            action.setIcon(icon)

        if tip:
            action.setToolTip(tip)
            action.setStatusTip(tip)

        if callback:
            action.triggered.connect(_callback)

        return action

    def dpi(self):
        return self._dpi

    def setDpi(self, dpi):
        self._dpi = dpi
        self.update()

    def update(self):
        self.refreshSize()
        self.updateIconColor()

    def refreshSize(self):
        self.setChildrenHeight(self.height())

        if self.isExpanded():
            self.expand()
        else:
            self.collapse()

    def updateIconColor(self):
        color = self.palette().color(self.foregroundRole())
        color = studioqt.Color.fromColor(color)
        self.setIconColor(color)

    def addLeftAction(self, text):
        action = QtWidgets.QAction(text, self._leftToolBar)
        self._leftToolBar.addAction(action)
        return action

    def addRightAction(self, text):
        action = QtWidgets.QAction(text, self._rightToolBar)
        self._rightToolBar.addAction(action)
        return action

    def widgets(self):
        widgets = []

        for i in range(0, self.layout().count()):
            w = self.layout().itemAt(i).widget()
            if isinstance(w, QtWidgets.QWidget):
                widgets.append(w)

        return widgets

    def findAction(self, text):

        action1 = self._findAction(self._leftToolBar, text)
        action2 = self._findAction(self._rightToolBar, text)

        return action1 or action2

    def _findAction(self, toolBar, text):

        for child in toolBar.children():
            if isinstance(child, QtWidgets.QAction):
                if child.text() == text:
                    return child

    def findToolButton(self, text):

        button1 = self._findToolButton(self._leftToolBar, text)
        button2 = self._findToolButton(self._rightToolBar, text)

        button = button1 or button2

        return button

    def _findToolButton(self, toolBar, text):

        for child in toolBar.children():
            if isinstance(child, QtWidgets.QAction):
                if child.text() == text:
                    return toolBar.widgetForAction(child)

    def actions(self):
        actions = []

        children = self._leftToolBar.children()
        children.extend(self._rightToolBar.children())

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

        return actions

    def isExpanded(self):
        return self._expanded

    def setExpandedHeight(self, height):
        self._expandedHeight = height
        self.setChildrenHeight(height)

    def expandedHeight(self):
        return int(self._expandedHeight * self.dpi())

    def expand(self):
        self._expanded = True
        height = self.expandedHeight()
        self.setFixedHeight(height)
        self.setChildrenHeight(height)
        self.updateIconColor()

    def collapse(self):
        self._expanded = False
        height = self.collapsedHeight()
        self.setFixedHeight(height)
        self.setChildrenHeight(0)
        self.updateIconColor()

    def collapsedHeight(self):
        return int(self._collapsedHeight * self.dpi())

    def setIconColor(self, color):
        for action in self.actions():
            icon = action.icon()
            icon = studioqt.Icon(icon)
            icon.setColor(color)
            action.setIcon(icon)

    def setChildrenHidden(self, value):
        for w in self.widgets():
            w.setHidden(value)

    def setChildrenHeight(self, height):

        for w in self.widgets():
            w.setFixedHeight(height)

        padding = self.SPACING * self.dpi()

        width = height + (padding * 2)
        height = height - padding

        self._leftToolBar.setFixedHeight(height)
        self._leftToolBar.setIconSize(QtCore.QSize(width, height))

        self._rightToolBar.setFixedHeight(height)
        self._rightToolBar.setIconSize(QtCore.QSize(width, height))

    def resizeEvent(self, *args, **kwargs):
        self.refreshSize()

    def mousePressEvent(self, *args, **kwargs):
        self.expand()
示例#25
0
class ImageSequenceWidget(QtWidgets.QToolButton):
    DEFAULT_PLAYHEAD_COLOR = QtGui.QColor(255, 255, 255, 220)

    def __init__(self, *args):
        QtWidgets.QToolButton.__init__(self, *args)
        self.setStyleSheet('border: 0px solid rgb(0, 0, 0, 20);')
        self._filename = None
        self._imageSequence = ImageSequence(self)
        self._imageSequence.frameChanged.connect(self._frameChanged)
        self.setSize(150, 150)
        self.setMouseTracking(True)

    def isControlModifier(self):
        """
        :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 currentIcon(self):
        """
        Return a icon object from the current icon path.
        
        :rtype: QtGui.QIcon
        """
        return QtGui.QIcon(self._imageSequence.currentFilename())

    def setDirname(self, dirname):
        """
        Set the location to the image sequence.
        
        :type dirname: str
        :rtype: None
        """
        self._imageSequence.setDirname(dirname)
        if self._imageSequence.frames():
            icon = self.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()

    def leaveEvent(self, event):
        """
        Stop playing the image sequence when the mouse leaves the widget.
        
        :type event: QtCore.QEvent
        :rtype: None
        """
        self._imageSequence.pause()

    def mouseMoveEvent(self, event):
        """
        Reimplemented to add support for scrubbing.
        
        :type event: QtCore.QEvent
        :rtype: None
        """
        if self.isControlModifier():
            percent = 1.0 - float(self.width() - event.pos().x()) / float(
                self.width())
            frame = int(self._imageSequence.duration() * percent)
            self._imageSequence.setCurrentFrame(frame)
            icon = self.currentIcon()
            self.setIcon(icon)

    def _frameChanged(self, filename=None):
        """
        Triggered when the image sequence changes frame.
        
        :type filename: str or None
        :rtype: None
        """
        if not self.isControlModifier():
            self._filename = filename
            icon = self.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():
            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()
示例#26
0
 def setIconColor():
     menuBarWidget.setIconColor(QtGui.QColor(255, 255, 0))
示例#27
0
class ToastWidget(QtWidgets.QLabel):

    DEFAULT_DURATION = 500  # 0.5 seconds

    FOREGROUND_COLOR = QtGui.QColor(255, 255, 255)
    BACKGROUND_COLOR = QtGui.QColor(0, 0, 0)


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

        self.setMouseTracking(True)
        self.setAlignment(QtCore.Qt.AlignCenter)
        self.setAttribute(QtCore.Qt.WA_TransparentForMouseEvents)

        self._alpha = 255

        self._messageDisplayTimer = QtCore.QTimer(self)
        self._messageDisplayTimer.timeout.connect(self.fadeOut)

        self._messageFadeOutTimer = QtCore.QTimer(self)
        self._messageFadeOutTimer.timeout.connect(self._fadeOut)

    def alignTo(self, widget, padding=30):

        width = self.textWidth() + padding
        height = self.textHeight() + padding

        x = widget.width() / 2 - width / 2
        y = (widget.height() - height) / 1.2

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

    def textRect(self):
        text = self.text()
        font = self.font()
        metrics = QtGui.QFontMetricsF(font)
        return metrics.boundingRect(text)

    def textWidth(self):
        textWidth = self.textRect().width()
        return max(0, textWidth)

    def textHeight(self):
        textHeight = self.textRect().height()
        return max(0, textHeight)

    def fadeOut(self):
        """
        :rtype: None
        """
        self._messageFadeOutTimer.start(5)

    def _fadeOut(self):
        """
        :rtype: None
        """
        alpha = self.alpha()

        if alpha > 0:
            alpha -= 2
            self.setAlpha(alpha)
        else:
            self.hide()
            self._messageFadeOutTimer.stop()
            self._messageDisplayTimer.stop()

    def setText(self, text, duration=None):
        """
        :type text: str
        :rtype: None
        """
        QtWidgets.QLabel.setText(self, text)
        duration = duration or self.DEFAULT_DURATION

        self.setAlpha(255)
        self._messageDisplayTimer.stop()
        self._messageDisplayTimer.start(duration)

        self.show()
        self.update()
        self.repaint()

    def alpha(self):
        """
        :rtype: float
        """
        return float(self._alpha)

    def setAlpha(self, value):
        """
        :type value: float
        :rtype: None
        """
        if value < 0:
            value = 0

        textAlpha = value
        backgroundAlpha = value / 1.4

        color = ToastWidget.FOREGROUND_COLOR
        backgroundColor = ToastWidget.BACKGROUND_COLOR

        # color = self.palette().color(self.foregroundRole())
        color = studioqt.Color.fromColor(color)
        color.setAlpha(textAlpha)

        # backgroundColor = self.palette().color(self.backgroundRole())
        backgroundColor = studioqt.Color.fromColor(backgroundColor)
        backgroundColor.setAlpha(backgroundAlpha)

        styleSheet = "color: {0}; background-color: {1};"
        styleSheet = styleSheet.format(color.toString(), backgroundColor.toString())
        self.setStyleSheet(styleSheet)

        self._alpha = value
示例#28
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
示例#29
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()
示例#30
0
class SettingsDialog(QtWidgets.QDialog):

    DEFAULT_ACCENT_COLOR = QtGui.QColor(20, 175, 250)
    DEFAULT_BACKGROUND_COLOR = QtGui.QColor(70, 70, 80)

    DEFAULT_ACCENT_COLORS = [
        QtGui.QColor(230, 75, 75),
        QtGui.QColor(235, 100, 70),
        QtGui.QColor(240, 125, 100),
        QtGui.QColor(240, 190, 40),
        QtGui.QColor(80, 200, 140),
        QtGui.QColor(20, 175, 250),
        QtGui.QColor(110, 110, 240),
    ]

    DEFAULT_BACKGROUND_COLORS = [
        QtGui.QColor(70, 70, 80),
        QtGui.QColor(65, 65, 75),
        QtGui.QColor(55, 55, 65),
        QtGui.QColor(50, 50, 57),
        QtGui.QColor(40, 40, 47),
    ]

    accentColorChanged = QtCore.Signal(object)
    backgroundColorChanged = QtCore.Signal(object)

    def __init__(self, parent=None):
        """
        :type parent: QtWidgets.QWidget
        :type library: studiolibrary.Library
        """
        QtWidgets.QDialog.__init__(self, parent)
        studioqt.loadUi(self)

        self._validator = None
        self._accentColor = self.DEFAULT_ACCENT_COLOR
        self._backgroundColor = self.DEFAULT_BACKGROUND_COLOR

        resource = studiolibrary.resource()
        self.setWindowIcon(resource.icon("icon_black"))

        windowTitle = "Studio Library - {version}"
        windowTitle = windowTitle.format(version=studiolibrary.version())
        self.setWindowTitle(windowTitle)

        self.createAccentColorBar()
        self.createBackgroundColorBar()

        self.ui.acceptButton.clicked.connect(self.accept)
        self.ui.rejectButton.clicked.connect(self.close)
        self.ui.browsePathButton.clicked.connect(self.browsePath)

        self.updateStyleSheet()
        self.center()

    def resizeEvent(self, event):
        """
        Reimplemented to support the logo scaling on DPI screens.

        :type event: QtGui.QEvent
        :rtype: None
        """
        scaleFactor = 1.4
        height = self.ui.headerFrame.height()
        self.ui.logo.setFixedWidth(height / scaleFactor)
        self.ui.logo.setFixedHeight(height / scaleFactor)

    def _accentColorChanged(self, color):
        """
        Triggered when the user clicks/changes the accent color.

        :type color: studioqt.Color
        :rtype: None
        """
        self.setAccentColor(color)

    def _backgroundColorClicked(self, color):
        """
        Triggered when the user clicks/changes the background color.

        :type color: studioqt.Color
        :rtype: None
        """
        self.setBackgroundColor(color)

    def createAccentColorBar(self):
        """
        Create and setup the accent color bar.

        :rtype: None
        """
        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),
        ]

        browserColors = []
        for colorR, colorG, colorB in browserColors_:
            for i in range(0, 3):

                colorR = colorR if colorR > 0 else 0
                colorG = colorG if colorG > 0 else 0
                colorB = colorB if colorB > 0 else 0

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

                colorR -= 20
                colorB -= 20
                colorG -= 20

        hColorBar = studioqt.HColorBar()
        hColorBar.setColors(self.DEFAULT_ACCENT_COLORS)
        hColorBar.setCurrentColor(self.DEFAULT_ACCENT_COLOR)
        hColorBar.setBrowserColors(browserColors)
        hColorBar.colorChanged.connect(self._accentColorChanged)

        self.ui.accentColorBarFrame.layout().addWidget(hColorBar)

    def createBackgroundColorBar(self):
        """
        Create and setup the background color bar.

        :rtype: None
        """
        browserColors_ = [
            (0, 0, 0),
            (20, 20, 30),
            (0, 30, 60),
            (0, 60, 60),
            (0, 60, 30),
            (60, 0, 10),
            (60, 0, 40),
            (40, 15, 5),
        ]

        browserColors = []
        for colorR, colorG, colorB in browserColors_:
            for i in range(0, 6):

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

                colorR += 20
                colorB += 20
                colorG += 20

        hColorBar = studioqt.HColorBar()
        hColorBar.setColors(self.DEFAULT_BACKGROUND_COLORS)
        hColorBar.setCurrentColor(self.DEFAULT_BACKGROUND_COLOR)
        hColorBar.setBrowserColors(browserColors)
        hColorBar.colorChanged.connect(self._backgroundColorClicked)

        self.ui.backgroundColorBarFrame.layout().addWidget(hColorBar)

    def accept(self):
        """
        Hides the modal dialog and sets the result code to Accepted.

        :rtype: None
        """
        self.validate()
        QtWidgets.QDialog.accept(self)

    def setValidator(self, validator):
        """
        Set the validator for the dialog.

        :type validator: func
        :rtype: None
        """
        self._validator = validator

    def validator(self):
        """
        Return the validator for the dialog.

        :rtype: func
        """
        return self._validator

    def validate(self):
        """
        Run the validate.

        :rtype: None
        """
        try:
            validator = self.validator()
            if validator:
                validator()
        except Exception, e:
            QtWidgets.QMessageBox.critical(self, "Validate Error", str(e))
            raise