diff --git a/ryven-editor/ryven/gui/code_editor/CodePreviewWidget.py b/ryven-editor/ryven/gui/code_editor/CodePreviewWidget.py index aee8e04c..8f412151 100644 --- a/ryven-editor/ryven/gui/code_editor/CodePreviewWidget.py +++ b/ryven-editor/ryven/gui/code_editor/CodePreviewWidget.py @@ -2,15 +2,46 @@ from typing import Type, Optional from qtpy.QtCore import Qt -from qtpy.QtWidgets import QWidget, QHBoxLayout, QVBoxLayout, QRadioButton, QLabel, QCheckBox, QGridLayout, \ +from qtpy.QtWidgets import ( + QWidget, + QHBoxLayout, + QVBoxLayout, + QRadioButton, + QLabel, + QCheckBox, + QGridLayout, QPushButton +) from ryvencore import Node from ryven.gui.code_editor.EditSrcCodeInfoDialog import EditSrcCodeInfoDialog from ryven.gui.code_editor.CodeEditorWidget import CodeEditorWidget from ryven.gui.code_editor.SourceCodeUpdater import SrcCodeUpdater -from ryven.gui.code_editor.codes_storage import class_codes, mod_codes, modif_codes, NodeTypeCodes, \ - Inspectable, NodeInspectable, MainWidgetInspectable, CustomInputWidgetInspectable +from ryven.gui.code_editor.codes_storage import ( + class_codes, + mod_codes, + modif_codes, + NodeTypeCodes, + Inspectable, + NodeInspectable, + MainWidgetInspectable, + CustomInputWidgetInspectable, + load_src_code, +) + + +class LoadSrcCodeButton(QPushButton): + def __init__(self): + super().__init__('load source code') + self._node = None + + @property + def node(self): + return self._node + + @node.setter + def node(self, node): + self._node = node class LinkedRadioButton(QRadioButton): @@ -40,6 +71,13 @@ def setup_ui(self): secondary_layout = QHBoxLayout() + # load source code button + self.load_code_button = LoadSrcCodeButton() + self.load_code_button.setProperty('class', 'small_button') + secondary_layout.addWidget(self.load_code_button) + self.load_code_button.hide() + self.load_code_button.clicked.connect(self._load_code_button_clicked) + # class radio buttons widget self.class_selection_layout = QHBoxLayout() # QGridLayout() @@ -96,18 +134,23 @@ def _set_node(self, node: Optional[Node]): self.reset_code_button.setEnabled(False) self.text_edit.set_code('') self._clear_class_layout() - return + else: + if class_codes.get(node.__class__) is None: + # source code not loaded yet + self.load_code_button.node = node + self.load_code_button.show() + self._clear_class_layout() + self._update_code(NodeInspectable(node, 'source not loaded')) + else: + self._process_node_src(node) + def _process_node_src(self, node: Node): self._rebuild_class_selection(node) - code = class_codes[node.__class__].node_cls - if self.edits_enabled and node in modif_codes: code = modif_codes[node] - self._update_code(NodeInspectable(node, code)) - def _update_code(self, insp: Inspectable): if self.edits_enabled: self._disable_editing() @@ -122,6 +165,7 @@ def _update_code(self, insp: Inspectable): def _rebuild_class_selection(self, node: Node): + self.load_code_button.hide() self._clear_class_layout() self.radio_buttons.clear() @@ -168,6 +212,12 @@ def _clear_class_layout(self): widget = item.widget() widget.hide() self.class_selection_layout.removeItem(item) + + def _load_code_button_clicked(self): + node: Node = self.sender().node + load_src_code(node.__class__) + self.load_code_button.hide() + self._process_node_src(node) def _update_radio_buttons_edit_status(self): """Draws radio buttons referring to modified objects bold.""" diff --git a/ryven-editor/ryven/gui/code_editor/codes_storage.py b/ryven-editor/ryven/gui/code_editor/codes_storage.py index b3ffc0f4..073ec8a9 100644 --- a/ryven-editor/ryven/gui/code_editor/codes_storage.py +++ b/ryven-editor/ryven/gui/code_editor/codes_storage.py @@ -9,9 +9,17 @@ def register_node_type(n: Type[Node]): """ - Inspects and stores source code of a node type. + Registers a node type and loads its source code directly if deferred + source code loading is disabled. """ + if not instance.defer_code_loading: + load_src_code(n) + else: + class_codes[n] = None + + +def load_src_code(n: Type[Node]): has_gui = hasattr(n, 'GUI') # check if node type has custom gui has_mw = has_gui and n.GUI.main_widget_class is not None diff --git a/ryven-editor/ryven/main/args_parser.py b/ryven-editor/ryven/main/args_parser.py index 3ec94d6c..c967569c 100644 --- a/ryven-editor/ryven/main/args_parser.py +++ b/ryven-editor/ryven/main/args_parser.py @@ -208,6 +208,16 @@ def parse_sys_args(just_defaults=False) -> Config: • When enabled, Ryven might consume much more memory than usual ''') + parser.add_argument( + '--defer-code-loading', + action='store_true', + dest='defer_code_loading', + help=f''' + • When using deferred code loading, Ryven will load the source code of\\ + nodes only once the user wants to inspect it.\\ + • Deferred code loading decreases package loading time.\\ + ''') + # Project configuration group = parser.add_argument_group('project configuration') diff --git a/ryven-editor/ryven/main/config.py b/ryven-editor/ryven/main/config.py index 6e415d7e..036e1687 100644 --- a/ryven-editor/ryven/main/config.py +++ b/ryven-editor/ryven/main/config.py @@ -39,6 +39,7 @@ class Config: window_title: str = 'Ryven' qt_api: str = 'pyside2' src_code_edits_enabled: bool = False + defer_code_loading: bool = False @staticmethod def get_available_window_themes() -> Set[str]: diff --git a/ryven-editor/ryven/main/packages/gui_env.py b/ryven-editor/ryven/main/packages/gui_env.py index 0ff7d226..50fdd3f0 100644 --- a/ryven-editor/ryven/main/packages/gui_env.py +++ b/ryven-editor/ryven/main/packages/gui_env.py @@ -25,7 +25,6 @@ class GuiClassesRegistry: """ exported_guis = [] - exported_guis_sources: [[str]] = [] class GuiClassesContainer: @@ -43,10 +42,6 @@ def export_guis(guis: [Type[NodeGUI]]): setattr(gcc, w.__name__, w) GuiClassesRegistry.exported_guis.append(gcc) - # get sources - gui_sources = [inspect.getsource(g) for g in guis] - GuiClassesRegistry.exported_guis_sources.append(gui_sources) - def node_gui(node_cls: Type[Node]): """ @@ -64,9 +59,6 @@ def register_gui(gui_cls: Type[NodeGUI]): node_cls.GUI = gui_cls __explicit_nodes.add(node_cls) InfoMsgs.write(f"Registered node gui: {node_cls} for {gui_cls}") - # legacy - GuiClassesRegistry.exported_guis.append(gui_cls) - GuiClassesRegistry.exported_guis_sources.append(inspect.getsource(gui_cls)) return gui_cls return register_gui