Skip to content

Commit

Permalink
Merge branch '1.4_maintenance' into 1.5_maintenance
Browse files Browse the repository at this point in the history
  • Loading branch information
johnhaddon committed Dec 10, 2024
2 parents 092681f + f3b7898 commit bf8d404
Show file tree
Hide file tree
Showing 9 changed files with 77 additions and 14 deletions.
23 changes: 22 additions & 1 deletion Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ Fixes
-----

- MergeScenes : Fixed bug handling input connections not originating from the output of another node. These could cause locations provided by other inputs to lose all their properties.
- PathFilter : Fixed bug allowing dropping paths onto read-only `PathFilter` nodes in the graph.
- VectorDataWidget : Fixed bug allowing dropping paths onto read-only widgets.
- GraphEditor : Fixed errors when dragging an unknown file type into the GraphEditor.
- Widget : Fixed `event.sourceWidget` for DragDropEvents generated from a Qt native drag within the same Gaffer process. This will now reference the `GafferUI.Widget` that the Qt source widget belongs to, if any.
- Catalogue : Fixed bug which "stole" drags that crossed the image listing but which were destined elsewhere, for instance a drag from the HierarchyView to a PathFilter in the GraphEditor.
- GadgetWidget : Fixed signal handling bug in `setViewportGadget()`. This could cause the widget to attempt to redraw unnecessarily when the _old_ viewport requested a redraw.

API
---
Expand Down Expand Up @@ -336,10 +342,25 @@ Build
- Zstandard : Added version 1.5.0.
- Windows : Updated compiler to Visual Studio 2022 / MSVC 17.8 / Runtime library 14.3.

1.4.15.x (relative to 1.4.15.1)
1.4.15.x (relative to 1.4.15.2)
========

Fixes
-----

- GraphEditor : Fixed errors when dragging an unknown file type into the GraphEditor.
- Widget : Fixed `event.sourceWidget` for DragDropEvents generated from a Qt native drag within the same Gaffer process. This will now reference the `GafferUI.Widget` that the Qt source widget belongs to, if any.
- Catalogue : Fixed bug which "stole" drags that crossed the image listing but which were destined elsewhere, for instance a drag from the HierarchyView to a PathFilter in the GraphEditor.
- GadgetWidget : Fixed signal handling bug in `setViewportGadget()`. This could cause the widget to attempt to redraw unnecessarily when the _old_ viewport requested a redraw.

1.4.15.2 (relative to 1.4.15.1)
========

Fixes
-----

- PathFilter : Fixed bug allowing dropping paths onto read-only `PathFilter` nodes in the graph.
- VectorDataWidget : Fixed bug allowing dropping paths onto read-only widgets.

1.4.15.1 (relative to 1.4.15.0)
========
Expand Down
4 changes: 2 additions & 2 deletions python/GafferImageUI/CatalogueUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -1079,7 +1079,7 @@ def __dropImage( self, eventData ) :

def __pathListingDragEnter( self, widget, event ) :

if isinstance( event.data, IECore.StringVectorData ) :
if event.sourceWidget is widget and isinstance( event.data, IECore.StringVectorData ) and event.data :
# Allow reordering of images
self.__moveToPath = None
self.__mergeGroupId += 1
Expand All @@ -1101,7 +1101,7 @@ def __pathListingDragLeave( self, widget, event ) :

def __pathListingDragMove( self, listing, event ) :

if not event.data or not isinstance( event.data, IECore.StringVectorData ) :
if not ( event.sourceWidget is listing and isinstance( event.data, IECore.StringVectorData ) and event.data ) :
return

targetPath = self.__pathListing.pathAt( event.line.p0 )
Expand Down
23 changes: 19 additions & 4 deletions python/GafferSceneUI/PathFilterUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ def __popupMenu( menuDefinition, plugValueWidget ) :
GafferUI.Pointer.registerPointer( "removeObjects", GafferUI.Pointer( "removeObjects.png", imath.V2i( 53, 14 ) ) )
GafferUI.Pointer.registerPointer( "replaceObjects", GafferUI.Pointer( "replaceObjects.png", imath.V2i( 53, 14 ) ) )

