Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inspector, Multi-Selection, Undo and more #176

Merged
merged 56 commits into from
Dec 5, 2023
Merged
Show file tree
Hide file tree
Changes from 52 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
3b4b3e9
Inspector UI
HeftyCoder Nov 26, 2023
f5f22d6
Implemented Selection Undo
HeftyCoder Nov 27, 2023
71202e3
Improved Inspector GUI
HeftyCoder Nov 27, 2023
0e0043f
Delegate_Command
HeftyCoder Nov 27, 2023
e953f09
Update InspectorGUI.py
HeftyCoder Nov 29, 2023
20e0c6e
Animated Path
HeftyCoder Nov 29, 2023
accb95b
QoL
HeftyCoder Nov 30, 2023
bf51201
Update FlowTheme.py
HeftyCoder Nov 30, 2023
d820afe
QoL and bug fixes
HeftyCoder Nov 30, 2023
e3c51d2
Undo History View [WIP]
HeftyCoder Dec 1, 2023
11779d0
Undo History Complete
HeftyCoder Dec 1, 2023
c710a03
HTML to inspect node metadata
HeftyCoder Dec 1, 2023
712e9c0
Fixed View performance
HeftyCoder Dec 1, 2023
ad4cae2
Example Inspector [Traits] and Connection Animation [WIP]
HeftyCoder Dec 1, 2023
8122559
Connection Animation [Complete]
HeftyCoder Dec 2, 2023
49824b6
Implemented Flow View save / load
HeftyCoder Dec 2, 2023
d4a0d6e
Update ConnectionItem.py
HeftyCoder Dec 2, 2023
1679834
Update FlowCommands.py
HeftyCoder Dec 2, 2023
0811f7a
Update GUIBase.py
HeftyCoder Dec 2, 2023
6b77e91
Merge remote-tracking branch 'upstream/master'
HeftyCoder Dec 3, 2023
6dcf8ad
Update StartupDialog.py
HeftyCoder Dec 3, 2023
716582a
Update InspectorGUI.py
HeftyCoder Dec 3, 2023
ea6e52f
Update StartupDialog.py
HeftyCoder Dec 3, 2023
2dd7871
Efficient Nested Tree View
HeftyCoder Dec 4, 2023
9cd6f2d
Update NodeListWidget.py
HeftyCoder Dec 4, 2023
43de062
Update NodeListWidget.py
HeftyCoder Dec 4, 2023
c0899d3
Removed traits inspector example
HeftyCoder Dec 4, 2023
e67e06b
Last Fixes
HeftyCoder Dec 4, 2023
e08369d
Fixes
HeftyCoder Dec 4, 2023
8b4f4a3
rework inspector mechanism
leon-thomm Dec 4, 2023
4fc4dd6
improve flow commands clarity
leon-thomm Dec 4, 2023
808d601
unconstrained ryven package nesting
leon-thomm Dec 4, 2023
970f6d4
add serialization for inspector widgets
leon-thomm Dec 4, 2023
0a128c2
add missing inspector widget load() call
leon-thomm Dec 4, 2023
1e468ea
Minimum width for tab bar in flow ui
HeftyCoder Dec 4, 2023
b452f05
Update flow_ui.py
HeftyCoder Dec 4, 2023
87fb87b
Merge remote-tracking branch 'HeftyCoder/master' into pr176
leon-thomm Dec 5, 2023
22b12a0
add push_undo() to NodeInspectorWidget
leon-thomm Dec 5, 2023
bc58064
add import error on conflicting package names
leon-thomm Dec 5, 2023
a99955a
move tab bar min width to stylesheet
leon-thomm Dec 5, 2023
c24255d
hide console in verbose mode
leon-thomm Dec 5, 2023
48296d7
Merge remote-tracking branch 'upstream/pr176'
HeftyCoder Dec 5, 2023
ad07f34
Merge branch 'pr176'
HeftyCoder Dec 5, 2023
5e2ff0a
minor styling changes and undo bugfix
leon-thomm Dec 5, 2023
a309796
improve flow selection methods
leon-thomm Dec 5, 2023
3fe0596
fix hover_item negation
leon-thomm Dec 5, 2023
a2ce8f5
fix inspector window bug
leon-thomm Dec 5, 2023
df90056
rename selection FlowView modes
leon-thomm Dec 5, 2023
1042b16
minor styling changes
leon-thomm Dec 5, 2023
32ebfb9
update connection animation
leon-thomm Dec 5, 2023
5565f0d
Merge branch 'pr176'
HeftyCoder Dec 5, 2023
4c55331
Fixed Selection Issue
HeftyCoder Dec 5, 2023
3174378
Update FlowView.py
HeftyCoder Dec 5, 2023
b542a40
Open-Close All Docks
HeftyCoder Dec 5, 2023
6fe9bba
add package name identifier prefix to exported data types
leon-thomm Dec 5, 2023
09d2b68
Only tabified docks are closed
HeftyCoder Dec 5, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions ryven-editor/ryven/example_nodes/inspector_example/gui.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from ryven.gui_env import *
from qtpy.QtWidgets import (
QWidget,
QVBoxLayout,
QLabel,
QCheckBox,
)
from .nodes import MyNode


