From e80a835dd3984408aa547743188aaf9bc877ecd0 Mon Sep 17 00:00:00 2001 From: John van de Wetering Date: Tue, 23 Jul 2024 22:53:15 +0200 Subject: [PATCH] Made previews only load once you first hover over the rewrite rule, cutting down on loading time (#339) * Made previews only load once you first hover over the rewrite rule * fixing types and slight formatting --------- Co-authored-by: Razin Shaikh --- zxlive/rewrite_action.py | 115 ++++++++++++++++++++++----------------- 1 file changed, 66 insertions(+), 49 deletions(-) diff --git a/zxlive/rewrite_action.py b/zxlive/rewrite_action.py index 5a245ee..5d520f0 100644 --- a/zxlive/rewrite_action.py +++ b/zxlive/rewrite_action.py @@ -2,15 +2,14 @@ import copy from dataclasses import dataclass, field -from typing import Callable, TYPE_CHECKING, Any, cast, Union +from typing import Callable, TYPE_CHECKING, Any, cast, Union, Optional from concurrent.futures import ThreadPoolExecutor import pyzx -from PySide6.QtCore import (Qt, QAbstractItemModel, QModelIndex, QPersistentModelIndex, +from PySide6.QtCore import (Qt, QAbstractItemModel, QModelIndex, QPersistentModelIndex, Signal, QObject, QMetaObject, QIODevice, QBuffer, QPoint, QPointF, QLineF) from PySide6.QtGui import QPixmap, QColor, QPen -from PySide6.QtWidgets import QGraphicsView, QGraphicsScene from .animations import make_animation @@ -34,7 +33,10 @@ class RewriteAction: matcher: Callable[[GraphT, Callable], list] rule: Callable[[GraphT, list], pyzx.rules.RewriteOutputType[VT, ET]] match_type: MatchType - tooltip: str + tooltip_str: str + picture_path: Optional[str] = field(default=None) + lhs_graph: Optional[GraphT] = field(default=None) + rhs_graph: Optional[GraphT] = field(default=None) # Whether the graph should be copied before trying to test whether it matches. # Needed if the matcher changes the graph. copy_first: bool = field(default=False) @@ -44,57 +46,21 @@ class RewriteAction: @classmethod def from_rewrite_data(cls, d: RewriteData) -> RewriteAction: - if display_setting.previews_show and ('picture' in d or 'custom_rule' in d): - if 'custom_rule' in d: - # We will create a custom tooltip picture representing the custom rewrite - graph_scene_left = GraphScene() - graph_scene_right = GraphScene() - graph_view_left = GraphView(graph_scene_left) - graph_view_left.draw_background_lines = False - graph_view_left.set_graph(d['lhs']) - graph_view_right = GraphView(graph_scene_right) - graph_view_right.draw_background_lines = False - graph_view_right.set_graph(d['rhs']) - graph_view_left.fit_view() - graph_view_right.fit_view() - graph_view_left.setSceneRect(graph_scene_left.itemsBoundingRect()) - graph_view_right.setSceneRect(graph_scene_right.itemsBoundingRect()) - lhs_size = graph_view_left.viewport().size() - rhs_size = graph_view_right.viewport().size() - # The picture needs to be wide enough to fit both of them and have some space for the = sign - pixmap = QPixmap(lhs_size.width()+rhs_size.width()+160,max(lhs_size.height(),rhs_size.height())) - pixmap.fill(QColor("#ffffff")) - graph_view_left.viewport().render(pixmap) - graph_view_right.viewport().render(pixmap,QPoint(lhs_size.width()+160,0)) - # We create a new scene to render the = sign - new_scene = GraphScene() - new_view = GraphView(new_scene) - new_view.draw_background_lines = False - new_scene.addLine(QLineF(QPointF(10,40),QPointF(80,40)),QPen(QColor("#000000"),8)) - new_scene.addLine(QLineF(QPointF(10,10),QPointF(80,10)),QPen(QColor("#000000"),8)) - new_view.setSceneRect(new_scene.itemsBoundingRect()) - new_view.viewport().render(pixmap,QPoint(lhs_size.width(),max(lhs_size.height(),rhs_size.height())/2-20)) - - buffer = QBuffer() - buffer.open(QIODevice.WriteOnly) - pixmap.save(buffer, "PNG", quality=100) - image = bytes(buffer.data().toBase64()).decode() - else: - pixmap = QPixmap() - pixmap.load(get_data("tooltips/"+d['picture'])) - buffer = QBuffer() - buffer.open(QIODevice.WriteOnly) - pixmap.save(buffer, "PNG", quality=100) - image = bytes(buffer.data().toBase64()).decode() - tooltip = ''.format(image) + d['tooltip'] + if 'custom_rule' in d: + picture_path = 'custom' + elif 'picture' in d: + picture_path = d['picture'] else: - tooltip = d['tooltip'] + picture_path = None return cls( name=d['text'], matcher=d['matcher'], rule=d['rule'], match_type=d['type'], - tooltip=tooltip, + tooltip_str=d['tooltip'], + picture_path = picture_path, + lhs_graph = d.get('lhs', None), + rhs_graph = d.get('rhs', None), copy_first=d.get('copy_first', False), returns_new_graph=d.get('returns_new_graph', False), ) @@ -140,6 +106,57 @@ def update_active(self, g: GraphT, verts: list[VT], edges: list[ET]) -> None: else self.matcher(g, lambda e: e in edges) ) + @property + def tooltip(self) -> str: + if self.picture_path is None: + return self.tooltip_str + if self.picture_path == 'custom': + # We will create a custom tooltip picture representing the custom rewrite + graph_scene_left = GraphScene() + graph_scene_right = GraphScene() + graph_view_left = GraphView(graph_scene_left) + graph_view_left.draw_background_lines = False + if self.lhs_graph is not None: + graph_view_left.set_graph(self.lhs_graph) + graph_view_right = GraphView(graph_scene_right) + graph_view_right.draw_background_lines = False + if self.rhs_graph is not None: + graph_view_right.set_graph(self.rhs_graph) + graph_view_left.fit_view() + graph_view_right.fit_view() + graph_view_left.setSceneRect(graph_scene_left.itemsBoundingRect()) + graph_view_right.setSceneRect(graph_scene_right.itemsBoundingRect()) + lhs_size = graph_view_left.viewport().size() + rhs_size = graph_view_right.viewport().size() + # The picture needs to be wide enough to fit both of them and have some space for the = sign + pixmap = QPixmap(lhs_size.width() + rhs_size.width() + 160, max(lhs_size.height(), rhs_size.height())) + pixmap.fill(QColor("#ffffff")) + graph_view_left.viewport().render(pixmap) + graph_view_right.viewport().render(pixmap, QPoint(lhs_size.width() + 160, 0)) + # We create a new scene to render the = sign + new_scene = GraphScene() + new_view = GraphView(new_scene) + new_view.draw_background_lines = False + new_scene.addLine(QLineF(QPointF(10,40), QPointF(80,40)), QPen(QColor("#000000"), 8)) + new_scene.addLine(QLineF(QPointF(10,10), QPointF(80,10)), QPen(QColor("#000000"), 8)) + new_view.setSceneRect(new_scene.itemsBoundingRect()) + new_view.viewport().render(pixmap, QPoint(lhs_size.width(), int(max(lhs_size.height(), rhs_size.height())/2 - 20))) + + buffer = QBuffer() + buffer.open(QIODevice.OpenModeFlag.WriteOnly) + pixmap.save(buffer, "PNG", quality=100) + image = bytes(buffer.data().toBase64()).decode() + else: + pixmap = QPixmap() + pixmap.load(get_data("tooltips/"+self.picture_path)) + buffer = QBuffer() + buffer.open(QIODevice.OpenModeFlag.WriteOnly) + pixmap.save(buffer, "PNG", quality=100) + image = bytes(buffer.data().toBase64()).decode() + self.tooltip_str = ''.format(image) + self.tooltip_str + self.picture_path = None + return self.tooltip_str + @dataclass class RewriteActionTree: