<gh_stars>0
# subclass
"""This module contains classes and functions that add added custom made widgets and
functionalities to the qt GUI. It contains the following components:
"""

# Set all
__all__ = ["MultiSelectMenu"]

# Import needed modules
from PyQt5 import QtCore, QtWidgets


###################################################################
# CheckableComboBox Class #########################################
###################################################################
class MultiSelectMenu(QtWidgets.QToolButton):
    """This class is used to create a multi selection drop down menu.
    """
    #################################################
    # Class initializer #############################
    #################################################
    def __init__(self, all_text_enabled=True, all_text="Select all"):
        """Initialize object."""
        # Get extra options
        self.all_text_enabled = all_text_enabled
        self.all_text = all_text

        # Run parent initializer and setup components
        super(MultiSelectMenu, self).__init__()
        self.setText("Select Categories ")
        self.toolmenu = QtWidgets.QMenu(self)
        self.setMenu(self.toolmenu)
        self.setPopupMode(QtWidgets.QToolButton.InstantPopup)
        self.toolmenu.installEventFilter(self)

        # Add all text to menu if enabled
        if all_text_enabled:
            action = QtWidgets.QAction(self)
            action.setText(all_text)
            action.setCheckable(True)
            action.changed.connect(self.selectAll)
            self.toolmenu.addAction(action)
            self.all_text_enabled = True

    #################################################
    # addItem method ################################
    #################################################
    def addItem(self, item):
        """Method used to add additional actions to the toolbar menu."""
        # Add item to menu
        action = QtWidgets.QAction(self)
        action.setText(item)
        action.setCheckable(True)
        self.toolmenu.addAction(action)

        # Connect to selection function when All option exists
        if self.all_text_enabled:
            action.changed.connect(self.selectAction)

    #################################################
    # addAllOption method ###########################
    #################################################
    def addAllOption(self, all_text="Select all"):
        """This function is used to add a "Select all" action to the toolbar menu.

        Args:
            all_text (str, optional): Defaults to "Select all". The text used for the
            select all element.
        """
        # Check whether all text was already enabled
        if not self.all_text_enabled:
            # Set all_text if specified
            self.all_text = all_text

            # Add all action to menu
            action = QtWidgets.QAction(self)
            action.setText(all_text)
            action.setCheckable(True)
            action.changed.connect(self.selectAll)
            self.toolmenu.insertAction(self.toolmenu.actions()[0], action)
            self.all_text_enabled = True
        else:
            print("All text already enabled use changeAllText to change the all text.")

    #################################################
    # ChangeAllText method  #########################
    #################################################
    def changeAllText(self, all_text):
        """This function is used to change the "Select all" text.

        Args:
            all_text (str): The text used for the select all element.
        """
        # Check whether all text was already enabled
        if not self.all_text_enabled:
            print(
                "No all text was enabled please first use the addAllOption method to "
                "enable the select all option."
            )
        else:
            self.all_text = all_text
            self.toolmenu.actions()[0].setText(all_text)

    #################################################
    # removeAllOption method ########################
    #################################################
    def removeAllOption(self):
        """This function is used to remove a "Select all" action to the toolbar menu.
        """
        # Remove select all element if it exists
        if self.all_text_enabled:
            self.all_text_enabled = False  # Set select all text to false
            self.toolmenu.removeAction(self.toolmenu.actions()[0])
        else:
            print("No select all action was found.")

    #################################################
    # selectAll method ##############################
    #################################################
    def selectAll(self):
        """This method is used to select all the options when the select all action
        is selected.
        """
        # Check or unchecked the other actions based on the "Select all" action
        if self.toolmenu.actions()[0].isChecked():  # If "Select all" action is checked
            for action in self.toolmenu.actions()[1:]:
                action.changed.disconnect(self.selectAction)
                action.setChecked(1)  # Check actions
                action.changed.connect(self.selectAction)
        else:
            for action in self.toolmenu.actions()[1:]:
                action.changed.disconnect(self.selectAction)
                action.setChecked(0)  # Uncheck all actions
                action.changed.connect(self.selectAction)

    #################################################
    # selectAction method ###########################
    #################################################
    def selectAction(self):
        """This method is used to unselect the select all option when one of the other
        values is unselected. Further it also makes sure that the select all button is
        selected again if all items are selected again.
        """
        # Check or unchecked the other actions based on the "Select all" action
        if self.toolmenu.actions()[0].isChecked() and len(self.selectedItems()) < len(
            self.toolmenu.actions()
        ):
            self.toolmenu.actions()[
                0
            ].changed.disconnect()  # Disconnect all select function
            self.toolmenu.actions()[0].setChecked(0)  # Disable all selected
            self.toolmenu.actions()[0].changed.connect(
                self.selectAll
            )  # Reconnect all select functino
        elif not self.toolmenu.actions()[0].isChecked() and len(
            self.selectedItems()
        ) == (len(self.toolmenu.actions()) - 1):
            self.toolmenu.actions()[0].setChecked(1)  # Enable all selected

    #################################################
    # selectedItems method ##########################
    #################################################
    def selectedItems(self):
        """This method returns a list containing the items that were selected in the
        toolbox menu.

        Returns:
            list: List containing the items that were selected.
        """
        # Create selected items list
        selected_items = []

        # Loop through the toolbar menu and return selected items
        if self.all_text_enabled:
            for action in self.toolmenu.actions()[1:]:
                if action.isChecked():  # Check if item is checked
                    selected_items.append(action.text())  # Append item text to list
        else:
            for action in self.toolmenu.actions():
                if action.isChecked():  # Check if item is checked
                    selected_items.append(action.text())  # Append item text to list

        # Return result
        return selected_items

    #################################################
    # Clear method  #################################
    #################################################
    def clear(self):
        """This function clears all the cations out of the Qmenu."""
        self.toolmenu.clear()

        # Add select all option back if it was enabled
        if self.all_text_enabled:
            action = QtWidgets.QAction(self)
            action.setText(self.all_text)
            action.setCheckable(True)
            action.changed.connect(self.selectAll)
            self.toolmenu.addAction(action)
            self.all_text_enabled = True

    #################################################
    # eventFilter method ############################
    #################################################
    def eventFilter(self, obj, event):
        """This function is used to slightly edit the open and close behaviour of the
        QToolButton. This was done since we want the toolbar drop down menu to stay open
        when the user is selecting players.

        Args:
            obj (QObject): The object on which the event filter needs to be applied.
            event (QEvent): The QEvent we want to overwrite.

        Returns:
            QEvent: Pass the event to the parent class.
        """
        # Check if the mouse button is released
        if event.type() in [QtCore.QEvent.MouseButtonRelease]:
            if isinstance(obj, QtWidgets.QMenu):
                if obj.activeAction():
                    if (
                        not obj.activeAction().menu()
                    ):  # if the selected action does not have a submenu
                        # eat the event, but trigger the function
                        obj.activeAction().trigger()
                        return True

        # Return event
        return super(MultiSelectMenu, self).eventFilter(obj, event)

