Example #1
0
class QTPie:
    """
    Manages the UI based on the users monitor and position in the application
    """
    def __init__(self,
                 icon=None,
                 tunableDict=json.loads(
                     json.dumps({
                         "windowX": 20,
                         "windowY": 50,
                         "windowWidth": 500,
                         "windowHeight": 500,
                         "volume": 50
                     })),
                 title="Window"):
        """
        Initializing the UI for Forge

        Args:\n
            icon (string, optional): File path to the icon(.ico file) for the top left of the window. Defaults to None.
            tunableDict (JSON, optional): The tunable variables class for saving the windows position on close.
                                          Defaults to {"windowX": 10, "windowY": 10, "windowWidth": 500, "windowHeight": 500}.
            title (str, optional): The name of the window. Defaults to "Window".
        """

        stylesheet = open(utilities.resource_path("QTPie Style\\style.css"),
                          "r")
        styling = stylesheet.read()
        stylesheet.close()

        self.actions = Actions()

        self.tunableDict = tunableDict

        self.app = QtWidgets.QApplication(sys.argv)
        self.app.setStyleSheet(styling)
        self.app.aboutToQuit.connect(
            lambda: self.actions.onWindowClose(self.mainWindow))

        if icon:
            appIcon = PyQt5.QtGui.QIcon()
            appIcon.addFile(utilities.resource_path("icon.png"))
            self.app.setWindowIcon(appIcon)

        self.grid = QtWidgets.QGridLayout()
        self.gridCount = 0
        self.grid.setSpacing(0)
        self.grid.setContentsMargins(0, 0, 0, 0)
        self.space = self.addLabel([1, 1, 1, 1], txt="", name="Spacer")

        self.window = QTPieWidget()
        self.window.setLayout(self.grid)

        self.mainWindow = QTPieWindow()
        self.mainWindow.setGeometry(self.tunableDict["windowX"],
                                    self.tunableDict["windowY"],
                                    self.tunableDict["windowWidth"],
                                    self.tunableDict["windowHeight"])
        self.mainWindow.setWindowTitle(title)
        self.mainWindow.setCentralWidget(self.window)

    def percentToPosition(self, xPos, yPos, width, height):
        """
        Converts percent values to pixel values and returns pixel values for QTPie to use

        Args:\n
            xPos (int, str, float): The x coordinate of the window on the users screen
            yPos (int, str, float):  The y coordinate of the window on the users screen
            width (int, str, float: The width of the window
            height (int, str, float): The height of the window

        Returns:\n
            tuple of int: The arg converted to an int pixel value
        """

        if type(xPos) == str:
            if xPos.find("%") != -1:
                xPos = self.window.size().width() * (
                    int(xPos.replace("%", "")) / 100)
        if type(yPos) == str:
            if yPos.find("%") != -1:
                yPos = self.window.size().height() * (
                    int(yPos.replace("%", "")) / 100)
        if type(width) == str:
            if width.find("%") != -1:
                width = self.window.size().width() * (
                    int(width.replace("%", "")) / 100)
        if type(height) == str:
            if height.find("%") != -1:
                height = self.window.size().height() * (
                    int(height.replace("%", "")) / 100)

        return int(xPos), int(yPos), int(width), int(height)

    def alignWidget(self, widget, alignment):
        """
        Given an alignment direction the widget is aligned to that direction

        Args:\n
            widget (PyQt5.QtWidgets.QWidget): A PyQt5 widget to be aligned
            alignment (str): A left, right or center string
        """

        alignments = {
            "left": QtCore.Qt.AlignLeft,
            "center": QtCore.Qt.AlignCenter,
            "right": QtCore.Qt.AlignRight
        }
        widget.setAlignment(alignments[alignment])

    def addGridRow(self, grid, count):
        for _ in range(12):
            grid.addWidget(self.space, count, _)
            grid.setColumnStretch(_, 1)
        grid.setRowStretch(count, 1)
        #count += 1

    def addLabel(self,
                 gridData,
                 name="",
                 txt="Button",
                 enableDrop=False,
                 align="center"):
        """
        Combines the basic Label code into one function with added functionality and support for css syntax

        Args:\n
            gridData (list of int): List of column, row, columnspan, rowspan values
            name (str, optional): The name for the QTPie stylesheet to specify style. Defaults to "".
            txt (str, optional): The text to be displayed. Defaults to "Button".
            enableDrop (bool, optional): Determines whether drag and drop is enabled. Defaults to False.

        Returns:\n
            QTPieLabel: A PyQt5 label
        """

        label = QTPieLabel(dropArea=enableDrop)
        label.setObjectName(name)
        label.setText(txt)
        label.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                            QtWidgets.QSizePolicy.Expanding)
        self.alignWidget(label, align)
        self.grid.addWidget(label, gridData[1], gridData[0], gridData[3],
                            gridData[2])

        return label

    def addButton(self,
                  gridData,
                  action,
                  name="",
                  txt="Button",
                  enableDrop=False):
        """
        Combines the basic Button code into one function with added functionality and support for css syntax

        Args:\n
            gridData (list of int): List of column, row, columnspan, rowspan values
            action (def): The function to be called on click
            name (str, optional): The name for the QTPie stylesheet to specify style. Defaults to "".
            txt (str, optional): The text the be displayed. Defaults to "Button".
            enableDrop (bool, optional): Determines whether drag and drop is enabled. Defaults to False.

        Returns:\n
            QTPieButton: A PyQt5 push button
        """

        btn = QTPieButton(dropArea=enableDrop)
        btn.setObjectName(name)
        btn.setText(txt)
        btn.clicked.connect(action)
        btn.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                          QtWidgets.QSizePolicy.Expanding)
        self.grid.addWidget(btn, gridData[1], gridData[0], gridData[3],
                            gridData[2])

        return btn

    def addImage(self,
                 gridData,
                 name="",
                 filename="smile.jpg",
                 keepAR=True,
                 enableDrop=False,
                 align="center"):
        """
        Combines the basic Image code into one function with added functionality and support for CSS syntax

        Args:\n
            gridData (list of int): List of column, row, columnspan, rowspan values
            name (str, optional): The name for the QTPie stylesheet to specify style. Defaults to "".
            filename (str, optional): The filepath for the pixmap image. Defaults to "icon.png".
            keepAR (bool, optional): Whether to keep the original pictures aspect ratio or fit to given width and height. Defaults to True.
            enableDrop (bool, optional): Determines whether drag and drop is enabled. Defaults to False.

        Returns:\n
            QTPieLabel: A PyQt scroll area with a PyQt5 label with a PyQt5 pixmap inside
        """

        name += "Image"

        image = QTPieLabel(dropArea=enableDrop,
                           isImage=True,
                           filename=filename)
        image.pixelMap = QTPiePixmap()
        image.pixelMap = image.pixelMap.fromImage(PyQt5.QtGui.QImage(filename))

        image.setObjectName(name)
        image.setPixmap(image.pixelMap)
        image.setSizePolicy(PyQt5.QtWidgets.QSizePolicy.Ignored,
                            PyQt5.QtWidgets.QSizePolicy.Ignored)
        self.alignWidget(image, align)

        self.grid.addWidget(image, gridData[1], gridData[0], gridData[3],
                            gridData[2])

        return image

    def makePlayPause(self, media):
        """
        Create a play pause button for a given media to be put on a given parent

        Args:\n
            media (QTPieMedia): The holder of a type of media
            parent (QTPieScrollArea or QTPieWidget): The widget for the button to be placed on

        Returns:\n
            QTPieButton: An extension of the PyQt5 QPushButton
        """

        playPause = QTPieButton()
        playPause.setObjectName("VideoPlayPause")
        playPause.setIcon(self.app.style().standardIcon(
            PyQt5.QtWidgets.QStyle.SP_MediaPause))
        playPause.clicked.connect(
            lambda: self.actions.playPause(media, playPause, self.app))
        playPause.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                QtWidgets.QSizePolicy.Expanding)

        return playPause

    def makeVolume(self, media):
        """
        Create a volume slider for a given media to be put on a given parent

        Args:\n
            media (QTPieMedia): The holder of a type of media
            parent (QTPieScrollArea or QTPieWidget): The widget for the button to be placed on

        Returns:\n
            QTPieSlider: An extension of the PyQt5 QSlider
        """

        volume = QTPieSlider()
        volume.setObjectName("VideoVolume")
        volume.setOrientation(QtCore.Qt.Horizontal)
        volume.setMinimum(0)
        volume.setMaximum(100)
        volume.valueChanged.connect(
            lambda: self.actions.changeVolume(media, volume))
        volume.setValue(media.volume())
        volume.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                             QtWidgets.QSizePolicy.Expanding)

        return volume

    def addVideo(self,
                 gridData,
                 name="",
                 filename=r"ChrisH.mp4",
                 enableDrop=False):
        """
        Combines the basic Video code into one function with added functionality and support for CSS syntax

        Args:\n
            gridData (list of int): List of column, row, columnspan, rowspan values
            name (str, optional): The name for the QTPie stylesheet to specify style. Defaults to "".
            filename (str, optional): The filepath for the media player video.
        
        Returns:\n
            QTPieVideo: A PyQt5 media player
        """

        #Making video output
        video = QTPieVideo()
        video.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                            QtWidgets.QSizePolicy.Expanding)

        #Making media controller
        media = QTPieMedia()
        media.setMedia(
            PyQt5.QtMultimedia.QMediaContent(
                PyQt5.QtCore.QUrl.fromLocalFile(filename)))
        media.setVideoOutput(video)
        media.setVolume(self.tunableDict["volume"])
        media.setObjectName(name)

        playPause = self.makePlayPause(media)
        volume = self.makeVolume(media)

        mediaGrid = QtWidgets.QGridLayout()
        mediaGrid.setObjectName("VideoControls")
        mediaGrid.setContentsMargins(0, 0, 0, 0)

        mediaGridCount = 0
        for _ in range(9):
            self.addGridRow(mediaGrid, mediaGridCount)
            mediaGridCount += 1

        mediaGrid.addWidget(video, 0, 0, 9, 12)
        mediaGrid.addWidget(playPause, 8, 0, 1, 1)
        mediaGrid.addWidget(volume, 8, 9, 2, 3)

        mediaWidget = QTPieWidget()
        mediaWidget.setObjectName("VideoControls")
        mediaWidget.setLayout(mediaGrid)
        mediaWidget.clicked.connect(
            lambda: self.actions.playPause(media, playPause, self.app))

        self.grid.addWidget(mediaWidget, gridData[1], gridData[0], gridData[3],
                            gridData[2])

        media.play()

        return media

    def addProgressBar(self, gridData, name=""):
        """
        Combines the basic Progress Bar code into one function with added functionality and support for CSS syntax

        Args:\n
            gridData (list of int): List of column, row, columnspan, rowspan values
            name (str, optional): The name for the QTPie stylesheet to specify style. Defaults to "".

        Returns:\n
            QTPieProgressBar: A PyQt5 progress bar
        """

        progressBar = QTPieProgressBar()
        progressBar.setObjectName(name)
        progressBar.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                  QtWidgets.QSizePolicy.Expanding)
        self.grid.addWidget(progressBar, gridData[1], gridData[0], gridData[3],
                            gridData[2])

        return progressBar

    def addSlider(self,
                  gridData,
                  action,
                  name="",
                  orientation="horizontal",
                  minVal=0,
                  maxVal=100):
        """
        Combines the basic Slider code into one function with added functionality and support for CSS syntax

        Args:\n
            gridData (list of int): List of column, row, columnspan, rowspan values
            action (def): The function to be called when the slider is moved
            name (str, optional): The name for the QTPie stylesheet to specify style. Defaults to "".
            orientation (str, optional): Whether the slider is vertical or horizontal. Defaults to "horizontal".
            minVal (int, optional): Minimum slider value. Defaults to 0.
            maxVal (int, optional): Maximum slider value. Defaults to 100.

        Returns:\n
            QTPieSlider: A PyQt5 slider
        """

        orientationDict = {
            "horizontal": QtCore.Qt.Horizontal,
            "vertical": QtCore.Qt.Vertical
        }

        slider = QTPieSlider()
        slider.setObjectName(name)
        slider.setOrientation(orientationDict[orientation])
        slider.setMinimum(minVal)
        slider.setMaximum(maxVal)
        slider.valueChanged.connect(action)
        slider.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                             QtWidgets.QSizePolicy.Expanding)
        self.grid.addWidget(slider, gridData[1], gridData[0], gridData[3],
                            gridData[2])

        return slider

    def addRadioButton(self, gridData, name="", txt="RadioButton"):
        """
        Combines the basic Radio Button code into one function with added functionality and support for CSS syntax

        Args:\n
            gridData (list of int): List of column, row, columnspan, rowspan values
            name (str, optional): The name for the QTPie stylesheet to specify style. Defaults to "".
            txt (str, optional): The text the be displayed. Defaults to "RadioButton".

        Returns:\n
            QTPieRadioButton: A PyQt5 radio button with a text tag
        """

        radioButton = QTPieRadioButton()
        radioButton.setObjectName(name)
        radioButton.setText(txt)
        radioButton.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                  QtWidgets.QSizePolicy.Expanding)
        self.grid.addWidget(radioButton, gridData[1], gridData[0], gridData[3],
                            gridData[2])

        return radioButton

    def addCheckbox(self, gridData, name="", txt="Checkbox"):
        """
        Combines the basic Checkbox code into one function with added functionality and support for CSS syntax

        Args:\n
            gridData (list of int): List of column, row, columnspan, rowspan values
            name (str, optional): The name for the QTPie stylesheet to specify style. Defaults to "".
            txt (str, optional): The text the be displayed. Defaults to "Checkbox".

        Returns:\n
            QTPieCheckbox: A PyQt5 checkbox with a text tag
        """

        checkbox = QTPieCheckbox()
        checkbox.setObjectName(name)
        checkbox.setText(txt)
        checkbox.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                               QtWidgets.QSizePolicy.Expanding)
        self.grid.addWidget(checkbox, gridData[1], gridData[0], gridData[3],
                            gridData[2])

        return checkbox

    def addTextbox(self, gridData, name="", align="left"):
        """
        Combines the basic Textbox code into one function with added functionality and support for CSS syntax

        Args:\n
            gridData (list of int): List of column, row, columnspan, rowspan values
            name (str, optional): The name for the QTPie stylesheet to specify style. Defaults to "".

        Returns:\n
            QTPieTextbox: A PyQt5 textbox with drag and drop optional
        """

        textbox = QTPieTextbox()
        textbox.setObjectName(name)
        textbox.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                              QtWidgets.QSizePolicy.Expanding)
        self.alignWidget(textbox, align)
        self.grid.addWidget(textbox, gridData[1], gridData[0], gridData[3],
                            gridData[2])

        return textbox

    def addDial(self,
                gridData,
                action,
                name="",
                minVal=0,
                maxVal=100,
                wrapping=True):
        """
        Combines the basic Dial code into one function with added functionality and support for CSS syntax

        Args:\n
            gridData (list of int): List of column, row, columnspan, rowspan values
            action (def): The function to be called when the dial is rotated
            name (str, optional): The name for the QTPie stylesheet to specify style. Defaults to "".
            minVal (int, optional): Minimum slider value. Defaults to 0.
            maxVal (int, optional): Maximum slider value. Defaults to 100.
            wrapping (bool, optional): Whether the dial can completely circle around. Defaults to True.

        Returns:\n
            QTPieDial: A PyQt5 dial
        """

        dial = QTPieDial(wrapping=wrapping)
        dial.setObjectName(name)
        dial.setMinimum(minVal)
        dial.setMaximum(maxVal)
        dial.valueChanged.connect(action)
        dial.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                           QtWidgets.QSizePolicy.Expanding)
        self.grid.addWidget(dial, gridData[1], gridData[0], gridData[3],
                            gridData[2])

        return dial

    def addDropdown(self,
                    gridData,
                    name="",
                    align="left",
                    textEdit=False,
                    autocomp=False,
                    values=[]):
        """
        Combines the basic AutofillBox code into one function with added functionality and support for CSS syntax

        Args:\n
            gridData (list of int): List of column, row, columnspan, rowspan values
            name (str, optional): The name for the QTPie stylesheet to specify style. Defaults to "".
            align (str, optional): The alignment for the text. Defaults to "left".
            textEdit (bool, optional): Determines whether the user can type or not. Defaults to False.
            autocomp (bool, optional): Determines whether the dropdown autocompletes the text. Defaults to False.
            values (list of str, optional): The autocomplete values. Defaults to [].

        Returns:\n
            QTPieTextbox: A PyQt5 combobox with a set of autofill values
        """

        dropdown = QTPieDropdown()
        dropdown.setObjectName(name)
        dropdown.setEditable(textEdit)
        dropdown.setAutoFillBackground(autocomp)
        for _ in values:
            dropdown.addItem(_)
        dropdown.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                               QtWidgets.QSizePolicy.Expanding)
        self.grid.addWidget(dropdown, gridData[1], gridData[0], gridData[3],
                            gridData[2])

        return dropdown

    def createMenu(self):
        """
        Makes the menu bar like most applications have at the top of the screen
        """

        mainMenu = self.mainWindow.menuBar()
        fileMenu = mainMenu.addMenu('File')
        editMenu = mainMenu.addMenu('Edit')
        viewMenu = mainMenu.addMenu('View')
        helpMenu = mainMenu.addMenu('Help')

        copyAction = QtWidgets.QAction('Copy', self.window)
        copyAction.setShortcut("Ctrl+C")
        fileMenu.addAction(copyAction)

        saveAction = QtWidgets.QAction('Save', self.window)
        saveAction.setShortcut("Ctrl+S")
        fileMenu.addAction(saveAction)

        pasteAction = QtWidgets.QAction('Paste', self.window)
        pasteAction.setShortcut("Ctrl+P")
        fileMenu.addAction(pasteAction)

        exitAction = QtWidgets.QAction(QtGui.QIcon("exit.png"), 'Exit',
                                       self.window)
        exitAction.setShortcut("Ctrl+E")
        #exitAction.triggered.connect(self.exitWindow)
        fileMenu.addAction(exitAction)
