Skip to content

Commit

Permalink
refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
pedohorse committed Oct 25, 2024
1 parent a192e00 commit 705ea1c
Show file tree
Hide file tree
Showing 27 changed files with 144 additions and 107 deletions.
2 changes: 1 addition & 1 deletion src/lifeblood_viewer/create_task_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from PySide2.QtWidgets import QWidget, QDialog, QVBoxLayout, QHBoxLayout, QLineEdit, QLabel, QMessageBox, QSpinBox, QPushButton
from PySide2.QtCore import Slot, QSize

from typing import TYPE_CHECKING, Optional, Tuple, List, Set
from typing import TYPE_CHECKING, Optional, Tuple, List
if TYPE_CHECKING:
from .graphics_items import Task

Expand Down
19 changes: 9 additions & 10 deletions src/lifeblood_viewer/editor_scene_integration.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
from PySide2.QtCore import Qt, QTimer
from PySide2.QtWidgets import QWidget
from .code_editor.editor import StringParameterEditor
from .scene_data_controller import SceneDataController
from lifeblood.enums import InvocationState
from lifeblood.ui_protocol_data import InvocationLogData

from typing import Optional, TYPE_CHECKING
if TYPE_CHECKING:
from .graphics_scene_with_data_controller import QGraphicsImguiSceneWithDataController
from typing import Optional, Tuple


def fetch_and_open_log_viewer(scene: "QGraphicsImguiSceneWithDataController", invoc_id: int, parent_widget: QWidget, *, update_interval: Optional[float] = None):
def fetch_and_open_log_viewer(scene_data_controller: SceneDataController, invoc_id: int, parent_widget: QWidget, *, update_interval: Optional[float] = None):
if update_interval is None:
scene.fetch_log_run_callback(invoc_id, _open_log_viewer, parent_widget)
scene_data_controller.fetch_log_run_callback(invoc_id, _open_log_viewer, parent_widget)
else:
scene.fetch_log_run_callback(invoc_id, _open_log_viewer_with_update, (parent_widget, update_interval, invoc_id, scene))
scene_data_controller.fetch_log_run_callback(invoc_id, _open_log_viewer_with_update, (parent_widget, update_interval, invoc_id, scene_data_controller))


def _open_log_viewer(log, parent):
def _open_log_viewer(log: InvocationLogData, parent: QWidget):
hl = StringParameterEditor.SyntaxHighlight.LOG
wgt = StringParameterEditor(syntax_highlight=hl, parent=parent)
wgt.setAttribute(Qt.WA_DeleteOnClose, True)
Expand All @@ -26,8 +25,8 @@ def _open_log_viewer(log, parent):
wgt.show()


def _open_log_viewer_with_update(log, callback_data):
parent, update_interval, invoc_id, scene = callback_data
def _open_log_viewer_with_update(log, callback_data: Tuple[QWidget, float, int, SceneDataController]):
parent, update_interval, invoc_id, scene_data_controller = callback_data

hl = StringParameterEditor.SyntaxHighlight.LOG
wgt = StringParameterEditor(syntax_highlight=hl, parent=parent)
Expand All @@ -50,7 +49,7 @@ def _on_log_fetched(new_log: InvocationLogData, _):
update_timer.start() # restart timer

