diff --git a/src/tribler/gui/tests/test_utilities.py b/src/tribler/gui/tests/test_utilities.py index 64010158ee7..c22290baac4 100644 --- a/src/tribler/gui/tests/test_utilities.py +++ b/src/tribler/gui/tests/test_utilities.py @@ -6,7 +6,7 @@ from tribler.gui.utilities import TranslatedString, compose_magnetlink, create_api_key, dict_item_is_any_of, \ duration_to_string, \ format_api_key, \ - quote_plus_unicode, set_api_key, unicode_quoter + format_size, quote_plus_unicode, set_api_key, unicode_quoter def test_quoter_char(): @@ -247,3 +247,10 @@ def test_wrong_parameters_in_original_string(warning: Mock): warning.assert_called_once_with('TypeError: Wrong number of parameters in translation "translated", ' 'original string: "original"') + + +def test_format_size(): + assert format_size(0) == '0.0 B' + assert format_size(1) == '1.0 B' + assert format_size(1.5) == '1.5 B' + assert format_size(2000) == '2.0 kB' diff --git a/src/tribler/gui/utilities.py b/src/tribler/gui/utilities.py index 6eb34575f78..ae27f2601a8 100644 --- a/src/tribler/gui/utilities.py +++ b/src/tribler/gui/utilities.py @@ -83,7 +83,7 @@ def index2uri(index): return data_item2uri(index.model().data_items[index.row()]) -def format_size(num, suffix='B', precision=1): +def format_size(num, suffix='B', precision=1) -> str: for unit in ['', 'k', 'M', 'G', 'T', 'P', 'E', 'Z']: if abs(num) < 1024.0: return f"{num:3.{precision}f} {unit}{suffix}" diff --git a/src/tribler/gui/widgets/tablecontentdelegate.py b/src/tribler/gui/widgets/tablecontentdelegate.py index 7d278f50515..54455638fdd 100644 --- a/src/tribler/gui/widgets/tablecontentdelegate.py +++ b/src/tribler/gui/widgets/tablecontentdelegate.py @@ -33,8 +33,8 @@ TAG_TOP_MARGIN, WINDOWS, ) -from tribler.gui.utilities import format_votes, get_color, get_gui_setting, get_health, get_image_path, \ - get_objects_with_predicate, tr +from tribler.gui.utilities import format_size, format_votes, get_color, get_gui_setting, get_health, get_image_path, \ + get_objects_with_predicate, pretty_date, tr from tribler.gui.widgets.tablecontentmodel import Column, RemoteTableModel from tribler.gui.widgets.tableiconbuttons import DownloadIconButton @@ -525,6 +525,38 @@ def draw_title_and_tags(self, painter: QPainter, option: QStyleOptionViewItem, i self.edit_tags_icon.paint(painter, edit_rect) +def calculate_panel_y(y: int, index: int) -> int: + return y + 60 + TORRENT_IN_SNIPPET_HEIGHT // 2 + TORRENT_IN_SNIPPET_HEIGHT * index - 6 + + +class SnippetSizeColumnMixin: + def draw_size(self, painter: QPainter, option: QStyleOptionViewItem, _, data_item: Dict) -> None: + if data_item.get('type') != SNIPPET: + return + + for index, torrent in enumerate(data_item["torrents_in_snippet"]): + painter.save() + panel_y = calculate_panel_y(option.rect.topLeft().y(), index) + text_box = QRect(option.rect.left() + 5, panel_y + 5, 0, 0) + txt = format_size(torrent['size']) + draw_text(painter, text_box, txt, color=TRIBLER_NEUTRAL) + painter.restore() + + +class SnippetCreatedColumnMixin: + def draw_created(self, painter: QPainter, option: QStyleOptionViewItem, _, data_item: Dict) -> None: + if data_item.get('type') != SNIPPET: + return + + for index, torrent in enumerate(data_item["torrents_in_snippet"]): + painter.save() + panel_y = calculate_panel_y(option.rect.topLeft().y(), index) + text_box = QRect(option.rect.left() + 5, panel_y + 5, 0, 0) + txt = pretty_date(torrent['created']) + draw_text(painter, text_box, txt, color=TRIBLER_NEUTRAL) + painter.restore() + + class RatingControlMixin: def draw_rating_control(self, painter, option, index, data_item): # Draw empty cell as the background @@ -600,12 +632,14 @@ def draw_download_controls(self, painter, option, index, data_item): class HealthLabelMixin: - def draw_health_column(self, painter, option, index, data_item): + def draw_health_column(self, painter, option, index, data_item: Dict): # Draw empty cell as the background self.paint_empty_background(painter, option) - - if data_item.get('type') == REGULAR_TORRENT: - self.health_status_widget.paint(painter, option.rect, index, hover=index == self.hover_index) + if data_item.get('type') != SNIPPET: + hover = index == self.hover_index + else: + hover = False + self.health_status_widget.paint(painter, option.rect, index, hover) return True @@ -619,6 +653,8 @@ class TriblerContentDelegate( ChannelStateMixin, SubscribedControlMixin, TagsMixin, + SnippetSizeColumnMixin, + SnippetCreatedColumnMixin, ): def __init__(self, table_view, parent=None): # TODO: refactor this not to rely on inheritance order, but instead use interface method pattern @@ -647,6 +683,8 @@ def __init__(self, table_view, parent=None): (Column.HEALTH, self.draw_health_column), (Column.STATUS, self.draw_commit_status_column), (Column.STATE, self.draw_channel_state), + (Column.SIZE, self.draw_size), + (Column.CREATED, self.draw_created), ] self.table_view = table_view @@ -873,10 +911,10 @@ def paint(self, painter, rect, index, hover=False): self.paint_elements(painter, rect, panel_y, health, data_item, hover) elif data_item["type"] == SNIPPET: for ind, torrent_in_snippet in enumerate(data_item["torrents_in_snippet"]): - panel_y = rect.topLeft().y() + 60 + TORRENT_IN_SNIPPET_HEIGHT // 2 + TORRENT_IN_SNIPPET_HEIGHT * ind - 6 + panel_y = calculate_panel_y(rect.topLeft().y(), ind) health = get_health(torrent_in_snippet['num_seeders'], torrent_in_snippet['num_leechers'], torrent_in_snippet['last_tracker_check']) - self.paint_elements(painter, rect, panel_y, health, torrent_in_snippet, hover, draw_health_text=False) + self.paint_elements(painter, rect, panel_y, health, torrent_in_snippet, hover, draw_health_text=True) def paint_elements(self, painter, rect, panel_y, health, data_item, hover=False, draw_health_text=True): painter.save() diff --git a/src/tribler/gui/widgets/tablecontentmodel.py b/src/tribler/gui/widgets/tablecontentmodel.py index 54b252bb7e6..bc2cee5ce3b 100644 --- a/src/tribler/gui/widgets/tablecontentmodel.py +++ b/src/tribler/gui/widgets/tablecontentmodel.py @@ -506,10 +506,8 @@ def item_txt(self, index, role, is_editing: bool = False): column_type == Column.SIZE and "torrents" not in self.columns and "torrents" in item - and item["type"] in (CHANNEL_TORRENT, COLLECTION_NODE, SNIPPET) + and item["type"] in (CHANNEL_TORRENT, COLLECTION_NODE) ): - if item["type"] == SNIPPET: - return "" return item["torrents"] # 'subscribed' column gets special treatment in case of ToolTipRole, because