# subclass
"""This module contains classes and functions that add added custom made widgets and
functionalities to the qt GUI. It contains the following components:
"""

# Set all
__all__ = ["MultiSelectMenu"]

# Import needed modules
from PyQt5 import QtCore, QtWidgets


###################################################################
# CheckableComboBox Class #########################################
###################################################################
class MultiSelectMenu(QtWidgets.QToolButton):
    """This class is used to create a multi selection drop down menu.
    """
    #################################################
    # Class initializer #############################
    #################################################
    def __init__(self, all_text_enabled=True, all_text="Select all"):
        """Initialize object."""
        # Get extra options
        self.all_text_enabled = all_text_enabled
        self.all_text = all_text

        # Run parent initializer and setup components
        super(MultiSelectMenu, self).__init__()
        self.setText("Select Categories ")
        self.toolmenu = QtWidgets.QMenu(self)
        self.setMenu(self.toolmenu)
        self.setPopupMode(QtWidgets.QToolButton.InstantPopup)
        self.toolmenu.installEventFilter(self)

        # Add all text to menu if enabled
        if all_text_enabled:
            action = QtWidgets.QAction(self)
            action.setText(all_text)
            action.setCheckable(True)
            action.changed.connect(self.selectAll)
            self.toolmenu.addAction(action)
            self.all_text_enabled = True

    #################################################
    # addItem method ################################
    #################################################
    def addItem(self, item):
        """Method used to add additional actions to the toolbar menu."""
        # Add item to menu
        action = QtWidgets.QAction(self)
        action.setText(item)
        action.setCheckable(True)
        self.toolmenu.addAction(action)

        # Connect to selection function when All option exists
        if self.all_text_enabled:
            action.changed.connect(self.selectAction)

    #################################################
    # addAllOption method ###########################
    #################################################
    def addAllOption(self, all_text="Select all"):
        """This function is used to add a "Select all" action to the toolbar menu.

        Args:
            all_text (str, optional): Defaults to "Select all". The text used for the
            select all element.
        """
        # Check whether all text was already enabled
        if not self.all_text_enabled:
            # Set all_text if specified
            self.all_text = all_text

            # Add all action to menu
            action = QtWidgets.QAction(self)
            action.setText(all_text)
            action.setCheckable(True)
            action.changed.connect(self.selectAll)
            self.toolmenu.insertAction(self.toolmenu.actions()[0], action)
            self.all_text_enabled = True
        else:
            print("All text already enabled use changeAllText to change the all text.")

    #################################################
    # ChangeAllText method  #########################
    #################################################
    def changeAllText(self, all_text):
        """This function is used to change the "Select all" text.

        Args:
            all_text (str): The text used for the select all element.
        """
        # Check whether all text was already enabled
        if not self.all_text_enabled:
            print(
                "No all text was enabled please first use the addAllOption method to "
                "enable the select all option."
            )
        else:
            self.all_text = all_text
            self.toolmenu.actions()[0].setText(all_text)

    #################################################
    # removeAllOption method ########################
    #################################################
    def removeAllOption(self):
        """This function is used to remove a "Select all" action to the toolbar menu.
        """
        # Remove select all element if it exists
        if self.all_text_enabled:
            self.all_text_enabled = False  # Set select all text to false
            self.toolmenu.removeAction(self.toolmenu.actions()[0])
        else:
            print("No select all action was found.")

    #################################################
    # selectAll method ##############################
    #################################################
    def selectAll(self):
        """This method is used to select all the options when the select all action
        is selected.
        """
        # Check or unchecked the other actions based on the "Select all" action
        if self.toolmenu.actions()[0].isChecked():  # If "Select all" action is checked
            for action in self.toolmenu.actions()[1:]:
                action.changed.disconnect(self.selectAction)
                action.setChecked(1)  # Check actions
                action.changed.connect(self.selectAction)
        else:
            for action in self.toolmenu.actions()[1:]:
                action.changed.disconnect(self.selectAction)
                action.setChecked(0)  # Uncheck all actions
                action.changed.connect(self.selectAction)

    #################################################
    # selectAction method ###########################
    #################################################
    def selectAction(self):
        """This method is used to unselect the select all option when one of the other
        values is unselected. Further it also makes sure that the select all button is
        selected again if all items are selected again.
        """
        # Check or unchecked the other actions based on the "Select all" action
        if self.toolmenu.actions()[0].isChecked() and len(self.selectedItems()) < len(
            self.toolmenu.actions()
        ):
            self.toolmenu.actions()[
                0
            ].changed.disconnect()  # Disconnect all select function
            self.toolmenu.actions()[0].setChecked(0)  # Disable all selected
            self.toolmenu.actions()[0].changed.connect(
                self.selectAll
            )  # Reconnect all select functino
        elif not self.toolmenu.actions()[0].isChecked() and len(
            self.selectedItems()
        ) == (len(self.toolmenu.actions()) - 1):
            self.toolmenu.actions()[0].setChecked(1)  # Enable all selected

    #################################################
    # selectedItems method ##########################
    #################################################
    def selectedItems(self):
        """This method returns a list containing the items that were selected in the
        toolbox menu.

        Returns:
            list: List containing the items that were selected.
        """
        # Create selected items list
        selected_items = []

        # Loop through the toolbar menu and return selected items
        if self.all_text_enabled:
            for action in self.toolmenu.actions()[1:]:
                if action.isChecked():  # Check if item is checked
                    selected_items.append(action.text())  # Append item text to list
        else:
            for action in self.toolmenu.actions():
                if action.isChecked():  # Check if item is checked
                    selected_items.append(action.text())  # Append item text to list

        # Return result
        return selected_items

    #################################################
    # Clear method  #################################
    #################################################
    def clear(self):
        """This function clears all the cations out of the Qmenu."""
        self.toolmenu.clear()

        # Add select all option back if it was enabled
        if self.all_text_enabled:
            action = QtWidgets.QAction(self)
            action.setText(self.all_text)
            action.setCheckable(True)
            action.changed.connect(self.selectAll)
            self.toolmenu.addAction(action)
            self.all_text_enabled = True

    #################################################
    # eventFilter method ############################
    #################################################
    def eventFilter(self, obj, event):
        """This function is used to slightly edit the open and close behaviour of the
        QToolButton. This was done since we want the toolbar drop down menu to stay open
        when the user is selecting players.

        Args:
            obj (QObject): The object on which the event filter needs to be applied.
            event (QEvent): The QEvent we want to overwrite.

        Returns:
            QEvent: Pass the event to the parent class.
        """
        # Check if the mouse button is released
        if event.type() in [QtCore.QEvent.MouseButtonRelease]:
            if isinstance(obj, QtWidgets.QMenu):
                if obj.activeAction():
                    if (
                        not obj.activeAction().menu()
                    ):  # if the selected action does not have a submenu
                        # eat the event, but trigger the function
                        obj.activeAction().trigger()
                        return True

        # Return event
        return super(MultiSelectMenu, self).eventFilter(obj, event)