update_timer.timeout.connect(
lambda: scene.fetch_log_run_callback(
lambda: scene_data_controller.fetch_log_run_callback(
invoc_id,
_on_log_fetched
)
Expand Down
6 changes: 3 additions & 3 deletions src/lifeblood_viewer/graphics_items/graphics_items.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class TaskSortOrder(Enum):

class PseudoNode(BaseNode):
def __init__(self, my_node: "Node"):
super(Node.PseudoNode, self).__init__('_noname_')
super().__init__('_noname_')
self.__my_node = my_node

def _ui_changed(self, definition_changed=False):
Expand Down Expand Up @@ -108,10 +108,10 @@ def output_connections(self, outname) -> Set["NodeConnection"]:
raise RuntimeError(f'nodetype {self.__node_type} does not have output {outname}')
return {x for x in self.__connections if x.output() == (self, outname)}

def input_names(self) -> Tuple[str]:
def input_names(self) -> Tuple[str, ...]:
return tuple(self.__inputs) if self.__inputs else ()

def output_names(self) -> tuple[str]:
def output_names(self) -> Tuple[str, ...]:
return tuple(self.__outputs) if self.__outputs else ()

def input_nodes(self, inname: Optional[str] = None) -> Set["Node"]:
Expand Down
12 changes: 11 additions & 1 deletion src/lifeblood_viewer/graphics_items/graphics_scene_container.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from lifeblood import logging
from .graphics_scene_base import GraphicsSceneBase
from .graphics_items import Node, Task, NodeConnection
from PySide2.QtCore import QPointF

from types import MappingProxyType
from typing import Dict, Tuple, Mapping, Optional
from typing import Dict, Tuple, Mapping, Optional, Sequence

logger = logging.get_logger('viewer')

Expand Down Expand Up @@ -87,6 +88,15 @@ def clear(self):
self.__node_dict = {}
logger.debug('scene cleared')

#

def move_nodes(self, nodes_datas: Sequence[Tuple[Node, QPointF]]):
"""
move nodes
"""
for node, pos in nodes_datas:
node.setPos(pos)

# settings # TODO: move to a dedicated settings provider

def node_snapping_enabled(self):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from .node_decorator_base import NodeDecorator, NodeDecoratorFactoryBase
from .drawable_node import DrawableNode
from .drawable_node_with_snap_points import DrawableNodeWithSnapPoints

from ..graphics_scene_base import GraphicsSceneBase

from typing import Iterable, List, Optional, Tuple
from typing import Iterable, List


class DecoratedNode(DrawableNode):
class DecoratedNode(DrawableNodeWithSnapPoints):
def __init__(self, scene: GraphicsSceneBase, id: int, type: str, name: str, node_decorator_factories: Iterable[NodeDecoratorFactoryBase] = ()):
super().__init__(scene, id, type, name)

Expand Down
34 changes: 11 additions & 23 deletions src/lifeblood_viewer/graphics_items/pretty_items/drawable_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from lifeblood.enums import TaskState
from ..graphics_items import Node, Task
from ..graphics_scene_base import GraphicsSceneBase
from ..node_connection_snap_point import NodeConnSnapPoint
from .drawable_task import DrawableTask


Expand All @@ -23,7 +22,7 @@ class DrawableNode(Node):
def __init__(self, scene: GraphicsSceneBase, id: int, type: str, name: str):
super().__init__(scene, id, type, name)

self.__visual_tasks: List[Task] = []
self.__visual_tasks: List[DrawableTask] = []

# display
self.__hoverover_pos: Optional[QPointF] = None
Expand Down Expand Up @@ -98,7 +97,7 @@ def set_expanded(self, expanded: bool):
self.__pivot_y = 0
# self.setPos(self.pos() - QPointF(0, 225 * 0.5)) # TODO: modify painterpath getters to avoid moving nodes on expand

for i, task in enumerate(self.tasks()):
for i, task in enumerate(self.drawable_tasks()):
self.__make_task_child_with_position(task, *self.get_task_pos(task, i), animate=True)
self.item_updated()

Expand Down Expand Up @@ -138,27 +137,9 @@ def get_output_position(self, name: str = 'main', *, local: bool = False) -> QPo
local
)

def input_snap_points(self) -> List[NodeConnSnapPoint]:
# TODO: cache snap points, don't recalc them every time
if self.get_nodeui() is None:
return []
inputs = []
for input_name in self.get_nodeui().inputs_names():
inputs.append(NodeConnSnapPoint(self, input_name, True))
return inputs

def output_snap_points(self) -> List[NodeConnSnapPoint]:
# TODO: cache snap points, don't recalc them every time
if self.get_nodeui() is None:
return []
outputs = []
for output_name in self.get_nodeui().outputs_names():
outputs.append(NodeConnSnapPoint(self, output_name, False))
return outputs

# move animation

def get_task_pos(self, task: "Task", pos_id: int) -> Tuple[QPointF, int]:
def get_task_pos(self, task: DrawableTask, pos_id: int) -> Tuple[QPointF, int]:
rect = self._get_bodyshape().boundingRect()
x, y = rect.topLeft().toTuple()
w, h = rect.size().toTuple()
Expand All @@ -184,6 +165,12 @@ def __make_task_child_with_position(self, task: DrawableTask, pos: QPointF, laye
else:
task.set_task_position(self, pos, layer)

def drawable_tasks(self) -> Iterable[DrawableTask]:
for task in self.tasks():
if not isinstance(task, DrawableTask):
continue
yield task

def add_task(self, task: Task):
if not isinstance(task, DrawableTask):
return super().add_task(task)
Expand Down Expand Up @@ -215,7 +202,7 @@ def remove_tasks(self, tasks_to_remove: Iterable["Task"]):
tasks_to_remove = set(tasks_to_remove)
super().remove_tasks(tasks_to_remove)

self.__visual_tasks: List["Task"] = [None if x in tasks_to_remove else x for x in self.__visual_tasks]
self.__visual_tasks = [None if x in tasks_to_remove else x for x in self.__visual_tasks]
off = 0
for i, task in enumerate(self.__visual_tasks):
if task is None:
Expand All @@ -229,6 +216,7 @@ def remove_tasks(self, tasks_to_remove: Iterable["Task"]):

def remove_task(self, task_to_remove: "Task"):
super().remove_task(task_to_remove)
assert isinstance(task_to_remove, DrawableTask) # TODO: see TODO in add_task
task_pid = self.__visual_tasks.index(task_to_remove)

for i in range(task_pid, len(self.__visual_tasks) - 1):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from .drawable_node import DrawableNode
from .node_connection_snap_point import NodeConnSnapPoint
from ..graphics_scene_base import GraphicsSceneBase

from typing import List


class DrawableNodeWithSnapPoints(DrawableNode):
def __init__(self, scene: GraphicsSceneBase, id: int, type: str, name: str):
super().__init__(scene, id, type, name)

def input_snap_points(self) -> List[NodeConnSnapPoint]:
# TODO: cache snap points, don't recalc them every time
if self.get_nodeui() is None:
return []
inputs = []
for input_name in self.get_nodeui().inputs_names():
inputs.append(NodeConnSnapPoint(self, input_name, True))
return inputs

def output_snap_points(self) -> List[NodeConnSnapPoint]:
# TODO: cache snap points, don't recalc them every time
if self.get_nodeui() is None:
return []
outputs = []
for output_name in self.get_nodeui().outputs_names():
outputs.append(NodeConnSnapPoint(self, output_name, False))
return outputs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from ..graphics_items import Node, Task
from ..graphics_scene_container import GraphicsSceneWithNodesAndTasks


from PySide2.QtCore import QAbstractAnimation, Slot, QPointF, QRectF, QSizeF, QSequentialAnimationGroup
from PySide2.QtGui import QBrush, QColor, QPainter, QPainterPath, QPen
from PySide2.QtWidgets import QGraphicsItem, QStyleOptionGraphicsItem, QWidget
Expand Down Expand Up @@ -255,4 +254,4 @@ def hoverMoveEvent(self, event):

def hoverLeaveEvent(self, event):
self.__hoverover_pos = None
self.update()
self.update()
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from PySide2.QtWidgets import QWidget, QStyleOptionGraphicsItem
from PySide2.QtCore import Qt, Slot, QRectF, QPointF
from PySide2.QtCore import Qt, QRectF, QPointF
from PySide2.QtGui import QPainterPath, QPainter, QBrush, QPen, QColor
from typing import Optional

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
from lifeblood_viewer.graphics_items import Node
from ...utils import call_later
from ..decorated_node import DecoratedNode
from ..drawable_node_with_snap_points import DrawableNodeWithSnapPoints
from ..node_connection_create_preview import NodeConnectionCreatePreview
from ..node_connection_snap_point import NodeConnSnapPoint
from ...graphics_scene_container import GraphicsSceneWithNodesAndTasks
from ...node_connection_snap_point import NodeConnSnapPoint

from lifeblood_viewer.scene_data_controller import SceneDataController
from lifeblood_viewer.code_editor.editor import StringParameterEditor
Expand Down Expand Up @@ -292,7 +293,7 @@ def mousePressEvent(self, event: QGraphicsSceneMouseEvent):
for input in self.input_names():
inpos = self.get_input_position(input)
if QPointF.dotProduct(inpos - pos, inpos - pos) <= r2 and wgt.request_ui_focus(self):
snap_points = [y for x in self.__scene_container.nodes() if x != self for y in x.output_snap_points()]
snap_points = [y for x in self.__scene_container.nodes() if x != self and isinstance(x, DrawableNodeWithSnapPoints) for y in x.output_snap_points()]
displayer = NodeConnectionCreatePreview(None, self, '', input, snap_points, 15, self._ui_interactor_finished)
self.scene().addItem(displayer)
self.__ui_interactor = displayer
Expand All @@ -305,7 +306,7 @@ def mousePressEvent(self, event: QGraphicsSceneMouseEvent):
for output in self.output_names():
outpos = self.get_output_position(output)
if QPointF.dotProduct(outpos - pos, outpos - pos) <= r2 and wgt.request_ui_focus(self):
snap_points = [y for x in self.__scene_container.nodes() if x != self for y in x.input_snap_points()]
snap_points = [y for x in self.__scene_container.nodes() if x != self and isinstance(x, DrawableNodeWithSnapPoints) for y in x.input_snap_points()]
displayer = NodeConnectionCreatePreview(self, None, output, '', snap_points, 15, self._ui_interactor_finished)
self.scene().addItem(displayer)
self.__ui_interactor = displayer
Expand Down Expand Up @@ -370,14 +371,21 @@ def mouseReleaseEvent(self, event: QGraphicsSceneMouseEvent):
# return
super().mouseReleaseEvent(event)
if self.__move_start_position is not None:
if self.__scene_container.node_snapping_enabled():
for node in self.__move_start_selection:
pos = node.pos()
# calc final pos if snapping is involved,
# then reset nodes to orig position and call scene's move_nodes so that proper op is generated
nodes_final_positions = []
for node in self.__move_start_selection:
pos = node.pos()
if self.__scene_container.node_snapping_enabled():
snapx = node.base_width / 4
snapy = node.base_height / 4
node.setPos(round(pos.x() / snapx) * snapx,
round(pos.y() / snapy) * snapy)
self.scene()._nodes_were_moved([(node, node.__move_start_position) for node in self.__move_start_selection])
pos = QPointF(round(pos.x() / snapx) * snapx,
round(pos.y() / snapy) * snapy)
nodes_final_positions.append((node, pos))
node.setPos(node.__move_start_position)

self.__scene_container.move_nodes(nodes_final_positions)
#self.scene()._nodes_were_moved([(node, node.__move_start_position) for node in self.__move_start_selection])
for node in self.__move_start_selection:
node.__move_start_position = None

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from math import sqrt
from lifeblood import logging
from ...graphics_items import Node, NodeConnection
from ...graphics_items import NodeConnection
from ...utils import call_later, length2
from ..node_connection_create_preview import NodeConnectionCreatePreview
from ..node_connection_snap_point import NodeConnSnapPoint
from ..drawable_node_with_snap_points import DrawableNodeWithSnapPoints
from ...graphics_scene_container import GraphicsSceneWithNodesAndTasks
from ...node_connection_snap_point import NodeConnSnapPoint

from lifeblood_viewer.scene_data_controller import SceneDataController
from lifeblood_viewer.graphics_scene_viewing_widget import GraphicsSceneViewingWidgetBase
Expand All @@ -13,14 +14,13 @@
from PySide2.QtGui import QColor, QPainter, QPainterPath, QPainterPathStroker, QPen
from PySide2.QtWidgets import QGraphicsItem, QStyleOptionGraphicsItem, QGraphicsSceneMouseEvent, QWidget

from typing import Optional

from typing import Optional, Tuple

logger = logging.get_logger('viewer')


class SceneNodeConnection(NodeConnection):
def __init__(self, scene: GraphicsSceneWithNodesAndTasks, id: int, nodeout: Node, nodein: Node, outname: str, inname: str, data_controller: SceneDataController):
def __init__(self, scene: GraphicsSceneWithNodesAndTasks, id: int, nodeout: DrawableNodeWithSnapPoints, nodein: DrawableNodeWithSnapPoints, outname: str, inname: str, data_controller: SceneDataController):
super().__init__(scene, id, nodeout, nodein, outname, inname)
self.__scene_container = scene
self.__data_controller: SceneDataController = data_controller
Expand Down Expand Up @@ -57,6 +57,16 @@ def __init__(self, scene: GraphicsSceneWithNodesAndTasks, id: int, nodeout: Node
# to ensure correct interaction
self.__ui_widget: Optional[GraphicsSceneViewingWidgetBase] = None

def output(self) -> Tuple[DrawableNodeWithSnapPoints, str]:
node, name = super().output()
assert isinstance(node, DrawableNodeWithSnapPoints)
return node, name

def input(self) -> Tuple[DrawableNodeWithSnapPoints, str]:
node, name = super().input()
assert isinstance(node, DrawableNodeWithSnapPoints)
return node, name

def distance_to_point(self, pos: QPointF):
"""
returns approx distance to a given point
Expand Down Expand Up @@ -202,9 +212,9 @@ def post_mousePressEvent(self, event: QGraphicsSceneMouseEvent):

output_picked = d02 < d12
if output_picked:
snap_points = [y for x in self.__scene_container.nodes() if x != innode for y in x.output_snap_points()]
snap_points = [y for x in self.__scene_container.nodes() if x != innode and isinstance(x, DrawableNodeWithSnapPoints) for y in x.output_snap_points()]
else:
snap_points = [y for x in self.__scene_container.nodes() if x != outnode for y in x.input_snap_points()]
snap_points = [y for x in self.__scene_container.nodes() if x != outnode and isinstance(x, DrawableNodeWithSnapPoints) for y in x.input_snap_points()]
self.__ui_interactor = NodeConnectionCreatePreview(None if output_picked else outnode,
innode if output_picked else None,
outname, inname,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def set_groups(self, groups: Set[str]):
def refresh_ui(self):
"""
unlike update - this method actually queries new task ui status
if task is not selected or not watched- does nothing
if task is not selected or not watched - does nothing
:return:
"""
if not self.isSelected() and len(self.item_watchers()) == 0:
Expand Down Expand Up @@ -184,7 +184,7 @@ def draw_imgui_elements(self, drawing_widget):
else:
if invoc_log.stdout:
if imgui.button(f'open in viewer##{invoc_id}'):
fetch_and_open_log_viewer(self.scene(), invoc_id, drawing_widget, update_interval=None if invoc_log.invocation_state == InvocationState.FINISHED else 5)
fetch_and_open_log_viewer(self.__data_controller, invoc_id, drawing_widget, update_interval=None if invoc_log.invocation_state == InvocationState.FINISHED else 5)

imgui.text_unformatted(invoc_log.stdout or '...nothing here...')
if invoc_log.invocation_state == InvocationState.IN_PROGRESS:
Expand Down
Loading

0 comments on commit 705ea1c

Please sign in to comment.