__DropMode = enum.Enum( "__DropMode", [ "None_", "Add", "Remove", "Replace" ] )
__DropMode = enum.Enum( "__DropMode", [ "None_", "Add", "Remove", "Replace", "NotEditable" ] )

__originalDragPointer = None

Expand All @@ -255,9 +255,14 @@ def __filterPlug( node ) :
return filterPlugs[0]
return None

def __editable( plug ) :

return not Gaffer.MetadataAlgo.readOnly( plug ) and plug.settable()

def __dropMode( nodeGadget, event ) :

if __pathsPlug( nodeGadget.node() ) is None :
pathsPlug = __pathsPlug( nodeGadget.node() )
if pathsPlug is None :
filter = None

filterPlug = __filterPlug( nodeGadget.node() )
Expand All @@ -267,9 +272,13 @@ def __dropMode( nodeGadget, event ) :
if filterPlug.getInput() is not None :
filter = filterPlug.source().node()
if filter is None :
return __DropMode.Replace
return __DropMode.Replace if __editable( filterPlug ) else __DropMode.NotEditable
elif not isinstance( filter, GafferScene.PathFilter ) :
return __DropMode.None_
pathsPlug = __pathsPlug( filter )

if not __editable( pathsPlug ) :
return __DropMode.NotEditable

if event.modifiers & event.Modifiers.Shift :
return __DropMode.Add
Expand Down Expand Up @@ -342,7 +351,10 @@ def __dragMove( nodeGadget, event ) :
if __originalDragPointer is None :
return False

GafferUI.Pointer.setCurrent( __dropMode( nodeGadget, event ).name.lower() + "Objects" )
dropMode = __dropMode( nodeGadget, event )
GafferUI.Pointer.setCurrent(
dropMode.name.lower() + "Objects" if dropMode != __DropMode.NotEditable else "notEditable"
)

return True

Expand All @@ -352,6 +364,9 @@ def __drop( nodeGadget, event ) :
if __originalDragPointer is None :
return False

if __dropMode( nodeGadget, event ) == __DropMode.NotEditable :
return True

pathsPlug = __pathsPlug( nodeGadget.node() )
if pathsPlug is None :
pathsPlug = __pathsPlug( __filterPlug( nodeGadget.node() ).source().node() )
Expand Down
14 changes: 10 additions & 4 deletions python/GafferSceneUI/SetFilterUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@
GafferUI.Pointer.registerPointer( "removeSets", GafferUI.Pointer( "pointerRemoveSets.png", imath.V2i( 53, 14 ) ) )
GafferUI.Pointer.registerPointer( "replaceSets", GafferUI.Pointer( "pointerReplaceSets.png", imath.V2i( 53, 14 ) ) )

__DropMode = enum.Enum( "__DropMode", [ "None_", "Add", "Remove", "Replace" ] )
__DropMode = enum.Enum( "__DropMode", [ "None_", "Add", "Remove", "Replace", "NotEditable" ] )

__originalDragPointer = None

Expand Down Expand Up @@ -146,13 +146,13 @@ def __dropMode( nodeGadget, event ) :
if nodeGadget.node()["filter"].getInput() is not None :
filter = nodeGadget.node()["filter"].source().node()
if filter is None :
return __DropMode.Replace if __editable( nodeGadget.node()["filter"] ) else __DropMode.None_
return __DropMode.Replace if __editable( nodeGadget.node()["filter"] ) else __DropMode.NotEditable
elif not isinstance( filter, GafferScene.SetFilter ) :
return __DropMode.None_
setsPlug = filter["setExpression"]

if not __editable( setsPlug ) :
return __DropMode.None_
return __DropMode.NotEditable

if event.modifiers & event.Modifiers.Shift :
return __DropMode.Add
Expand Down Expand Up @@ -201,7 +201,10 @@ def __dragMove( nodeGadget, event ) :
if __originalDragPointer is None :
return False

GafferUI.Pointer.setCurrent( __dropMode( nodeGadget, event ).name.lower() + "Sets" )
dropMode = __dropMode( nodeGadget, event )
GafferUI.Pointer.setCurrent(
dropMode.name.lower() + "Sets" if dropMode != __DropMode.NotEditable else "notEditable"
)

return True

Expand All @@ -211,6 +214,9 @@ def __drop( nodeGadget, event ) :
if __originalDragPointer is None :
return False

if __dropMode( nodeGadget, event ) == __DropMode.NotEditable :
return True

setsPlug = __setsPlug( nodeGadget.node() )
if setsPlug is None :
setsPlug = __setsPlug( nodeGadget.node()["filter"].source().node() )
Expand Down
2 changes: 1 addition & 1 deletion python/GafferUI/GadgetWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def setViewportGadget( self, viewportGadget ) :
self.__viewportGadget.setVisible( False )

self.__viewportGadget = viewportGadget
self.__viewportGadget.renderRequestSignal().connect( Gaffer.WeakMethod( self.__renderRequest ) )
self.__renderRequestConnection = self.__viewportGadget.renderRequestSignal().connect( Gaffer.WeakMethod( self.__renderRequest ), scoped = True )
size = self.size()
if size.x and size.y :
self.__viewportGadget.setViewport( size )
Expand Down
3 changes: 3 additions & 0 deletions python/GafferUI/VectorDataWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,9 @@ def __addRows( self, button ) :

def __dragEnter( self, widget, event ) :

if not self.getEditable() :
return False

if event.sourceWidget is self.__tableViewHolder and widget is not self.__buttonRow[1]:
# we don't accept drags from ourself unless the target is the remove button
return False
Expand Down
6 changes: 5 additions & 1 deletion python/GafferUI/Widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -1578,9 +1578,13 @@ def __foreignDragEnter( self, qObject, qEvent ) :
Widget._modifiers( qEvent.keyboardModifiers() ),
)
dragDropEvent.data = data
dragDropEvent.sourceWidget = None
dragDropEvent.destinationWidget = None

if isinstance( qEvent.source(), QtWidgets.QWidget ) :
dragDropEvent.sourceWidget = GafferUI.Widget._owner( qEvent.source() )
else :
dragDropEvent.sourceWidget = None

if widget._dragEnterSignal( widget, dragDropEvent ) :
qEvent.acceptProposedAction()
self.__foreignDragDropEvent = dragDropEvent
Expand Down
13 changes: 13 additions & 0 deletions python/GafferUITest/GadgetWidgetTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,18 @@ def testViewportVisibility( self ) :
self.assertFalse( vg1.visible() )
self.assertFalse( vg2.visible() )

def testConnectionLifetime( self ) :

gadgetWidget = GafferUI.GadgetWidget()
viewportGadget1 = gadgetWidget.getViewportGadget()
self.assertEqual( viewportGadget1.renderRequestSignal().numSlots(), 1 )

viewportGadget2 = GafferUI.ViewportGadget()
self.assertEqual( viewportGadget2.renderRequestSignal().numSlots(), 0 )

gadgetWidget.setViewportGadget( viewportGadget2 )
self.assertEqual( viewportGadget1.renderRequestSignal().numSlots(), 0 )
self.assertEqual( viewportGadget2.renderRequestSignal().numSlots(), 1 )

if __name__ == "__main__":
unittest.main()
3 changes: 2 additions & 1 deletion startup/gui/graphEditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,8 @@ def __dropLocationData( event ) :
if (
not isinstance( event.data, IECore.StringVectorData ) or
len( event.data ) != 1 or
not event.data[0].startswith( "/" )
not event.data[0].startswith( "/" ) or
event.sourceWidget is None
) :
return None

Expand Down

0 comments on commit bf8d404

Please sign in to comment.