2121 PIPE_LAYOUT_ANGLE ,
2222 IN_PORT , OUT_PORT )
2323from ..widgets .viewer import NodeViewer
24+ from ..widgets .node_space_bar import node_space_bar
2425
2526
2627class QWidgetDrops (QtWidgets .QWidget ):
28+ def __init__ (self ):
29+ super (QWidgetDrops , self ).__init__ ()
30+ self .setAcceptDrops (True )
31+ self .setWindowTitle ("NodeGraphQt" )
32+ self .setStyleSheet ('''
33+ QWidget {
34+ background-color: rgb(55,55,55);
35+ color: rgb(200,200,200);
36+ border-width: 0px;
37+ }''' )
38+
2739 def dragEnterEvent (self , event ):
2840 if event .mimeData ().hasUrls :
2941 event .accept ()
@@ -135,7 +147,7 @@ def __init__(self, parent=None):
135147 self ._viewer .need_show_tab_search .connect (self ._toggle_tab_search )
136148
137149 self ._wire_signals ()
138- self .widget . setAcceptDrops ( True )
150+ self ._node_space_bar = node_space_bar ( self )
139151
140152 def __repr__ (self ):
141153 return '<{} object at {}>' .format (self .__class__ .__name__ , hex (id (self )))
@@ -358,6 +370,7 @@ def widget(self):
358370
359371 layout = QtWidgets .QVBoxLayout (self ._widget )
360372 layout .setContentsMargins (0 , 0 , 0 , 0 )
373+ layout .addWidget (self ._node_space_bar )
361374 layout .addWidget (self ._viewer )
362375 return self ._widget
363376
@@ -631,7 +644,12 @@ def fit_to_selection(self):
631644 Sets the zoom level to fit selected nodes.
632645 If no nodes are selected then all nodes in the graph will be framed.
633646 """
634- nodes = self .selected_nodes () or self .all_nodes ()
647+ if self ._current_node_space is None :
648+ all_nodes = self .all_nodes ()
649+ else :
650+ all_nodes = self ._current_node_space .children ()
651+
652+ nodes = self .selected_nodes () or all_nodes
635653 if not nodes :
636654 return
637655 self ._viewer .zoom_to_nodes ([n .view for n in nodes ])
@@ -720,7 +738,6 @@ def create_node(self, node_type, name=None, selected=True, color=None,
720738 NodeCls = self ._node_factory .create_node_instance (node_type )
721739 if NodeCls :
722740 node = NodeCls ()
723- node .set_graph (self )
724741 node .model ._graph_model = self .model
725742
726743 wid_types = node .model .__dict__ .pop ('_TEMP_property_widget_types' )
@@ -737,6 +754,7 @@ def create_node(self, node_type, name=None, selected=True, color=None,
737754 node .NODE_NAME = self .get_unique_name (name or node .NODE_NAME )
738755 node .model .name = node .NODE_NAME
739756 node .model .selected = selected
757+ node .set_graph (self )
740758
741759 def format_color (clr ):
742760 if isinstance (clr , str ):
@@ -758,7 +776,15 @@ def format_color(clr):
758776
759777 undo_cmd = NodeAddedCmd (self , node , node .model .pos )
760778 undo_cmd .setText ('create node: "{}"' .format (node .NODE_NAME ))
761- self ._undo_stack .push (undo_cmd )
779+
780+ if isinstance (node , SubGraph ):
781+ self .begin_undo ('create sub graph node' )
782+ self ._undo_stack .push (undo_cmd )
783+ if node .get_property ('create_from_select' ):
784+ node .create_from_nodes (self .selected_nodes ())
785+ self .end_undo ()
786+ else :
787+ self ._undo_stack .push (undo_cmd )
762788 self .node_created .emit (node )
763789 return node
764790 raise Exception ('\n \n >> Cannot find node:\t "{}"\n ' .format (node_type ))
@@ -798,14 +824,15 @@ def set_node_space(self, node):
798824 Args:
799825 node (NodeGraphQt.SubGraph): node object.
800826 """
827+ if node is self ._current_node_space :
828+ return
801829 if self ._current_node_space is not None :
802- [n .hide () for n in self ._current_node_space .children ()]
803830 self ._current_node_space .exit ()
804831
805832 self ._current_node_space = node
806833 if node is not None :
807- [n .show () for n in node .children ()]
808834 node .enter ()
835+ self ._node_space_bar .set_node (node )
809836
810837 def get_node_space (self ):
811838 """
@@ -826,9 +853,13 @@ def delete_node(self, node):
826853 assert isinstance (node , NodeObject ), \
827854 'node must be a instance of a NodeObject.'
828855 self .nodes_deleted .emit ([node .id ])
829- self . _undo_stack . push ( NodeRemovedCmd ( self , node ))
830- if isinstance ( node , SubGraph ):
856+ if isinstance ( node , SubGraph ):
857+ self . _undo_stack . beginMacro ( 'delete sub graph' )
831858 self .delete_nodes (node .children ())
859+ self ._undo_stack .push (NodeRemovedCmd (self , node ))
860+ self ._undo_stack .endMacro ()
861+ else :
862+ self ._undo_stack .push (NodeRemovedCmd (self , node ))
832863
833864 def delete_nodes (self , nodes ):
834865 """
@@ -839,7 +870,7 @@ def delete_nodes(self, nodes):
839870 """
840871 self .nodes_deleted .emit ([n .id for n in nodes ])
841872 self ._undo_stack .beginMacro ('delete nodes' )
842- [self .delete_nodes (n .children ()) for n in nodes if isinstance (n ,SubGraph )]
873+ [self .delete_nodes (n .children ()) for n in nodes if isinstance (n , SubGraph )]
843874 [self ._undo_stack .push (NodeRemovedCmd (self , n )) for n in nodes ]
844875 self ._undo_stack .endMacro ()
845876
@@ -880,17 +911,18 @@ def select_all(self):
880911 Select all nodes in the node graph.
881912 """
882913 self ._undo_stack .beginMacro ('select all' )
883- for node in self .all_nodes ():
884- node .set_selected (True )
914+ if self ._current_node_space is not None :
915+ [node .set_selected (True ) for node in self ._current_node_space .children ()]
916+ else :
917+ [node .set_selected (True ) for node in self .all_nodes ()]
885918 self ._undo_stack .endMacro ()
886919
887920 def clear_selection (self ):
888921 """
889922 Clears the selection in the node graph.
890923 """
891924 self ._undo_stack .beginMacro ('clear selection' )
892- for node in self .all_nodes ():
893- node .set_selected (False )
925+ [node .set_selected (False ) for node in self .all_nodes ()]
894926 self ._undo_stack .endMacro ()
895927
896928 def get_node_by_id (self , node_id = None ):
@@ -905,6 +937,41 @@ def get_node_by_id(self, node_id=None):
905937 """
906938 return self ._model .nodes .get (node_id , None )
907939
940+ def get_node_by_path (self , node_path ):
941+ """
942+ Returns the node from the node path string.
943+
944+ Args:
945+ node_path (str): node path (:attr:`NodeObject.path()`)
946+
947+ Returns:
948+ NodeGraphQt.NodeObject: node object.
949+ """
950+ names = [name for name in node_path .split ("/" ) if name ]
951+ root = names .pop (0 )
952+ node = self ._current_node_space
953+ if node is None :
954+ node = self .get_node_by_name (root )
955+ if node is None :
956+ return None
957+ else :
958+ while True :
959+ parent_node = node .parent ()
960+ if parent_node is None :
961+ break
962+ node = parent_node
963+
964+ for name in names :
965+ find = False
966+ for n in node .children ():
967+ if n .name () == name :
968+ node = n
969+ find = True
970+ continue
971+ if not find :
972+ return None
973+ return node
974+
908975 def get_node_by_name (self , name ):
909976 """
910977 Returns node that matches the name.
@@ -914,9 +981,14 @@ def get_node_by_name(self, name):
914981 Returns:
915982 NodeGraphQt.NodeObject: node object.
916983 """
917- for node_id , node in self ._model .nodes .items ():
984+ if self ._current_node_space is not None :
985+ nodes = self ._current_node_space .children ()
986+ else :
987+ nodes = self .all_nodes ()
988+ for node in nodes :
918989 if node .name () == name :
919990 return node
991+ return None
920992
921993 def get_unique_name (self , name ):
922994 """
@@ -929,7 +1001,10 @@ def get_unique_name(self, name):
9291001 str: unique node name.
9301002 """
9311003 name = ' ' .join (name .split ())
932- node_names = [n .name () for n in self .all_nodes ()]
1004+ if self ._current_node_space is not None :
1005+ node_names = [n .name () for n in self ._current_node_space .children ()]
1006+ else :
1007+ node_names = [n .name () for n in self .all_nodes ()]
9331008 if name not in node_names :
9341009 return name
9351010
@@ -1149,13 +1224,15 @@ def import_session(self, file_path):
11491224 return
11501225
11511226 self ._deserialize (layout_data )
1152- node_space_id = layout_data ['graph' ]['node_space' ]
1227+
1228+ if 'graph' in layout_data .keys ():
1229+ node_space_id = layout_data ['graph' ]['node_space' ]
11531230
1154- # deserialize graph data
1155- self .set_node_space (self .get_node_by_id (node_space_id ))
1156- self ._viewer .set_pipe_layout (layout_data ['graph' ]['pipe_layout' ])
1231+ # deserialize graph data
1232+ self .set_node_space (self .get_node_by_id (node_space_id ))
1233+ self ._viewer .set_pipe_layout (layout_data ['graph' ]['pipe_layout' ])
11571234
1158- self ._viewer .set_scene_rect (layout_data ['graph' ]['graph_rect' ])
1235+ self ._viewer .set_scene_rect (layout_data ['graph' ]['graph_rect' ])
11591236
11601237 self ._undo_stack .clear ()
11611238 self ._model .session = file_path
0 commit comments