# subclass This module contains classes and functions that add added custom made widgets and functionalities to the qt GUI. It contains the following components: # Set all # Import needed modules ################################################################### # CheckableComboBox Class ######################################### ################################################################### This class is used to create a multi selection drop down menu. ################################################# # Class initializer ############################# ################################################# Initialize object. # Get extra options # Run parent initializer and setup components # Add all text to menu if enabled ################################################# # addItem method ################################ ################################################# Method used to add additional actions to the toolbar menu. # Add item to menu # Connect to selection function when All option exists ################################################# # addAllOption method ########################### ################################################# This function is used to add a "Select all" action to the toolbar menu.          Args:             all_text (str, optional): Defaults to "Select all". The text used for the             select all element. # Check whether all text was already enabled # Set all_text if specified # Add all action to menu ################################################# # ChangeAllText method  ######################### ################################################# This function is used to change the "Select all" text.          Args:             all_text (str): The text used for the select all element. # Check whether all text was already enabled ################################################# # removeAllOption method ######################## ################################################# This function is used to remove a "Select all" action to the toolbar menu. # Remove select all element if it exists # Set select all text to false ################################################# # selectAll method ############################## ################################################# This method is used to select all the options when the select all action         is selected. # Check or unchecked the other actions based on the "Select all" action # If "Select all" action is checked # Check actions # Uncheck all actions ################################################# # selectAction method ########################### ################################################# This method is used to unselect the select all option when one of the other         values is unselected. Further it also makes sure that the select all button is         selected again if all items are selected again. # Check or unchecked the other actions based on the "Select all" action # Disconnect all select function # Disable all selected # Reconnect all select functino # Enable all selected ################################################# # selectedItems method ########################## ################################################# This method returns a list containing the items that were selected in the         toolbox menu.          Returns:             list: List containing the items that were selected. # Create selected items list # Loop through the toolbar menu and return selected items # Check if item is checked # Append item text to list # Check if item is checked # Append item text to list # Return result ################################################# # Clear method  ################################# ################################################# This function clears all the cations out of the Qmenu. # Add select all option back if it was enabled ################################################# # eventFilter method ############################ ################################################# This function is used to slightly edit the open and close behaviour of the         QToolButton. This was done since we want the toolbar drop down menu to stay open         when the user is selecting players.          Args:             obj (QObject): The object on which the event filter needs to be applied.             event (QEvent): The QEvent we want to overwrite.          Returns:             QEvent: Pass the event to the parent class. # Check if the mouse button is released # if the selected action does not have a submenu # eat the event, but trigger the function # Return event