def file_types_present_details(self,
                                   title_case=True,
                                   singular_natural=False) -> str:
        """
        Displays details about how many files are selected or ready to be downloaded.

        :param title_case: whether the details should use title case or not.
        :param singular_natural: if True, instead of '1 photo', return 'A photo'. If True,
         title_case parameter is treated as always False.
        :return:
        """

        p = self[FileType.photo]
        v = self[FileType.video]

        if v > 1:
            # Translators: %(variable)s represents Python code, not a plural of the term
            # variable. You must keep the %(variable)s untranslated, or the program will
            # crash.
            videos = _('%(no_videos)s Videos') % dict(no_videos=thousands(v))
        elif v == 1:
            if singular_natural:
                # translators: natural language expression signifying a single video
                videos = _('a video')
            else:
                videos = _('1 Video')

        if p > 1:
            # Translators: %(variable)s represents Python code, not a plural of the term
            # variable. You must keep the %(variable)s untranslated, or the program will
            # crash.
            photos = _('%(no_photos)s Photos') % dict(no_photos=thousands(p))
        elif p == 1:
            if singular_natural:
                # translators: natural language expression signifying a single photo
                photos = _('a photo')
            else:
                photos = _('1 Photo')

        if (p > 0) and (v > 0):
            s = make_internationalized_list([photos, videos])
        elif (p == 0) and (v == 0):
            return ''
        elif v > 0:
            s = videos
        else:
            s = photos

        if title_case or singular_natural:
            return s
        else:
            return s.lower()
    def summarize_file_count(self) -> Tuple[str, str]:
        """
        Summarizes the total number of photos and/or videos that can be
        downloaded. Displayed in the progress bar at the top of the
        main application window after a scan is finished.

        :return tuple with (1) number of files, e.g.
         "433 photos and videos" or "23 videos". and (2) file types
         present e.g. "photos and videos"
        """
        file_types_present = self.file_types_present()
        # Translators: %(variable)s represents Python code, not a plural of the term
        # variable. You must keep the %(variable)s untranslated, or the program will
        # crash.
        file_count_summary = _("%(number)s %(filetypes)s") % dict(
            number=thousands(self[FileType.photo] + self[FileType.video]),
            filetypes=file_types_present)
        return file_count_summary, file_types_present
def make_body_details(
    bytes_total: int,
    bytes_free: int,
    files_to_display: DisplayingFilesOfType,
    marked: FileTypeCounter,
    photos_size_to_download: int,
    videos_size_to_download: int,
) -> BodyDetails:
    """
    Gather the details to render for destination storage usage
    for photo and video downloads, and their backups.

    :param bytes_total:
    :param bytes_free:
    :param files_to_display:
    :param marked:
    :param photos_size_to_download:
    :param videos_size_to_download:
    :return:
    """

    bytes_total_text = format_size_for_user(bytes_total, no_decimals=0)
    existing_bytes = bytes_total - bytes_free
    existing_size = format_size_for_user(existing_bytes)

    photos = videos = photos_size = videos_size = ""

    if files_to_display != DisplayingFilesOfType.videos:
        # Translators: %(variable)s represents Python code, not a plural of the term
        # variable. You must keep the %(variable)s untranslated, or the program will
        # crash.
        photos = _("%(no_photos)s Photos") % {
            "no_photos": thousands(marked[FileType.photo])
        }
        photos_size = format_size_for_user(photos_size_to_download)
    if files_to_display != DisplayingFilesOfType.photos:
        # Translators: %(variable)s represents Python code, not a plural of the term
        # variable. You must keep the %(variable)s untranslated, or the program will
        # crash.
        videos = _("%(no_videos)s Videos") % {
            "no_videos": thousands(marked[FileType.video])
        }
        videos_size = format_size_for_user(videos_size_to_download)

    size_to_download = photos_size_to_download + videos_size_to_download
    comp1_file_size_sum = photos_size_to_download
    comp2_file_size_sum = videos_size_to_download
    comp3_file_size_sum = existing_bytes
    comp1_text = photos
    comp2_text = videos
    comp3_text = _("Used")
    comp4_text = _("Excess")
    comp1_size_text = photos_size
    comp2_size_text = videos_size
    comp3_size_text = existing_size

    bytes_to_use = size_to_download + existing_bytes
    percent_used = ""

    if bytes_total == 0:
        bytes_free_of_total = _("Device size unknown")
        comp4_file_size_sum = 0
        comp4_size_text = 0
        comp3_size_text = 0
    elif bytes_to_use > bytes_total:
        bytes_total_ = bytes_total
        bytes_total = bytes_to_use
        excess_bytes = bytes_to_use - bytes_total_
        comp4_file_size_sum = excess_bytes
        comp4_size_text = format_size_for_user(excess_bytes)
        # Translators: %(variable)s represents Python code, not a plural of the term
        # variable. You must keep the %(variable)s untranslated, or the program will
        # crash.
        bytes_free_of_total = _("No space free on %(size_total)s device"
                                ) % dict(size_total=bytes_total_text)
    else:
        comp4_file_size_sum = 0
        comp4_size_text = 0
        bytes_free = bytes_total - bytes_to_use
        # Translators: %(variable)s represents Python code, not a plural of the term
        # variable. You must keep the %(variable)s untranslated, or the program will
        # crash.
        bytes_free_of_total = _("%(size_free)s free of %(size_total)s") % dict(
            size_free=format_size_for_user(bytes_free, no_decimals=1),
            size_total=bytes_total_text,
        )

    return BodyDetails(
        bytes_total_text=bytes_total_text,
        bytes_total=bytes_total,
        percent_used_text=percent_used,
        bytes_free_of_total=bytes_free_of_total,
        comp1_file_size_sum=comp1_file_size_sum,
        comp2_file_size_sum=comp2_file_size_sum,
        comp3_file_size_sum=comp3_file_size_sum,
        comp4_file_size_sum=comp4_file_size_sum,
        comp1_text=comp1_text,
        comp2_text=comp2_text,
        comp3_text=comp3_text,
        comp4_text=comp4_text,
        comp1_size_text=comp1_size_text,
        comp2_size_text=comp2_size_text,
        comp3_size_text=comp3_size_text,
        comp4_size_text=comp4_size_text,
        color1=QColor(CustomColors.color1.value),
        color2=QColor(CustomColors.color2.value),
        color3=QColor(CustomColors.color3.value),
        displaying_files_of_type=files_to_display,
    )