class MyNodeInspector(NodeInspectorWidget, QWidget):
def __init__(self, params):
NodeInspectorWidget.__init__(self, params)
QWidget.__init__(self)

self.setLayout(QVBoxLayout())
self.layout().addWidget(QLabel('This is a custom inspector for MyNode.'))
self.cb = QCheckBox('This is an undoable checkbox.')
self.cb.stateChanged.connect(self.on_cb_changed)
self.layout().addWidget(self.cb)

def on_cb_changed(self, state):
def undo_fn():
self.cb.stateChanged.disconnect(self.on_cb_changed)
self.cb.setChecked(not state)
self.cb.stateChanged.connect(self.on_cb_changed)

def redo_fn():
self.cb.stateChanged.disconnect(self.on_cb_changed)
self.cb.setChecked(state)
self.cb.stateChanged.connect(self.on_cb_changed)

self.push_undo(
text=f'{self.node.title} inspector checkbox: {state}',
undo_fn=undo_fn,
redo_fn=redo_fn,
)


@node_gui(MyNode)
class MyNodeGui(NodeGUI):
inspector_widget_class = MyNodeInspector
wrap_inspector_in_default = True
14 changes: 14 additions & 0 deletions ryven-editor/ryven/example_nodes/inspector_example/nodes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from ryven.node_env import *


class MyNode(Node):
title = 'My Node'


export_nodes(
[MyNode],
)

@on_gui_load
def on_load():
from . import gui
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ class Sub1Node(Node):
title = 'Node from sub-package 1'


export_sub_nodes(__file__,
export_nodes(
sub_pkg_name='A',
node_types=[Sub1Node],
)
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ class Sub2Node(Node):
title = 'Node from sub-package 2'


export_sub_nodes(__file__,
export_nodes(
sub_pkg_name='B',
node_types=[Sub2Node],
)
21 changes: 19 additions & 2 deletions ryven-editor/ryven/gui/flow_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
QHBoxLayout,
QTabWidget,
QDockWidget,
QUndoView,
)
from qtpy.QtCore import Qt, QByteArray

Expand All @@ -18,6 +19,7 @@
from ryven.gui.code_editor.CodePreviewWidget import CodePreviewWidget
from ryven.gui.uic.ui_flow_window import Ui_FlowWindow
from ryvencore_qt.src.flows.FlowView import FlowView
from ryvencore_qt.src.flows.nodes.NodeInspector import InspectorView
from typing import List


Expand All @@ -37,7 +39,7 @@ def __init__(self, main_window, flow: Flow, flow_view: FlowView):
# UI
self.ui = Ui_FlowWindow()
self.ui.setupUi(self)
# this is needed because it seems that qt compiler doesn't work well
# this is needed because there's no option in qt designer (propably)
self.ui.logger_dock.setWidget(self.ui.logs_scrollArea)
central_layout = QHBoxLayout()
self.ui.centralwidget.setLayout(central_layout)
Expand All @@ -60,6 +62,9 @@ def __init__(self, main_window, flow: Flow, flow_view: FlowView):
]
for i in range(1, len(right_area_widgets)):
self.tabifyDockWidget(right_area_widgets[i - 1], right_area_widgets[i])

