From f3f9245d2ba23c9b1c14e882ee849923ff8ebdfe Mon Sep 17 00:00:00 2001 From: "V.G. Bulavintsev" Date: Sat, 25 Dec 2021 16:44:47 +0100 Subject: [PATCH 1/2] Disable progressbars for individual files --- .../tribler_gui/widgets/downloadsdetailstabwidget.py | 5 ++++- src/tribler-gui/tribler_gui/widgets/torrentfiletreewidget.py | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/tribler-gui/tribler_gui/widgets/downloadsdetailstabwidget.py b/src/tribler-gui/tribler_gui/widgets/downloadsdetailstabwidget.py index 4e7ac9a43b9..c2854ba40c4 100644 --- a/src/tribler-gui/tribler_gui/widgets/downloadsdetailstabwidget.py +++ b/src/tribler-gui/tribler_gui/widgets/downloadsdetailstabwidget.py @@ -10,7 +10,10 @@ from tribler_gui.utilities import compose_magnetlink, connect, copy_to_clipboard, format_size, format_speed, tr INCLUDED_FILES_CHANGE_DELAY = 1000 # milliseconds -PROGRESS_BAR_DRAW_LIMIT = 1000 # Don't draw progress bars for files in torrents that have more than this many files + +# Disabled, because drawing progress bars with setItemWidget is horribly slow on some systems. +# We must use delegate-based drawing instead +PROGRESS_BAR_DRAW_LIMIT = 0 # Don't draw progress bars for files in torrents that have more than this many files def convert_to_files_tree_format(download_info): diff --git a/src/tribler-gui/tribler_gui/widgets/torrentfiletreewidget.py b/src/tribler-gui/tribler_gui/widgets/torrentfiletreewidget.py index e4465e52fc5..fbbb15f7b72 100644 --- a/src/tribler-gui/tribler_gui/widgets/torrentfiletreewidget.py +++ b/src/tribler-gui/tribler_gui/widgets/torrentfiletreewidget.py @@ -107,12 +107,12 @@ def subtree_progress_update(self, updates, force_update=False, draw_progress_bar self.progress_bytes = self.progress_bytes - old_bytes + new_bytes if child_changed or force_update: - if self.file_size and self.progress_bytes: + if self.progress_bytes is not None and self.file_size: self.file_progress = self.progress_bytes / self.file_size self.setText(PROGRESS_COL, f"{self.file_progress:.1%}") # ACHTUNG! This can be _very_ slow for torrents with lots of files, hence disabled by default - # To draw progress bars with acceptable performance we'd have to implement use QT's MVC stuff + # To draw progress bars with acceptable performance we'd have to use QT's MVC stuff if draw_progress_bars: bar_container, progress_bar = create_progress_bar_widget() progress_bar.setValue(int(self.file_progress * 100)) From a1c2523003781d887bb1450b0e031ce65bb20ce4 Mon Sep 17 00:00:00 2001 From: "V.G. Bulavintsev" Date: Sun, 26 Dec 2021 18:58:56 +0100 Subject: [PATCH 2/2] Fix QPoint-related divisions to integer --- .../tribler_gui/dialogs/dialogcontainer.py | 4 +- src/tribler-gui/tribler_gui/tribler_window.py | 2 +- .../widgets/downloadprogressbar.py | 5 +- .../tribler_gui/widgets/lazytableview.py | 14 ++-- .../widgets/tablecontentdelegate.py | 52 ++++++++------ .../tribler_gui/widgets/tableiconbuttons.py | 4 +- .../tribler_gui/widgets/tagslineedit.py | 70 +++++++++++++------ 7 files changed, 94 insertions(+), 57 deletions(-) diff --git a/src/tribler-gui/tribler_gui/dialogs/dialogcontainer.py b/src/tribler-gui/tribler_gui/dialogs/dialogcontainer.py index 2ff20cff3da..b24154b8d20 100644 --- a/src/tribler-gui/tribler_gui/dialogs/dialogcontainer.py +++ b/src/tribler-gui/tribler_gui/dialogs/dialogcontainer.py @@ -49,8 +49,8 @@ def on_main_window_resize(self): self.dialog_widget.setFixedWidth(self.width() - self.left_right_margin) self.dialog_widget.move( QPoint( - self.geometry().center().x() - self.dialog_widget.geometry().width() / 2, - self.geometry().center().y() - self.dialog_widget.geometry().height() / 2, + self.geometry().center().x() - self.dialog_widget.geometry().width() // 2, + self.geometry().center().y() - self.dialog_widget.geometry().height() // 2, ) ) except RuntimeError: diff --git a/src/tribler-gui/tribler_gui/tribler_window.py b/src/tribler-gui/tribler_gui/tribler_window.py index 88a73d6c521..f825bc82a11 100644 --- a/src/tribler-gui/tribler_gui/tribler_window.py +++ b/src/tribler-gui/tribler_gui/tribler_window.py @@ -315,7 +315,7 @@ def sigint_handler(*_): self.resize(size) center = QApplication.desktop().availableGeometry(self).center() - screen_center_pos = QPoint(center.x() - self.width() / 2, center.y() - self.height() / 2) + screen_center_pos = QPoint(center.x() - self.width() // 2, center.y() - self.height() // 2) pos = self.gui_settings.value("pos", screen_center_pos) if not QApplication.desktop().availableGeometry(self).intersects(QRect(pos, self.size())): diff --git a/src/tribler-gui/tribler_gui/widgets/downloadprogressbar.py b/src/tribler-gui/tribler_gui/widgets/downloadprogressbar.py index 44761a50315..04d9c742679 100644 --- a/src/tribler-gui/tribler_gui/widgets/downloadprogressbar.py +++ b/src/tribler-gui/tribler_gui/widgets/downloadprogressbar.py @@ -67,7 +67,8 @@ def paintEvent(self, _): for i in range(len(self.pieces)): if self.pieces[i]: painter.fillRect( - QRect(float(i) * piece_width, 0, math.ceil(piece_width), self.height()), QColor(230, 115, 0) + QRect(int(float(i) * piece_width), 0, math.ceil(piece_width), self.height()), + QColor(230, 115, 0), ) else: # We have more pieces than pixels, group pieces pieces_per_pixel = len(self.pieces) / float(self.width()) @@ -78,7 +79,7 @@ def paintEvent(self, _): for j in range(begin_piece, end_piece): piece_sum += self.pieces[j] qt_color = QColor() - qt_color.setHsl(26, 255, 128 + 127 * (1 - piece_sum / pieces_per_pixel)) + qt_color.setHsl(26, 255, 128 + 127 * (1 - piece_sum // pieces_per_pixel)) painter.fillRect(QRect(i, 0, 10, self.height()), qt_color) else: painter.fillRect(QRect(0, 0, self.width() * self.fraction, self.height()), QColor(230, 115, 0)) diff --git a/src/tribler-gui/tribler_gui/widgets/lazytableview.py b/src/tribler-gui/tribler_gui/widgets/lazytableview.py index 1909f81cc13..5039d4cde23 100644 --- a/src/tribler-gui/tribler_gui/widgets/lazytableview.py +++ b/src/tribler-gui/tribler_gui/widgets/lazytableview.py @@ -34,8 +34,8 @@ def update_position(self): if not parent_rect: return - x = parent_rect.width() / 2 - self.width() / 2 - y = parent_rect.height() / 2 - self.height() / 2 + x = parent_rect.width() // 2 - self.width() // 2 + y = parent_rect.height() // 2 - self.height() // 2 self.setGeometry(x, y, self.width(), self.height()) def resizeEvent(self, event): @@ -48,6 +48,7 @@ class TriblerContentTableView(QTableView): This table view is designed to support lazy loading. When the user reached the end of the table, it will ask the model for more items, and load them dynamically. """ + channel_clicked = pyqtSignal(dict) torrent_clicked = pyqtSignal(dict) torrent_doubleclicked = pyqtSignal(dict) @@ -265,8 +266,9 @@ def on_tags_edited(self, index, tags): def save_edited_tags(self, index: QModelIndex, tags: List[str]): data_item = self.model().data_items[index.row()] - TriblerNetworkRequest(f"tags/{data_item['infohash']}", - lambda _, ind=index, tgs=tags: self.on_tags_edited(ind, tgs), - raw_data=json.dumps({"tags": tags}), - method='PATCH', + TriblerNetworkRequest( + f"tags/{data_item['infohash']}", + lambda _, ind=index, tgs=tags: self.on_tags_edited(ind, tgs), + raw_data=json.dumps({"tags": tags}), + method='PATCH', ) diff --git a/src/tribler-gui/tribler_gui/widgets/tablecontentdelegate.py b/src/tribler-gui/tribler_gui/widgets/tablecontentdelegate.py index 462783bf5c0..cfe35160a1b 100644 --- a/src/tribler-gui/tribler_gui/widgets/tablecontentdelegate.py +++ b/src/tribler-gui/tribler_gui/widgets/tablecontentdelegate.py @@ -29,7 +29,8 @@ TAG_BORDER_COLOR, TAG_HEIGHT, TAG_HORIZONTAL_MARGIN, - TAG_TEXT_COLOR, TAG_TEXT_HORIZONTAL_PADDING, + TAG_TEXT_COLOR, + TAG_TEXT_HORIZONTAL_PADDING, TAG_TOP_MARGIN, WINDOWS, ) @@ -70,7 +71,7 @@ def draw_progress_bar(painter, rect, progress=0.0): r = rect x = r.x() + outer_margin - y = r.y() + (r.height() - bar_height) / 2 + y = r.y() + (r.height() - bar_height) // 2 h = bar_height # Draw background rect @@ -151,7 +152,7 @@ def __init__(self, parent=None): self.button_box = QRect() self.button_box_extended_border_ratio = float(1.0) - def get_bool_gui_setting(self, setting_name: str, default: bool=False): + def get_bool_gui_setting(self, setting_name: str, default: bool = False): """ Get a particular boolean GUI setting. The reason why this is a separate method is that there are some additional checks that need to be done @@ -207,8 +208,10 @@ def on_mouse_moved(self, pos, index): # Check if we hover over the 'edit tags' button new_hovering_state = False - if self.hover_index != self.no_index and \ - self.hover_index.column() == index.model().column_position[Column.NAME]: + if ( + self.hover_index != self.no_index + and self.hover_index.column() == index.model().column_position[Column.NAME] + ): if index in index.model().edit_tags_rects: rect = index.model().edit_tags_rects[index] if rect.contains(pos): @@ -228,9 +231,9 @@ def on_mouse_left(self) -> None: @staticmethod def split_rect_into_squares(r, buttons): x_border = 2 - side_size = min(r.width() / len(buttons), r.height() - x_border) - y_border = (r.height() - side_size) / 2 - x_start = r.left() + (r.width() - len(buttons) * side_size) / 2 # Center the squares horizontally + side_size = min(r.width() // len(buttons), r.height() - x_border) + y_border = (r.height() - side_size) // 2 + x_start = r.left() + (r.width() - len(buttons) * side_size) // 2 # Center the squares horizontally for n, button in enumerate(buttons): x = x_start + n * side_size y = r.top() + y_border @@ -281,7 +284,7 @@ def get_indicator_rect(rect): r = rect indicator_border = 1 indicator_side = (r.height() if r.width() > r.height() else r.width()) - indicator_border * 2 - y = r.top() + (r.height() - indicator_side) / 2 + y = r.top() + (r.height() - indicator_side) // 2 x = r.left() + indicator_border w = indicator_side h = indicator_side @@ -343,13 +346,17 @@ class TagsMixin: edit_tags_icon = QIcon(get_image_path("edit_white.png")) edit_tags_icon_hover = QIcon(get_image_path("edit_orange.png")) - def draw_title_and_tags(self, painter: QPainter, option: QStyleOptionViewItem, - index: QModelIndex, data_item: Dict) -> None: + def draw_title_and_tags( + self, painter: QPainter, option: QStyleOptionViewItem, index: QModelIndex, data_item: Dict + ) -> None: painter.setRenderHint(QPainter.Antialiasing, True) title_text_pos = option.rect.topLeft() painter.setPen(Qt.white) - painter.drawText(QRectF(title_text_pos.x() + 6, title_text_pos.y(), option.rect.width() - 6, 28), - Qt.AlignVCenter, data_item["name"]) + painter.drawText( + QRectF(title_text_pos.x() + 6, title_text_pos.y(), option.rect.width() - 6, 28), + Qt.AlignVCenter, + data_item["name"], + ) cur_tag_x = option.rect.x() + 6 cur_tag_y = option.rect.y() + TAG_TOP_MARGIN @@ -383,14 +390,15 @@ def draw_title_and_tags(self, painter: QPainter, option: QStyleOptionViewItem, painter.setPen(TAG_BORDER_COLOR) path = QPainterPath() rect = QRectF(cur_tag_x, cur_tag_y, tag_box_width, TAG_HEIGHT) - path.addRoundedRect(rect, TAG_HEIGHT / 2, TAG_HEIGHT / 2) + path.addRoundedRect(rect, TAG_HEIGHT // 2, TAG_HEIGHT // 2) painter.fillPath(path, TAG_BACKGROUND_COLOR) painter.drawPath(path) painter.setPen(Qt.white) - text_pos = rect.topLeft() + QPointF(TAG_TEXT_HORIZONTAL_PADDING, - painter.fontMetrics().ascent() + - ((rect.height() - painter.fontMetrics().height()) / 2) - 1) + text_pos = rect.topLeft() + QPointF( + TAG_TEXT_HORIZONTAL_PADDING, + painter.fontMetrics().ascent() + ((rect.height() - painter.fontMetrics().height()) // 2) - 1, + ) painter.setPen(TAG_TEXT_COLOR) painter.drawText(text_pos, tag_text) @@ -624,8 +632,8 @@ def paint(self, painter, rect, index, toggled=False, hover=False): painter.save() - x = rect.x() + (rect.width() - self._width) / 2 - y = rect.y() + (rect.height() - self._height) / 2 + x = rect.x() + (rect.width() - self._width) // 2 + y = rect.y() + (rect.height() - self._height) // 2 offset = self._end_offset[toggled]() p = painter @@ -720,8 +728,8 @@ def paint(self, painter, rect, index, hover=False): elif state == COMMIT_STATUS_UPDATED: icon = self.updated_icon - x = rect.left() + (rect.width() - self.w) / 2 - y = rect.top() + (rect.height() - self.h) / 2 + x = rect.left() + (rect.width() - self.w) // 2 + y = rect.top() + (rect.height() - self.h) // 2 icon_rect = QRect(x, y, self.w, self.h) icon.paint(painter, icon_rect) @@ -760,7 +768,7 @@ def paint(self, painter, rect, index, hover=False): painter.save() # Indicator ellipse rectangle - y = r.top() + (r.height() - self.indicator_side) / 2 + y = r.top() + (r.height() - self.indicator_side) // 2 x = r.left() + self.indicator_border w = self.indicator_side h = self.indicator_side diff --git a/src/tribler-gui/tribler_gui/widgets/tableiconbuttons.py b/src/tribler-gui/tribler_gui/widgets/tableiconbuttons.py index 46c98935d62..a126e7af2c5 100644 --- a/src/tribler-gui/tribler_gui/widgets/tableiconbuttons.py +++ b/src/tribler-gui/tribler_gui/widgets/tableiconbuttons.py @@ -29,8 +29,8 @@ def paint(self, painter, rect, _): # Update button activation rect from the drawing call self.rect = rect - x = rect.left() + (rect.width() - self.w) / 2 - y = rect.top() + (rect.height() - self.h) / 2 + x = rect.left() + (rect.width() - self.w) // 2 + y = rect.top() + (rect.height() - self.h) // 2 icon_rect = QRect(x, y, self.w, self.h) self.icon.paint(painter, icon_rect, mode=self.icon_mode) diff --git a/src/tribler-gui/tribler_gui/widgets/tagslineedit.py b/src/tribler-gui/tribler_gui/widgets/tagslineedit.py index 41542097d49..07750f6cc3d 100644 --- a/src/tribler-gui/tribler_gui/widgets/tagslineedit.py +++ b/src/tribler-gui/tribler_gui/widgets/tagslineedit.py @@ -2,12 +2,26 @@ from typing import List, Tuple from PyQt5.QtCore import QLineF, QPoint, QPointF, QRectF, QSizeF, QTimerEvent, Qt, pyqtSignal -from PyQt5.QtGui import QColor, QGuiApplication, QKeyEvent, QKeySequence, QMouseEvent, QPainter, QPainterPath, \ - QPalette, QTextLayout +from PyQt5.QtGui import ( + QColor, + QGuiApplication, + QKeyEvent, + QKeySequence, + QMouseEvent, + QPainter, + QPainterPath, + QPalette, + QTextLayout, +) from PyQt5.QtWidgets import QLineEdit, QStyle, QStyleOptionFrame -from tribler_gui.defs import EDIT_TAG_BACKGROUND_COLOR, EDIT_TAG_BORDER_COLOR, EDIT_TAG_TEXT_COLOR, TAG_HEIGHT, \ - TAG_TEXT_HORIZONTAL_PADDING +from tribler_gui.defs import ( + EDIT_TAG_BACKGROUND_COLOR, + EDIT_TAG_BORDER_COLOR, + EDIT_TAG_TEXT_COLOR, + TAG_HEIGHT, + TAG_TEXT_HORIZONTAL_PADDING, +) @dataclass @@ -28,6 +42,7 @@ class TagsLineEdit(QLineEdit): Represents a QLineEdit widget in which a user can type tags. Ported C++ implementation, see https://github.com/nicktrandafil/tags. """ + escape_pressed = pyqtSignal() enter_pressed = pyqtSignal() @@ -79,9 +94,9 @@ def in_cross_area(self, tag_index: int, point: QPoint) -> bool: """ Return whether the provided point is within the cross rect of the tag with a particular index. """ - return TagsLineEdit.compute_cross_rect(self.tags[tag_index].rect) \ - .adjusted(-2, 0, 0, 0) \ - .contains(point) and (not self.cursor_is_visible() or tag_index != self.editing_index) + return TagsLineEdit.compute_cross_rect(self.tags[tag_index].rect).adjusted(-2, 0, 0, 0).contains(point) and ( + not self.cursor_is_visible() or tag_index != self.editing_index + ) def resizeEvent(self, _) -> None: self.compute_tag_rects() @@ -173,13 +188,15 @@ def draw_tags(self, painter: QPainter, from_ind: int, to_ind: int) -> None: """ for ind in range(from_ind, to_ind): i_r = self.tags[ind].rect - text_pos = i_r.topLeft() + QPointF(TAG_TEXT_HORIZONTAL_PADDING, self.fontMetrics().ascent() + ( - (i_r.height() - self.fontMetrics().height()) / 2)) + text_pos = i_r.topLeft() + QPointF( + TAG_TEXT_HORIZONTAL_PADDING, + self.fontMetrics().ascent() + ((i_r.height() - self.fontMetrics().height()) // 2), + ) # draw rect painter.setPen(EDIT_TAG_BORDER_COLOR) path = QPainterPath() - path.addRoundedRect(i_r, TAG_HEIGHT / 2, TAG_HEIGHT / 2) + path.addRoundedRect(i_r, TAG_HEIGHT // 2, TAG_HEIGHT // 2) painter.fillPath(path, EDIT_TAG_BACKGROUND_COLOR) painter.drawPath(path) @@ -213,8 +230,11 @@ def compute_tag_rects(self) -> None: if self.cursor_is_visible(): self.compute_tag_rects_with_range(lt, TAG_HEIGHT, (0, self.editing_index)) - w = self.fontMetrics().horizontalAdvance( - self.text_layout.text()) + TAG_TEXT_HORIZONTAL_PADDING + TAG_TEXT_HORIZONTAL_PADDING + w = ( + self.fontMetrics().horizontalAdvance(self.text_layout.text()) + + TAG_TEXT_HORIZONTAL_PADDING + + TAG_TEXT_HORIZONTAL_PADDING + ) # Check if we overflow and if so, move the editor rect to the next line in the input field. if lt.x() + w >= r.topRight().x(): @@ -236,9 +256,12 @@ def compute_tag_rects_with_range(self, lt: QPoint, height: int, tags_range: Tupl i_width = self.fontMetrics().horizontalAdvance(self.tags[tag_index].text) i_r = QRectF(lt, QSizeF(i_width, height)) i_r.translate(TAG_TEXT_HORIZONTAL_PADDING, 0) - i_r.adjust(-TAG_TEXT_HORIZONTAL_PADDING, 0, - TAG_TEXT_HORIZONTAL_PADDING + TAG_CROSS_LEFT_PADDING + TAG_CROSS_RIGHT_PADDING + TAG_CROSS_WIDTH, - 0) + i_r.adjust( + -TAG_TEXT_HORIZONTAL_PADDING, + 0, + TAG_TEXT_HORIZONTAL_PADDING + TAG_CROSS_LEFT_PADDING + TAG_CROSS_RIGHT_PADDING + TAG_CROSS_WIDTH, + 0, + ) # Check if we overflow and if so, move this tag to the next line in the input field. input_rect = self.input_field_rect() @@ -255,7 +278,7 @@ def has_selection_active(self) -> bool: def remove_selection(self) -> None: self.cursor_ind = self.select_start txt = self.tags[self.editing_index].text - self.tags[self.editing_index].text = txt[:self.cursor_ind] + txt[self.cursor_ind + self.select_size:] + self.tags[self.editing_index].text = txt[: self.cursor_ind] + txt[self.cursor_ind + self.select_size :] self.deselectAll() def remove_backwards_character(self) -> None: @@ -264,7 +287,7 @@ def remove_backwards_character(self) -> None: else: self.cursor_ind -= 1 txt = self.tags[self.editing_index].text - txt = txt[:self.cursor_ind] + txt[self.cursor_ind + 1:] + txt = txt[: self.cursor_ind] + txt[self.cursor_ind + 1 :] self.tags[self.editing_index].text = txt def selectAll(self) -> None: @@ -362,8 +385,9 @@ def mousePressEvent(self, event: QMouseEvent) -> None: continue if self.editing_index == tag_index: - self.move_cursor(self.text_layout.lineAt(0).xToCursor( - (event.pos() - self.current_rect().topLeft()).x()), False) + self.move_cursor( + self.text_layout.lineAt(0).xToCursor((event.pos() - self.current_rect().topLeft()).x()), False + ) else: self.edit_tag(tag_index) @@ -416,8 +440,10 @@ def keyPressEvent(self, event: QKeyEvent) -> None: event.accept() elif event.key() == Qt.Key_End: - if self.cursor_ind == len(self.tags[self.editing_index].text) and \ - self.editing_index < len(self.tags) - 1: + if ( + self.cursor_ind == len(self.tags[self.editing_index].text) + and self.editing_index < len(self.tags) - 1 + ): self.edit_tag(len(self.tags) - 1) else: self.move_cursor(len(self.tags[self.editing_index].text), False) @@ -450,7 +476,7 @@ def keyPressEvent(self, event: QKeyEvent) -> None: if self.has_selection_active(): self.remove_selection() txt = self.tags[self.editing_index].text - txt = txt[:self.cursor_ind] + event.text().lower() + txt[self.cursor_ind:] + txt = txt[: self.cursor_ind] + event.text().lower() + txt[self.cursor_ind :] self.tags[self.editing_index].text = txt self.cursor_ind += len(event.text()) event.accept()