Create and return a new asset

        :param project: the project for the asset
        :type project: :class:`jukeboxcore.djadapter.models.Project`
        :param atype: the assettype of the asset
        :type atype: :class:`jukeboxcore.djadapter.models.Atype`
        :param shot: the shot to add the asset to
        :type shot: :class:`jukeboxcore.djadapter.models.Shot`
        :param asset: the asset to add the new asset to
        :type asset: :class:`jukeboxcore.djadapter.models.Asset`
        :returns: The created asset or None
        :rtype: None | :class:`jukeboxcore.djadapter.models.Asset`
        :raises: None

def create_asset(self, project, atype=None, shot=None, asset=None):
        """Create and return a new asset

        :param project: the project for the asset
        :type project: :class:`jukeboxcore.djadapter.models.Project`
        :param atype: the assettype of the asset
        :type atype: :class:`jukeboxcore.djadapter.models.Atype`
        :param shot: the shot to add the asset to
        :type shot: :class:`jukeboxcore.djadapter.models.Shot`
        :param asset: the asset to add the new asset to
        :type asset: :class:`jukeboxcore.djadapter.models.Asset`
        :returns: The created asset or None
        :rtype: None | :class:`jukeboxcore.djadapter.models.Asset`
        :raises: None
        """
        element = shot or asset
        dialog = AssetCreatorDialog(project=project, atype=atype, parent=self)
        dialog.exec_()
        asset = dialog.asset
        if not atype:
            element.assets.add(asset)
        return asset