# inspector dock first
self.ui.inspector_dock.raise_()

self.flow.algorithm_mode_changed.sub(self.flow_alg_mode_changed)

Expand All @@ -86,6 +91,14 @@ def __init__(self, main_window, flow: Flow, flow_view: FlowView):
# code preview
self.code_preview_widget = CodePreviewWidget(main_window, self.flow_view)
self.ui.source_dock.setWidget(self.code_preview_widget)

# inspector widget
self.inspector_widget = InspectorView(self.flow_view)
self.ui.inspector_dock.setWidget(self.inspector_widget)

#undo history widget
self.undo_widget = QUndoView(self.flow_view._undo_stack)
self.ui.undo_history_dock.setWidget(self.undo_widget)
# logs
self.ui.logs_scrollArea.setWidget(self.create_loggers_widget())

Expand All @@ -102,6 +115,7 @@ def __init__(self, main_window, flow: Flow, flow_view: FlowView):
def unload(self):
"""Disconnects the flow ui from the design or main application signals"""
self.flow_view.design.performance_mode_changed.disconnect(self.set_performance_mode)
self.flow_view._undo_stack.clear()

def set_performance_mode(self, mode: str):
if mode == 'fast':
Expand Down Expand Up @@ -132,10 +146,11 @@ def flow_algorithm_mode_toggled(self):
)

# should be dict[str, str] in 3.9+
def save(self) -> dict:
def save_state(self) -> dict:
return {
'geometry': self.saveGeometry().toHex().data().decode(),
'state': self.saveState().toHex().data().decode(),
'view': self.flow_view.save_state(),
}

# should be dict[str, dict[str, str]] in 3.9+
Expand All @@ -162,3 +177,5 @@ def load_directly(self, flow_dict: dict):
self.restoreGeometry(load('geometry'))
if 'state' in flow_dict:
self.restoreState(load('state'))
if 'view' in flow_dict:
self.flow_view.load(flow_dict['view'])
32 changes: 25 additions & 7 deletions ryven-editor/ryven/gui/main_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def __init__(
self.theme = config.window_theme
self.node_packages = {} # {Node: str}
self.flow_UIs = {} # Should be dict[Flow, FlowUI] in 3.9+
self.flow_ui_template = None # Should be dict[str, QByteArray] in 3.9+
self.flow_ui_template = None # Should be dict[str, QByteArray | dict] in 3.9+
self._project_content = None

# Init Session GUI
Expand Down Expand Up @@ -117,6 +117,8 @@ def console_ref_monkeypatch(self):
The editor console can still be used for commands.
'''
)
# hide the console in verbose mode
self.ui.consoleDock.hide()

# Setup ryvencore Session and load project

Expand All @@ -143,7 +145,11 @@ def console_ref_monkeypatch(self):

self.resize(1500, 800) # FIXME: this renders the --geometry argument useless, no?
# self.showMaximized()


def closeEvent(self, event):
for flow_ui in self.flow_UIs.values():
flow_ui.unload()

def print_info(self):
print('''
CONTROLS
Expand Down Expand Up @@ -176,6 +182,7 @@ def set_flow_template():
template = {
'geometry': flow_ui.saveGeometry().toHex().data().decode(),
'state': flow_ui.saveState().toHex().data().decode(),
'view': flow_ui.flow_view.save_state()
}
self.set_flow_ui_template(template)

Expand Down Expand Up @@ -309,7 +316,13 @@ def load_stylesheet(self, ss):
self.session_gui.set_stylesheet(ss_content)
self.setStyleSheet(ss_content)

# necessary for proper flow view loading
def showEvent(self, event):
for flow_ui in self.flow_UIs.values():
flow_ui.flow_view.reload()

# events

def on_performance_mode_value_changed(self, mode: str):
if mode == 'fast':
self.setDockOptions(self.dockOptions() & ~QMainWindow.AnimatedDocks)
Expand Down Expand Up @@ -495,7 +508,7 @@ def import_nodes(self, package: NodesPackage = None, path: str = None):
self.nodes_list_widget.update_list(self.core_session.nodes)
self.nodes_list_widget.make_pack_hier()

# should be dict[str, str] | dict[str, QByteArray] | None in 3.9+
# should be dict[str, str] | dict[str, QByteArray | dict] | None in 3.9+
def set_flow_ui_template(self, template):
if template is None:
self.flow_ui_template = None
Expand All @@ -505,7 +518,11 @@ def set_flow_ui_template(self, template):
if type(template[key]) is QByteArray
else bytes.fromhex(template[key])
)
self.flow_ui_template = {'geometry': save('geometry'), 'state': save('state')}
self.flow_ui_template = {
'geometry': save('geometry'),
'state': save('state'),
'view': template['view']
}

