Source code for filtering.filter_menu_button
# Copyright (c) 2021 Autodesk Inc.
#
# CONFIDENTIAL AND PROPRIETARY
#
# This work is provided "AS IS" and subject to the ShotGrid Pipeline Toolkit
# Source Code License included in this distribution package. See LICENSE.
# By accessing, using, copying or modifying this work you indicate your
# agreement to the ShotGrid Pipeline Toolkit Source Code License. All rights
# not expressly granted therein are reserved by Autodesk Inc.
import sgtk
from sgtk.platform.qt import QtCore, QtGui
from .filter_menu import FilterMenu
sg_qicons = sgtk.platform.current_bundle().import_module("sg_qicons")
SGQIcon = sg_qicons.SGQIcon
sg_qwidgets = sgtk.platform.current_bundle().import_module("sg_qwidgets")
SGQToolButton = sg_qwidgets.SGQToolButton
[docs]class FilterMenuButton(SGQToolButton):
"""
A QToolButton to be used with the FilterMenu class.
"""
def __init__(self, parent=None, text=None, icon=None):
"""
Constructor.
:param parent: The parent widget.
:type parent: :class:`sgtk.platform.qt.QtGui.QWidget`
:param text: The text displayed on the button.
:type text: str
:param icon: The button icon.
:type icon: :class:`sgtk.platform.qt.QtGui.QIcon`
"""
super(FilterMenuButton, self).__init__(parent)
self.__icon = icon if icon else SGQIcon.filter()
self.__checked = False
# Set up the animated refresh icon to display while the filter menu for this filter
# button is loading. Ensure the animation loops forever.
refresh_icon_path = SGQIcon.resource_path(
"spinning-wheel", SGQIcon.SIZE_16x16, "gif"
)
self.__refresh_movie_icon = QtGui.QMovie(refresh_icon_path)
if self.__refresh_movie_icon.loopCount() != -1:
self.__refresh_movie_icon.finished.connect(self.__refresh_movie_icon.start)
self.setCheckable(True)
self.setPopupMode(QtGui.QToolButton.InstantPopup)
self.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon)
self.setIcon(self.__icon)
self.setText(text or "Filter")
[docs] def setMenu(self, menu):
"""
Override the base QToolButton method.
Enforce the menu to be of type `FilterMenu`. Connect the menu's filters changed
signal to update the menu button accordingly.
"""
assert isinstance(
menu, FilterMenu
), "FilterMenuButton menu must be of type '{}'".format(
FilterMenu.__class__.__name__
)
if self.menu():
self.menu().menu_about_to_be_refreshed.disconnect(
lambda: self.set_enabled(False)
)
self.menu().menu_refreshed.disconnect(lambda: self.set_enabled(True))
self.menu().filters_changed.disconnect(self.update_button_checked)
super(FilterMenuButton, self).setMenu(menu)
self.update_button_checked()
self.menu().filters_changed.connect(self.update_button_checked)
self.menu().menu_about_to_be_refreshed.connect(lambda: self.set_enabled(False))
self.menu().menu_refreshed.connect(lambda: self.set_enabled(True))
[docs] def setEnabled(self, enabled):
"""Override the base QToolButton method to ensure the check state is restored."""
super(FilterMenuButton, self).setEnabled(enabled)
if not enabled:
# Uncheck the button while disabled so stylistically it looks disabled.
self.setChecked(False)
else:
# Restore the check state on enabling it again.
self.setChecked(self.__checked)
[docs] def update_button_checked(self):
"""
Callback triggered when the menu filters have changed. Update the button's checked state
based on the menu's current filtering.
"""
self.__checked = self.menu().has_filtering
if self.isEnabled():
# Update the menu button icon to indicate whether or not the menu has any active
# filtering. Do not update the check state while not enabled, since this may
# override the disabled icon. Restore the check state once button is enabled.
self.setChecked(self.__checked)
[docs] def set_enabled(self, enabled):
"""
Update the button enabled state.
:param enabled: True will turn on the button (enable), else False will turn off (disable).
:type enabled: bool
"""
self.setEnabled(enabled)
if not enabled:
# Show the animated refresh icon. Connect the animation signal/slot.
self.__refresh_movie_icon.frameChanged.connect(self._update_refresh_icon)
self.__refresh_movie_icon.start()
else:
# Show the main button icon and stop the refresh animation
self.setIcon(self.__icon)
self.__refresh_movie_icon.stop()
# Disconnect the animation signal/slot
try:
self.__refresh_movie_icon.frameChanged.disconnect(
self._update_refresh_icon
)
except:
# Signal was not connected, continue on.
pass
def _update_refresh_icon(self, frame):
"""Update the animated refresh icon."""
self.setIcon(QtGui.QIcon(self.__refresh_movie_icon.currentPixmap()))