Example #2
0
class QTPie:
    """
    Manages the UI based on the users monitor and position in the application.
    """
    def __init__(self,
                 icon=None,
                 tunableDict=json.loads(
                     json.dumps({
                         "windowX": 20,
                         "windowY": 50,
                         "windowWidth": 500,
                         "windowHeight": 500,
                         "volume": 50
                     })),
                 title="Window"):
        """
        Initializing the UI for Forge.

        Args:\n
            icon (string, optional): File path to the icon(.ico file) for the top left of the window. Defaults to None.
            tunableDict (JSON, optional): The tunable variables class for saving the windows position on close.
                                          Defaults to {"windowX": 10, "windowY": 10, "windowWidth": 500, "windowHeight": 500}.
            title (str, optional): The name of the window. Defaults to "Window".
        """

        stylesheet = open(
            utilities.resource_path("QTPie\\QTPie Style\\style.css"), "r")
        self.styling = stylesheet.read()
        stylesheet.close()

        self.actions = Actions()

        self.tunableDict = tunableDict

        self.app = QtWidgets.QApplication(sys.argv)
        self.app.setStyleSheet(self.styling)
        self.app.aboutToQuit.connect(
            lambda: self.actions.onWindowClose(self.mainWindow))

        if icon:
            appIcon = PyQt5.QtGui.QIcon()
            appIcon.addFile(utilities.resource_path("icon.png"))
            self.app.setWindowIcon(appIcon)

        self.grid = QtWidgets.QGridLayout()
        self.gridCount = 0
        self.grid.setSpacing(0)
        self.grid.setContentsMargins(0, 0, 0, 0)
        self.space = self.makeLabel(txt="", name="Spacer", addToGrid=False)

        self.window = QTPieWidget()
        self.window.setLayout(self.grid)

        self.mainWindow = QTPieWindow()
        self.mainWindow.setGeometry(self.tunableDict["windowX"],
                                    self.tunableDict["windowY"],
                                    self.tunableDict["windowWidth"],
                                    self.tunableDict["windowHeight"])
        self.mainWindow.setWindowTitle(title)
        self.mainWindow.setCentralWidget(self.window)

    def percentToPosition(self, xPos, yPos, width, height):
        """
        Converts percent values to pixel values and returns pixel values for QTPie to use.

        Args:\n
            xPos (int, str, float): The x coordinate of the window on the users screen.
            yPos (int, str, float):  The y coordinate of the window on the users screen.
            width (int, str, float: The width of the window.
            height (int, str, float): The height of the window.

        Returns:\n
            tuple of int: The arg converted to an int pixel value.
        """

        if type(xPos) == str:
            if xPos.find("%") != -1:
                xPos = self.window.size().width() * (
                    int(xPos.replace("%", "")) / 100)
        if type(yPos) == str:
            if yPos.find("%") != -1:
                yPos = self.window.size().height() * (
                    int(yPos.replace("%", "")) / 100)
        if type(width) == str:
            if width.find("%") != -1:
                width = self.window.size().width() * (
                    int(width.replace("%", "")) / 100)
        if type(height) == str:
            if height.find("%") != -1:
                height = self.window.size().height() * (
                    int(height.replace("%", "")) / 100)

        return int(xPos), int(yPos), int(width), int(height)

    def alignWidget(self, widget, alignment):
        """
        Given an alignment direction the widget is aligned to that direction.

        Args:\n
            widget (PyQt5.QtWidgets.QWidget): A PyQt5 widget to be aligned.
            alignment (str): A left, right or center string.
        """

        alignments = {
            "left": QtCore.Qt.AlignLeft,
            "center": QtCore.Qt.AlignCenter,
            "right": QtCore.Qt.AlignRight
        }
        widget.setAlignment(alignments[alignment.lower()])

    def addGridRow(self, grid, count, columns):
        """
        Adds a row to the given grid on the count.

        Args:\n
            grid (PyQt5.QtWidgets.QGridLayout): A grid with count amount of rows.
            count (int): The current amount of rows the grid being passed in has.
            columns (int): The amount of columns to be added to each row.
        """

        for _ in range(columns):
            grid.addWidget(self.space, count, _)
            grid.setColumnStretch(_, 1)
        grid.setRowStretch(count, 1)

    def makeLabel(self,
                  name="",
                  txt="Button",
                  enableDrop=False,
                  align="center",
                  addToGrid=True,
                  gridData=[0, 0, 0, 0]):
        """
        Combines the basic Label code into one function with added functionality and support for css syntax.

        Args:\n
            name (str, optional): The name for the QTPie stylesheet to specify style. Defaults to "".
            txt (str, optional): The text to be displayed. Defaults to "Button".
            enableDrop (bool, optional): Determines whether drag and drop is enabled. Defaults to False.
            align (str, optional): left, right, center alignment of the content of the label. Defaults to "center".
            addToGrid (bool, optional): Determines whether to add to the main grid or not. Defaults to True.
            gridData (list of int, optional): List of column, row, columnspan, rowspan values. Defaults to [0, 0, 0, 0].

        Returns:\n
            QTPieLabel: A QTPie label.
        """

        label = QTPieLabel(dropArea=enableDrop)
        label.setObjectName(name)
        label.setText(txt)
        label.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                            QtWidgets.QSizePolicy.Expanding)
        self.alignWidget(label, align)

        if addToGrid:
            self.grid.addWidget(label, gridData[1], gridData[0], gridData[3],
                                gridData[2])

        return label

    def makeImage(self,
                  name="",
                  filename=r"smile.jpg",
                  keepAR=True,
                  enableDrop=False,
                  align="center",
                  addToGrid=True,
                  gridData=[0, 0, 0, 0]):
        """
        Combines the basic Image code into one function with added functionality and support for CSS syntax

        Args:\n
            name (str, optional): The name for the QTPie stylesheet to specify style. Defaults to "".
            filename (str, optional): The filepath for the pixmap image. Defaults to "icon.png".
            keepAR (bool, optional): Whether to keep the original pictures aspect ratio or fit to given width and height. Defaults to True.
            enableDrop (bool, optional): Determines whether drag and drop is enabled. Defaults to False.
            align (str, optional): left, right, center alignment of the content of the label. Defaults to "center".
            addToGrid (bool, optional): Determines whether to add to the main grid or not. Defaults to True.
            gridData (list of int, optional): List of column, row, columnspan, rowspan values. Defaults to [0, 0, 0, 0].

        Returns:\n
            QTPieImage: A QTPie image with a pixmamp in it and extending the QTPieLabel
        """

        name += "Image"

        image = QTPieImage(dropArea=enableDrop, filename=filename)
        image.pixelMap = QTPiePixmap()
        image.pixelMap = image.pixelMap.fromImage(PyQt5.QtGui.QImage(filename))

        image.setObjectName(name)
        image.setPixmap(image.pixelMap)
        image.setSizePolicy(PyQt5.QtWidgets.QSizePolicy.Ignored,
                            PyQt5.QtWidgets.QSizePolicy.Ignored)
        self.alignWidget(image, align)

        if addToGrid:
            self.grid.addWidget(image, gridData[1], gridData[0], gridData[3],
                                gridData[2])

        return image

    def makeButton(self,
                   clickAction,
                   mouseEnterAction=None,
                   mouseLeaveAction=None,
                   name="",
                   txt="Button",
                   icon="",
                   enableDrop=False,
                   enableHover=False,
                   addToGrid=True,
                   gridData=[0, 0, 0, 0]):
        """
        Combines the basic Button code into one function with added functionality and support for css syntax. Optional to apply to grid.

        Args:\n
            clickAction (def): The function to be called on click.
            mouseEnterAction (def, optional): The function to be called on the mouse entering the button. Defaults to None.
            mouseLeaveAction (def, optional): The function to be called on the mouse leaving the button. Defaults to None.
            name (str, optional): The name for the QTPie stylesheet to specify style. Defaults to "".
            txt (str, optional): The text the be displayed. Defaults to "Button".
            icon (str, optional): The string corresponding to an icon. Defaults to "".
            enableDrop (bool, optional): Determines whether drag and drop is enabled. Defaults to False.
            enableHover (bool, optional): Determines whether hovering signals are enabled. Defaults to False.
            addToGrid (bool, optional): Determines whether to add to the main grid or not. Defaults to True.
            gridData (list of int, optional): List of column, row, columnspan, rowspan values. Defaults to [0, 0, 0, 0].

        Returns:\n
            QTPieButton: A PyQt5 push button.
        """

        icons = {
            "play": PyQt5.QtWidgets.QStyle.SP_MediaPlay,
            "pause": PyQt5.QtWidgets.QStyle.SP_MediaPause,
            "file": PyQt5.QtWidgets.QStyle.SP_FileLinkIcon,
            "volume": PyQt5.QtWidgets.QStyle.SP_MediaVolume,
            "muted": PyQt5.QtWidgets.QStyle.SP_MediaVolumeMuted
        }

        btn = QTPieButton(dropArea=enableDrop, hover=enableHover)
        btn.setObjectName(name)
        if icon in icons:
            btn.setIcon(self.app.style().standardIcon(icons[icon]))
        else:
            btn.setText(txt)
        btn.clicked.connect(clickAction)
        if mouseEnterAction:
            btn.hover = enableHover
            btn.mouseEnter.connect(mouseEnterAction)
        if mouseLeaveAction:
            btn.hover = enableHover
            btn.mouseLeave.connect(mouseLeaveAction)
        btn.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                          QtWidgets.QSizePolicy.Expanding)

        if addToGrid:
            self.grid.addWidget(btn, gridData[1], gridData[0], gridData[3],
                                gridData[2])

        return btn

    def makeVolume(self, mediaWidget, volumeWidget):
        """
        Create a volume slider for a given media. Does not apply to grid.

        Args:\n
            mediaWidget (QTPieMediaWidget): The widget that holds all media player widgets.
            volumeWidget (QTPieVolumeWidget): The widget that holds all volume widgets.
            parent (QTPieScrollArea or QTPieWidget): The widget for the button to be placed on.

        Returns:\n
            QTPieSlider: A QTPie slider.
        """

        volume = QTPieSlider()
        volume.setObjectName("VideoVolume")
        volume.setOrientation(QtCore.Qt.Horizontal)
        volume.setMinimum(0)
        volume.setMaximum(100)
        volume.setValue(mediaWidget.media.volume())
        volume.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                             QtWidgets.QSizePolicy.Expanding)
        volume.valueChanged.connect(lambda: self.actions.changeVolume(
            mediaWidget, volumeWidget, self.app, self.tunableDict))

        return volume

    def makeVideoProgressBar(self, mediaWidget):
        """
        Create a volume slider for a given media. Does not apply to grid.

        Args:\n
            mediaWidget (QTPieMediaWidget): The widget that holds all media player widgets.

        Returns:\n
            QTPieSlider: A QTPie slider.
        """

        videoProgress = QTPieSlider()
        videoProgress.setObjectName("VideoProgressBar")
        videoProgress.setOrientation(QtCore.Qt.Horizontal)
        videoProgress.setMinimum(0)
        videoProgress.setMaximum(100)
        videoProgress.sliderMoved.connect(
            lambda: self.actions.changeTimestamp(mediaWidget, videoProgress))
        mediaWidget.media.positionChanged.connect(
            lambda: self.actions.timestampChanged(mediaWidget, videoProgress))
        mediaWidget.media.durationChanged.connect(
            lambda: self.actions.durationChanged(mediaWidget, videoProgress))
        videoProgress.setValue(mediaWidget.media.position())
        videoProgress.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                    QtWidgets.QSizePolicy.Expanding)

        return videoProgress

    def setupWidget(self, widget, name="", makeGrid=True, columns=1, rows=1):
        """
        Boilerplate for the QTPie widgets.

        Args:\n
            widget (QTPieWidget or super(QTPieWidget)): The widget to be setup.
            name (str, optional): The name for the style sheet. Defaults to "".
            makeGrid (bool, optional): Whether the grid is setup immediatley or not. Defautls to True.
            columns (int, optional): The number of columns per row of the grid. Defaults to 1.
            rows (int, optional): The number of rows in the grid. Defaults to 1.
        """

        widget.setObjectName(name)
        widget.setMouseTracking(True)
        widget.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                             QtWidgets.QSizePolicy.Expanding)

        if makeGrid:
            self.setupGrid(widget, name, columns, rows)

    def setupGrid(self, widget, name="", columns=1, rows=1):
        """
        Boilerplate for the PyQt5 QGridLayout's.

        Args:\n
            widget (QTPieWidget or super(QTPieWidget)): The widget to be setup.
            name (str, optional): The name for the style sheet. Defaults to "".
            columns (int, optional): The number of columns per row of the grid. Defaults to 1.
            rows (int, optional): The number of rows in the grid. Defaults to 1.
        """

        widget.grid = QtWidgets.QGridLayout()
        widget.grid.setObjectName(name)
        widget.grid.setSpacing(0)
        widget.grid.setContentsMargins(0, 0, 0, 0)

        for i in range(rows):
            self.addGridRow(widget.grid, widget.gridCount, columns)
            widget.gridCount += 1

    def makeVideo(self,
                  name="",
                  filename=r"ChrisH.mp4",
                  enableDrop=False,
                  addToGrid=True,
                  gridData=[0, 0, 0, 0]):
        """
        Combines the basic Video code into one function with added functionality and support for CSS syntax.

        Args:\n
            name (str, optional): The name for the QTPie stylesheet to specify style. Defaults to "".
            filename (str, optional): The filepath for the media player video.
            addToGrid (bool, optional): Determines whether to add to the main grid or not. Defaults to True.
            gridData (list of int, optional): List of column, row, columnspan, rowspan values. Defaults to [0, 0, 0, 0].
        
        Returns:\n
            QTPieVideo: A PyQt5 media player
        """

        name = "mediaPlayer" + name
        '''Making the widget for the media'''
        mediaWidget = QTPieMediaWidget(doesSignal=True, dropArea=True)
        self.setupWidget(mediaWidget, name=name)

        #Assigning video to mediaWidget
        mediaWidget.video = QTPieVideo()
        mediaWidget.video.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                        QtWidgets.QSizePolicy.Expanding)

        #Assigning media to mediaWidget
        mediaWidget.media = QTPieMedia()
        mediaWidget.media.setMedia(
            PyQt5.QtMultimedia.QMediaContent(
                PyQt5.QtCore.QUrl.fromLocalFile(filename)))
        mediaWidget.media.setVideoOutput(mediaWidget.video)
        mediaWidget.media.setVolume(self.tunableDict["volume"])
        mediaWidget.media.setObjectName(name)
        '''Making the widget for the media controls'''
        controlWidget = QTPieControlWidget(doesSignal=True)
        self.setupWidget(controlWidget, name=name + "Controls", columns=12)

        #Assigning widgets for the controlWidget
        controlWidget.playPause = self.makeButton(
            lambda: self.actions.playPause(mediaWidget, controlWidget, self.app
                                           ),
            name="VideoPlayPause",
            icon="pause",
            addToGrid=False)
        controlWidget.openFile = self.makeButton(
            lambda: self.actions.openFile(mediaWidget),
            name="VideoOpenFile",
            icon="file",
            addToGrid=False)
        controlWidget.videoProgress = self.makeVideoProgressBar(mediaWidget)
        '''Making the widget for the volume controls'''
        volumeWidget = QTPieVolumeWidget(doesSignal=True)
        self.setupWidget(volumeWidget, name=name + "Volume", columns=6)

        #Assigning widgets for the volumeWidget
        volumeWidget.volumeBar = self.makeVolume(mediaWidget, volumeWidget)
        volumeWidget.volumeBtn = self.makeButton(
            lambda: self.actions.muteUnmute(mediaWidget, volumeWidget, self.
                                            app, self.tunableDict),
            mouseEnterAction=lambda: self.actions.volumeHover(volumeWidget),
            name="VideoVolumeBtn",
            icon="volume",
            enableHover=True,
            addToGrid=False)

        volumeWidget.mouseLeave.connect(
            lambda: self.actions.volumeUnhover(volumeWidget))

        #Adding widgets to volumeWidget grid layout
        volumeWidget.grid.addWidget(volumeWidget.volumeBtn, 0, 0, 1, 1)
        volumeWidget.grid.addWidget(volumeWidget.volumeBar, 0, 1, 1, 2)

        #Setting layout of volumeWidget to grid
        volumeWidget.setLayout(volumeWidget.grid)
        volumeWidget.volumeBar.hide()

        #Assigning volume widget to controlWidget
        controlWidget.volumeWidget = volumeWidget
        controlWidget.updateControls()

        #Adding widgets to controlWidget grid layout
        controlWidget.grid.addWidget(controlWidget.playPause, 1, 0, 1, 1)
        controlWidget.grid.addWidget(controlWidget.volumeWidget, 1, 1, 1, 6)
        controlWidget.grid.addWidget(controlWidget.openFile, 1, 11, 1, 1)
        controlWidget.grid.addWidget(controlWidget.videoProgress, 0, 0, 1, 12)

        #Finalizing the controlWidget and connecting actions
        controlWidget.setLayout(controlWidget.grid)

        #Connecting actions to the mediaWidget
        mediaWidget.clicked.connect(lambda: self.actions.playPause(
            mediaWidget, controlWidget, self.app))
        mediaWidget.mouseEnter.connect(
            lambda: self.actions.showControls(controlWidget))
        mediaWidget.mouseLeave.connect(
            lambda: self.actions.hideControls(mediaWidget, controlWidget))

        #Adding widgets to mediaWidget grid layout
        mediaWidget.grid.addWidget(mediaWidget.video, 0, 0, 20, 11)
        mediaWidget.grid.addWidget(controlWidget, 18, 0, 2, 11)
        mediaWidget.setLayout(mediaWidget.grid)

        self.actions.hideControls(mediaWidget, controlWidget)
        self.actions.playPause(mediaWidget, controlWidget, self.app)

        if addToGrid:
            self.grid.addWidget(mediaWidget, gridData[1], gridData[0],
                                gridData[3], gridData[2])

        return mediaWidget

    def makeProgressBar(self, name="", addToGrid=True, gridData=[0, 0, 0, 0]):
        """
        Combines the basic Progress Bar code into one function with added functionality and support for CSS syntax.

        Args:\n
            name (str, optional): The name for the QTPie stylesheet to specify style. Defaults to "".
            addToGrid (bool, optional): Determines whether to add to the main grid or not. Defaults to True.
            gridData (list of int, optional): List of column, row, columnspan, rowspan values. Defaults to [0, 0, 0, 0].

        Returns:\n
            QTPieProgressBar: A QTPie progress bar.
        """

        progressBar = QTPieProgressBar()
        progressBar.setObjectName(name)
        progressBar.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                  QtWidgets.QSizePolicy.Expanding)

        if addToGrid:
            self.grid.addWidget(progressBar, gridData[1], gridData[0],
                                gridData[3], gridData[2])

        return progressBar

    def makeSlider(self,
                   action,
                   name="",
                   orientation="horizontal",
                   minVal=0,
                   maxVal=100,
                   addToGrid=True,
                   gridData=[0, 0, 0, 0]):
        """
        Combines the basic Slider code into one function with added functionality and support for CSS syntax.

        Args:\n
            action (def): The function to be called when the slider is moved.
            name (str, optional): The name for the QTPie stylesheet to specify style. Defaults to "".
            orientation (str, optional): Whether the slider is vertical or horizontal. Defaults to "horizontal".
            minVal (int, optional): Minimum slider value. Defaults to 0.
            maxVal (int, optional): Maximum slider value. Defaults to 100.
            addToGrid (bool, optional): Determines whether to add to the main grid or not. Defaults to True.
            gridData (list of int, optional): List of column, row, columnspan, rowspan values. Defaults to [0, 0, 0, 0].

        Returns:\n
            QTPieSlider: A QTPie slider.
        """

        orientationDict = {
            "horizontal": QtCore.Qt.Horizontal,
            "vertical": QtCore.Qt.Vertical
        }

        slider = QTPieSlider()
        slider.setObjectName(name)
        slider.setOrientation(orientationDict[orientation])
        slider.setMinimum(minVal)
        slider.setMaximum(maxVal)
        slider.valueChanged.connect(action)
        slider.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                             QtWidgets.QSizePolicy.Expanding)

        if addToGrid:
            self.grid.addWidget(slider, gridData[1], gridData[0], gridData[3],
                                gridData[2])

        return slider

    def makeRadioButton(self,
                        name="",
                        txt="RadioButton",
                        addToGrid=True,
                        gridData=[0, 0, 0, 0]):
        """
        Combines the basic Radio Button code into one function with added functionality and support for CSS syntax.

        Args:\n
            name (str, optional): The name for the QTPie stylesheet to specify style. Defaults to "".
            txt (str, optional): The text the be displayed. Defaults to "RadioButton".
            addToGrid (bool, optional): Determines whether to add to the main grid or not. Defaults to True.
            gridData (list of int, optional): List of column, row, columnspan, rowspan values. Defaults to [0, 0, 0, 0].

        Returns:\n
            QTPieRadioButton: A QTPie radio button with a text tag.
        """

        radioButton = QTPieRadioButton()
        radioButton.setObjectName(name)
        radioButton.setText(txt)
        radioButton.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                  QtWidgets.QSizePolicy.Expanding)

        if addToGrid:
            self.grid.addWidget(radioButton, gridData[1], gridData[0],
                                gridData[3], gridData[2])

        return radioButton

    def makeCheckbox(self,
                     name="",
                     txt="Checkbox",
                     addToGrid=True,
                     gridData=[0, 0, 0, 0]):
        """
        Combines the basic Checkbox code into one function with added functionality and support for CSS syntax.

        Args:\n
            name (str, optional): The name for the QTPie stylesheet to specify style. Defaults to "".
            txt (str, optional): The text the be displayed. Defaults to "Checkbox".
            addToGrid (bool, optional): Determines whether to add to the main grid or not. Defaults to True.
            gridData (list of int, optional): List of column, row, columnspan, rowspan values. Defaults to [0, 0, 0, 0].

        Returns:\n
            QTPieCheckbox: A QTPie checkbox with a text tag.
        """

        checkbox = QTPieCheckbox()
        checkbox.setObjectName(name)
        checkbox.setText(txt)
        checkbox.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                               QtWidgets.QSizePolicy.Expanding)

        if addToGrid:
            self.grid.addWidget(checkbox, gridData[1], gridData[0],
                                gridData[3], gridData[2])

        return checkbox

    def makeTextbox(self,
                    name="",
                    align="left",
                    enableDrop=False,
                    addToGrid=True,
                    gridData=[0, 0, 0, 0]):
        """
        Combines the basic Textbox code into one function with added functionality and support for CSS syntax.

        Args:\n
            name (str, optional): The name for the QTPie stylesheet to specify style. Defaults to "".
            aling (str, optional): left, right, center alignment of the content of the label. Defaults to "left".
            enableDrop (bool, optional): Enables or disables text droppping into the text box. Defaults to False.
            addToGrid (bool, optional): Determines whether to add to the main grid or not. Defaults to True.
            gridData (list of int, optional): List of column, row, columnspan, rowspan values. Defaults to [0, 0, 0, 0].

        Returns:\n
            QTPieTextbox: A QTPie textbox with drag and drop optional
        """

        textbox = QTPieTextbox(dropArea=enableDrop)
        textbox.setObjectName(name)
        textbox.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                              QtWidgets.QSizePolicy.Expanding)
        self.alignWidget(textbox, align)

        if addToGrid:
            self.grid.addWidget(textbox, gridData[1], gridData[0], gridData[3],
                                gridData[2])

        return textbox

    def makeDial(self,
                 action,
                 name="",
                 minVal=0,
                 maxVal=100,
                 wrapping=True,
                 addToGrid=True,
                 gridData=[0, 0, 0, 0]):
        """
        Combines the basic Dial code into one function with added functionality and support for CSS syntax.

        Args:\n
            action (def): The function to be called when the dial is rotated.
            name (str, optional): The name for the QTPie stylesheet to specify style. Defaults to "".
            minVal (int, optional): Minimum slider value. Defaults to 0.
            maxVal (int, optional): Maximum slider value. Defaults to 100.
            wrapping (bool, optional): Whether the dial can completely circle around. Defaults to True.
            addToGrid (bool, optional): Determines whether to add to the main grid or not. Defaults to True.
            gridData (list of int, optional): List of column, row, columnspan, rowspan values. Defaults to [0, 0, 0, 0].

        Returns:\n
            QTPieDial: A QTPie dial.
        """

        dial = QTPieDial(wrapping=wrapping)
        dial.setObjectName(name)
        dial.setMinimum(minVal)
        dial.setMaximum(maxVal)
        dial.valueChanged.connect(action)
        dial.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                           QtWidgets.QSizePolicy.Expanding)

        if addToGrid:
            self.grid.addWidget(dial, gridData[1], gridData[0], gridData[3],
                                gridData[2])

        return dial

    def makeDropdown(self,
                     name="",
                     align="left",
                     textEdit=False,
                     autocomp=False,
                     values=[],
                     addToGrid=True,
                     gridData=[0, 0, 0, 0]):
        """
        Combines the basic AutofillBox code into one function with added functionality and support for CSS syntax.

        Args:\n
            name (str, optional): The name for the QTPie stylesheet to specify style. Defaults to "".
            align (str, optional): The alignment for the text. Defaults to "left".
            textEdit (bool, optional): Determines whether the user can type or not. Defaults to False.
            autocomp (bool, optional): Determines whether the dropdown autocompletes the text. Defaults to False.
            values (list of str, optional): The autocomplete values. Defaults to [].
            addToGrid (bool, optional): Determines whether to add to the main grid or not. Defaults to True.
            gridData (list of int, optional): List of column, row, columnspan, rowspan values. Defaults to [0, 0, 0, 0].

        Returns:\n
            QTPieTextbox: A QTPie dropdown with a set of autofill values
        """

        dropdown = QTPieDropdown()
        dropdown.setObjectName(name)
        dropdown.setEditable(textEdit)
        dropdown.setAutoFillBackground(autocomp)
        for _ in values:
            dropdown.addItem(_)
        dropdown.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                               QtWidgets.QSizePolicy.Expanding)

        if addToGrid:
            self.grid.addWidget(dropdown, gridData[1], gridData[0],
                                gridData[3], gridData[2])

        return dropdown

    def createMenu(self):
        """
        Makes the menu bar like most applications have at the top of the screen.
        """

        mainMenu = self.mainWindow.menuBar()
        fileMenu = mainMenu.addMenu('File')
        editMenu = mainMenu.addMenu('Edit')
        viewMenu = mainMenu.addMenu('View')
        helpMenu = mainMenu.addMenu('Help')

        copyAction = QtWidgets.QAction('Copy', self.window)
        copyAction.setShortcut("Ctrl+C")
        fileMenu.addAction(copyAction)

        saveAction = QtWidgets.QAction('Save', self.window)
        saveAction.setShortcut("Ctrl+S")
        fileMenu.addAction(saveAction)

        pasteAction = QtWidgets.QAction('Paste', self.window)
        pasteAction.setShortcut("Ctrl+P")
        fileMenu.addAction(pasteAction)

        exitAction = QtWidgets.QAction(QtGui.QIcon("exit.png"), 'Exit',
                                       self.window)
        exitAction.setShortcut("Ctrl+E")
        fileMenu.addAction(exitAction)