def load_qt_window(self, project_dict):
"""
Expand All @@ -518,7 +535,7 @@ def load_qt_window(self, project_dict):

def load_flow_ui(self, flow_ui: FlowUI):
"""
Loads a flows previous geometry and state based on the previous flow id.
Loads a flow uis previous geometry and state based on the previous flow id.
"""
if self._project_content is None:
return
Expand Down Expand Up @@ -562,10 +579,10 @@ def save_project(self, file_name):
state = self.saveState().toHex().data().decode()

# Serialization of the flow views
# should be dict[str, dict[str, str]] in 3.9+
# should be dict[str, dict[str, str | dict]] in 3.9+
flow_uis_ser: dict = {}
for flow, flow_ui in self.flow_UIs.items():
flow_uis_ser[str(flow.global_id)] = flow_ui.save()
flow_uis_ser[str(flow.global_id)] = flow_ui.save_state()

whole_project_dict = {
'general info': general_project_info_dict,
Expand All @@ -581,6 +598,7 @@ def save_project(self, file_name):
whole_project_dict['flow_ui_template'] = {
'geometry': QByteArray(self.flow_ui_template['geometry']).toHex().data().decode(),
'state': QByteArray(self.flow_ui_template['state']).toHex().data().decode(),
'view': self.flow_ui_template['view']
}

data = json.dumps(whole_project_dict, indent=4)
Expand Down
19 changes: 19 additions & 0 deletions ryven-editor/ryven/gui/startup_dialog/StartupDialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,18 @@ def __init__(self, config: Config, parent=None):
verbose_output_cb.toggled.connect(self.on_verbose_toggled)
fbox.addRow(verbose_output_label, verbose_output_cb)

# Defer source code loading
defer_code_label = QLabel('Defer SCL:')
defer_code_cb = QCheckBox('Enable defer source code loading')
defer_code_cb.setToolTip(
f'''Choose whether source code will be loaded on package
import or when the user manually attempt to inspect the
source on a specific node. Helps reduce package import
time.'''
)
defer_code_cb.toggled.connect(self.on_defer_toggled)
fbox.addRow(defer_code_label, defer_code_cb)

layout.addLayout(fbox)

# Buttons
Expand Down Expand Up @@ -437,6 +449,9 @@ def __init__(self, config: Config, parent=None):
# Set verbose output
verbose_output_cb.setChecked(self.conf.verbose)

# Set defer code loading
defer_code_cb.setChecked(self.conf.defer_code_loading)

# Set window title and icon
self.setWindowTitle('Ryven')
self.setWindowIcon(
Expand Down Expand Up @@ -578,6 +593,10 @@ def on_verbose_toggled(self, check):
# "Apply" the verbose option
self.conf.verbose = check

# Defer Source Code Loading
def on_defer_toggled(self, check):
"""Call-back method, whenever the defer source code loading checkbox was toggled"""
self.conf.defer_code_loading = check
#
# Helper/Working methods
#
Expand Down
30 changes: 30 additions & 0 deletions ryven-editor/ryven/gui/uic/flow_window.ui
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,36 @@
<set>QMainWindow::AllowTabbedDocks|QMainWindow::AnimatedDocks</set>
</property>
<widget class="QWidget" name="centralwidget"/>
<widget class="QDockWidget" name="inspector_dock">
<property name="floating">
<bool>false</bool>
</property>
<property name="features">
<set>QDockWidget::DockWidgetClosable|QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetMovable</set>
</property>
<property name="windowTitle">
<string>Inspector</string>
</property>
<attribute name="dockWidgetArea">
<number>2</number>
</attribute>
<widget class="QWidget" name="inspectorWidgetContents"/>
</widget>
<widget class="QDockWidget" name="undo_history_dock">
<property name="floating">
<bool>false</bool>
</property>
<property name="features">
<set>QDockWidget::DockWidgetClosable|QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetMovable</set>
</property>
<property name="windowTitle">
<string>Undo History</string>
</property>
<attribute name="dockWidgetArea">
<number>2</number>
</attribute>
<widget class="QWidget" name="undoHistoryContent"/>
</widget>
<widget class="QDockWidget" name="settings_dock">
<property name="features">
<set>QDockWidget::DockWidgetClosable|QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetMovable</set>
Expand Down
28 changes: 18 additions & 10 deletions ryven-editor/ryven/gui/uic/ui_flow_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,22 @@ def setupUi(self, FlowWindow):
self.centralwidget = QtWidgets.QWidget(FlowWindow)
self.centralwidget.setObjectName("centralwidget")
FlowWindow.setCentralWidget(self.centralwidget)
self.inspector_dock = QtWidgets.QDockWidget(FlowWindow)
self.inspector_dock.setFloating(False)
self.inspector_dock.setFeatures(QtWidgets.QDockWidget.DockWidgetClosable|QtWidgets.QDockWidget.DockWidgetFloatable|QtWidgets.QDockWidget.DockWidgetMovable)
self.inspector_dock.setObjectName("inspector_dock")
self.inspectorWidgetContents = QtWidgets.QWidget()
self.inspectorWidgetContents.setObjectName("inspectorWidgetContents")
self.inspector_dock.setWidget(self.inspectorWidgetContents)
FlowWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.inspector_dock)
self.undo_history_dock = QtWidgets.QDockWidget(FlowWindow)
self.undo_history_dock.setFloating(False)
self.undo_history_dock.setFeatures(QtWidgets.QDockWidget.DockWidgetClosable|QtWidgets.QDockWidget.DockWidgetFloatable|QtWidgets.QDockWidget.DockWidgetMovable)
self.undo_history_dock.setObjectName("undo_history_dock")
self.undoHistoryContent = QtWidgets.QWidget()
self.undoHistoryContent.setObjectName("undoHistoryContent")
self.undo_history_dock.setWidget(self.undoHistoryContent)
FlowWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.undo_history_dock)
self.settings_dock = QtWidgets.QDockWidget(FlowWindow)
self.settings_dock.setFeatures(QtWidgets.QDockWidget.DockWidgetClosable|QtWidgets.QDockWidget.DockWidgetFloatable|QtWidgets.QDockWidget.DockWidgetMovable)
self.settings_dock.setObjectName("settings_dock")
Expand Down Expand Up @@ -64,18 +80,10 @@ def setupUi(self, FlowWindow):
def retranslateUi(self, FlowWindow):
_translate = QtCore.QCoreApplication.translate
FlowWindow.setWindowTitle(_translate("FlowWindow", "MainWindow"))
self.inspector_dock.setWindowTitle(_translate("FlowWindow", "Inspector"))
self.undo_history_dock.setWindowTitle(_translate("FlowWindow", "Undo History"))
self.settings_dock.setWindowTitle(_translate("FlowWindow", "Settings"))
self.variables_dock.setWindowTitle(_translate("FlowWindow", "Variables"))
self.logger_dock.setWindowTitle(_translate("FlowWindow", "Log"))
self.source_dock.setWindowTitle(_translate("FlowWindow", "Source Code"))
self.actionxc.setText(_translate("FlowWindow", "xc"))


if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
FlowWindow = QtWidgets.QMainWindow()
ui = Ui_FlowWindow()
ui.setupUi(FlowWindow)
FlowWindow.show()
sys.exit(app.exec_())
Loading