From 839069f60cb76ee63df757c6c14e6bd37d57ff1a Mon Sep 17 00:00:00 2001 From: "V.G. Bulavintsev" Date: Fri, 24 Dec 2021 23:00:47 +0100 Subject: [PATCH] Request to Core on tooltip --- src/pyipv8 | 2 +- .../db/orm_bindings/channel_node.py | 10 ++- .../db/orm_bindings/collection_node.py | 5 +- .../db/orm_bindings/metadata_node.py | 11 +--- .../restapi/metadata_endpoint.py | 11 ++-- .../restapi/metadata_endpoint_base.py | 1 + .../tribler_gui/widgets/clickabletooltip.py | 61 ++++++++++++++++--- .../tribler_gui/widgets/tablecontentmodel.py | 8 +-- 8 files changed, 71 insertions(+), 38 deletions(-) diff --git a/src/pyipv8 b/src/pyipv8 index cb4188ca558..465590da01d 160000 --- a/src/pyipv8 +++ b/src/pyipv8 @@ -1 +1 @@ -Subproject commit cb4188ca558b2328550dd3f7a0e34cabcb5b9ea7 +Subproject commit 465590da01d0023235c118648847e67d753c362e diff --git a/src/tribler-core/tribler_core/components/metadata_store/db/orm_bindings/channel_node.py b/src/tribler-core/tribler_core/components/metadata_store/db/orm_bindings/channel_node.py index 67e3b5513d0..62e12b2d522 100644 --- a/src/tribler-core/tribler_core/components/metadata_store/db/orm_bindings/channel_node.py +++ b/src/tribler-core/tribler_core/components/metadata_store/db/orm_bindings/channel_node.py @@ -299,7 +299,7 @@ def make_copy(self, tgt_parent_id, attributes_override=None): dst_dict.update({"origin_id": tgt_parent_id, "status": NEW}) return self.__class__(**dst_dict) - def to_simple_dict(self): + def to_simple_dict(self, include_path=False): """ Return a basic dictionary with information about the node """ @@ -310,6 +310,14 @@ def to_simple_dict(self): "public_key": hexlify(self.public_key), "status": self.status, } + if include_path: + parent_nodes = self.get_parent_nodes()[:-1] + simple_dict.update( + { + "parents_path_text": list(p.title for p in parent_nodes), + "parents_path_ids": list(p.id_ for p in parent_nodes) + } + ) return simple_dict diff --git a/src/tribler-core/tribler_core/components/metadata_store/db/orm_bindings/collection_node.py b/src/tribler-core/tribler_core/components/metadata_store/db/orm_bindings/collection_node.py index 4c61929a118..5bb0d830319 100644 --- a/src/tribler-core/tribler_core/components/metadata_store/db/orm_bindings/collection_node.py +++ b/src/tribler-core/tribler_core/components/metadata_store/db/orm_bindings/collection_node.py @@ -26,7 +26,6 @@ ) from tribler_core.utilities.utilities import random_infohash - # pylint: disable=too-many-statements @@ -67,8 +66,8 @@ def state(self): return CHANNEL_STATE.PREVIEW.value - def to_simple_dict(self): - result = super().to_simple_dict() + def to_simple_dict(self, **kwargs): + result = super().to_simple_dict(**kwargs) result.update( { "torrents": self.num_entries, diff --git a/src/tribler-core/tribler_core/components/metadata_store/db/orm_bindings/metadata_node.py b/src/tribler-core/tribler_core/components/metadata_store/db/orm_bindings/metadata_node.py index 22010974617..1c65cd16080 100644 --- a/src/tribler-core/tribler_core/components/metadata_store/db/orm_bindings/metadata_node.py +++ b/src/tribler-core/tribler_core/components/metadata_store/db/orm_bindings/metadata_node.py @@ -29,7 +29,7 @@ class MetadataNode(db.ChannelNode): ][1:] nonpersonal_attributes = db.ChannelNode.nonpersonal_attributes + ('title', 'tags') - def to_simple_dict(self, include_path=False, **kwargs): + def to_simple_dict(self, **kwargs): """ Return a basic dictionary with information about the channel. """ @@ -38,17 +38,8 @@ def to_simple_dict(self, include_path=False, **kwargs): { "name": self.title, "category": self.tags, - "parents_path_text": list(p.title for p in self.get_parent_nodes())[:-1] } ) - if include_path: - parent_nodes = self.get_parent_nodes()[:-1] - simple_dict.update( - { - "parents_path_text": list(p.title for p in parent_nodes), - "parents_path_ids": list(p.int for p in parent_nodes) - } - ) return simple_dict diff --git a/src/tribler-core/tribler_core/components/metadata_store/restapi/metadata_endpoint.py b/src/tribler-core/tribler_core/components/metadata_store/restapi/metadata_endpoint.py index 6374565d697..e63ffc40a8a 100644 --- a/src/tribler-core/tribler_core/components/metadata_store/restapi/metadata_endpoint.py +++ b/src/tribler-core/tribler_core/components/metadata_store/restapi/metadata_endpoint.py @@ -65,7 +65,7 @@ def setup_routes(self): web.delete('', self.delete_channel_entries), web.get('/torrents/{infohash}/health', self.get_torrent_health), web.patch(r'/{public_key:\w*}/{id:\w*}', self.update_channel_entry), - web.get(r'/{public_key:\w*}/{id:\w*}', self.get_channel_entries), + web.get(r'/{public_key:\w*}/{id:\w*}', self.get_channel_entry), ] ) @@ -158,18 +158,17 @@ async def update_channel_entry(self, request): @docs( tags=['Metadata'], - summary='Get channel entries.', - responses={200: {'description': 'Returns a list of entries'}, HTTP_NOT_FOUND: {'schema': HandledErrorSchema}}, + summary='Get channel entry.', + responses={200: {'description': 'Returns the entry'}, HTTP_NOT_FOUND: {'schema': HandledErrorSchema}}, ) - async def get_channel_entries(self, request): + async def get_channel_entry(self, request): public_key = unhexlify(request.match_info['public_key']) id_ = request.match_info['id'] with db_session: entry = self.mds.ChannelNode.get(public_key=public_key, id_=id_) if entry: - # TODO: handle costly attributes in a more graceful and generic way for all types of metadata - entry_dict = entry.to_simple_dict() + entry_dict = entry.to_simple_dict(include_path=True) else: return RESTResponse({"error": "entry not found in database"}, status=HTTP_NOT_FOUND) diff --git a/src/tribler-core/tribler_core/components/metadata_store/restapi/metadata_endpoint_base.py b/src/tribler-core/tribler_core/components/metadata_store/restapi/metadata_endpoint_base.py index f4140293c37..946aa44077f 100644 --- a/src/tribler-core/tribler_core/components/metadata_store/restapi/metadata_endpoint_base.py +++ b/src/tribler-core/tribler_core/components/metadata_store/restapi/metadata_endpoint_base.py @@ -12,6 +12,7 @@ # This dict is used to translate JSON fields into the columns used in Pony for _sorting_. # id_ is not in the list because there is not index on it, so we never really want to sort on it. json2pony_columns = { + 'public_key': 'public_key', 'category': "tags", 'name': "title", 'size': "size", diff --git a/src/tribler-gui/tribler_gui/widgets/clickabletooltip.py b/src/tribler-gui/tribler_gui/widgets/clickabletooltip.py index 10557ef13c4..8971b29581e 100644 --- a/src/tribler-gui/tribler_gui/widgets/clickabletooltip.py +++ b/src/tribler-gui/tribler_gui/widgets/clickabletooltip.py @@ -1,6 +1,9 @@ from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtCore import QObject, Qt +from tribler_gui.tribler_request_manager import TriblerNetworkRequest +from tribler_gui.widgets.tablecontentmodel import Column, get_user_name_cached + """ Adapted for QTableView from @@ -228,6 +231,45 @@ class ClickableTooltipFilter(QObject): def toolTipLinkClicked(self, url): print(url) + def show_author_tooltip(self, table_view, index, item): + def on_details_received(response): + if not response: + return + item.update(response) + print("BLA", response) + + pk = item.get('public_key', "0") + user_name = get_user_name_cached(pk) + tooltip_txt = user_name + if path := item.get('parents_path_text', []): + tooltip_txt += "\n" + " / ".join(str(p) for p in path) + tooltip_txt += "\n" + 'This is link {c}' + + self.show_tooltip(table_view, index, tooltip_txt) + + if "parents_path_text" not in item and "parents_path_ids" not in item: + TriblerNetworkRequest( + f"metadata/{item['public_key']}/{item['id']}", + on_details_received, + method='GET', + ) + else: + on_details_received(item) + + def show_tooltip(self, table_view, index, txt): + + if not txt: + if ClickableTooltip.instance() is not None: + ClickableTooltip.instance().hide() + + if txt is not None: + print("SHOWN") + rect = table_view.visualRect(index) + toolTip = ClickableTooltip.showText(QtGui.QCursor.pos(), txt, parent=table_view, rect=rect) + if toolTip is not None: + toolTip.linkActivated.connect(self.toolTipLinkClicked) + return True + def eventFilter(self, source, event): if event.type() == QtCore.QEvent.ToolTip: print("TT EVENT") @@ -239,17 +281,16 @@ def eventFilter(self, source, event): index = table_view.indexAt(pos) if not index.isValid(): return False - txt = table_view.model().data(index, Qt.ToolTipRole) - if not txt: - if ClickableTooltip.instance() is not None: - ClickableTooltip.instance().hide() + model = table_view.model() + column_type = model.columns_shown[index.column()] + if column_type == Column.AUTHOR: + item = table_view.model().data_items[index.row()] + self.show_author_tooltip(table_view, index, item) + return True - if txt is not None: - print("SHOWN") - rect = table_view.visualRect(index) - toolTip = ClickableTooltip.showText(QtGui.QCursor.pos(), txt, parent=table_view, rect=rect) - toolTip.linkActivated.connect(self.toolTipLinkClicked) + txt = table_view.model().data(index, Qt.ToolTipRole) + self.show_tooltip(table_view, index, txt) + return True - return True return super().eventFilter(source, event) diff --git a/src/tribler-gui/tribler_gui/widgets/tablecontentmodel.py b/src/tribler-gui/tribler_gui/widgets/tablecontentmodel.py index b1fa6edf7c7..6029aa96561 100644 --- a/src/tribler-gui/tribler_gui/widgets/tablecontentmodel.py +++ b/src/tribler-gui/tribler_gui/widgets/tablecontentmodel.py @@ -451,13 +451,7 @@ def item_txt(self, index, role, is_editing: bool = False): if item.get('public_key') == "": return "Anonymous author" - pk = item.get('public_key', "0") - user_name = get_user_name_cached(pk) - tooltip_txt = user_name - if path := item.get('parents_path_text', []): - tooltip_txt += "\n" + " / ".join(str(p) for p in path) - tooltip_txt += "\n" + 'This is link {c}' - return tooltip_txt + return "PLACEHOLDER FOR AUTHOR TOOLTIP" # The 'name' column is special in a sense that we want to draw the title and tags ourselves. # At the same time, we want to name this column to not break the renaming of torrent files, hence this check.