Skip to content

Commit

Permalink
Merge pull request #5925 from johnhaddon/popupWindowColorspace
Browse files Browse the repository at this point in the history
Popup window colorspace fix
  • Loading branch information
murraystevenson authored Jun 28, 2024
2 parents 1b34963 + c06bc0d commit f021e75
Show file tree
Hide file tree
Showing 14 changed files with 129 additions and 20 deletions.
6 changes: 6 additions & 0 deletions Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ Fixes

- HierarchyView, LightEditor, PrimitiveInspector, SceneInspector : Fixed bug which allowed scenes from private plugs to be displayed.
- PrimitiveInspector : Fixed bug which claimed "Location does not exist" for objects without any primitive variables.
- OpenColorIO : Fixed the display transform used to show colours in popups.

API
---

- PopupWindow : Added `parent` argument to `popup()` method. This allows popup windows to inherit the display transform from the main UI.

1.4.8.0 (relative to 1.4.7.0)
=======
Expand Down
8 changes: 4 additions & 4 deletions python/GafferSceneUI/LightEditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ def __editSelectedCells( self, pathListing, quickBoolean = True ) :
with GafferUI.ListContainer( GafferUI.ListContainer.Orientation.Horizontal, spacing = 4 ) :
GafferUI.Image( "warningSmall.png" )
GafferUI.Label( "<h4>The " + column.headerData().value + " column can only be toggled for lights." )
self.__popup.popup()
self.__popup.popup( parent = self )
return

context["scene:path"] = path
Expand All @@ -419,7 +419,7 @@ def __editSelectedCells( self, pathListing, quickBoolean = True ) :
GafferUI.Image( "warningSmall.png" )
GafferUI.Label( "<h4>The selected cells cannot be edited in the current Edit Scope</h4>" )

self.__popup.popup()
self.__popup.popup( parent = self )

return

Expand All @@ -437,7 +437,7 @@ def __editSelectedCells( self, pathListing, quickBoolean = True ) :
if isinstance( self.__popup.plugValueWidget(), GafferUI.TweakPlugValueWidget ) :
self.__popup.plugValueWidget().setNameVisible( False )

self.__popup.popup()
self.__popup.popup( parent = self )

else :

Expand All @@ -446,7 +446,7 @@ def __editSelectedCells( self, pathListing, quickBoolean = True ) :
GafferUI.Image( "warningSmall.png" )
GafferUI.Label( "<h4>{}</h4>".format( nonEditable[0].nonEditableReason() ) )

self.__popup.popup()
self.__popup.popup( parent = self )

def __toggleBoolean( self, inspectors, inspections ) :

Expand Down
8 changes: 4 additions & 4 deletions python/GafferSceneUI/RenderPassEditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ def __setActiveRenderPass( self, pathListing ) :
GafferUI.Image( "warningSmall.png" )
GafferUI.Label( "<h4>The script is read-only.</h4>" )

self.__popup.popup()
self.__popup.popup( parent = self )
return

if "renderPass" not in script["variables"] :
Expand Down Expand Up @@ -488,7 +488,7 @@ def __editSelectedCells( self, pathListing, quickBoolean = True ) :
GafferUI.Image( "warningSmall.png" )
GafferUI.Label( "<h4>The selected cells cannot be edited in the current Edit Scope</h4>" )

self.__popup.popup()
self.__popup.popup( parent = self )

return

Expand All @@ -508,7 +508,7 @@ def __editSelectedCells( self, pathListing, quickBoolean = True ) :

## \todo : Adjust popup width based on the inspector column width(s) to improve
# editing of long paths, similar to how we handle this in the Spreadsheet.
self.__popup.popup()
self.__popup.popup( parent = self )

else :

Expand All @@ -517,7 +517,7 @@ def __editSelectedCells( self, pathListing, quickBoolean = True ) :
GafferUI.Image( "warningSmall.png" )
GafferUI.Label( "<h4>{}</h4>".format( nonEditable[0].nonEditableReason() ) )

self.__popup.popup()
self.__popup.popup( parent = self )

def __toggleBoolean( self, inspectors, inspections ) :

Expand Down
3 changes: 2 additions & 1 deletion python/GafferSceneUI/SceneViewUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,8 @@ def __clicked( self, button ) :
center = imath.V2i(
bound.center().x,
bound.max().y + self.__window.bound().size().y / 2 + 8,
)
),
parent = self
)

##########################################################################
Expand Down
2 changes: 1 addition & 1 deletion python/GafferSceneUI/_HistoryWindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ def __editSelectedCell( self, pathListing ) :
if isinstance( self.__popup.plugValueWidget(), GafferUI.TweakPlugValueWidget ) :
self.__popup.plugValueWidget().setNameVisible( False )

self.__popup.popup()
self.__popup.popup( parent = self )

def __dragBegin( self, pathListing, event ) :

Expand Down
4 changes: 2 additions & 2 deletions python/GafferSceneUI/_SceneViewInspector.py
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ def __valueDoubleClick( self, widget, event ) :
)
if isinstance( self.__popup.plugValueWidget(), GafferUI.TweakPlugValueWidget ) :
self.__popup.plugValueWidget().setNameVisible( False )
self.__popup.popup()
self.__popup.popup( parent = self )

else :

Expand All @@ -425,7 +425,7 @@ def __valueDoubleClick( self, widget, event ) :
self.__formatWarnings( [ r.nonEditableReason() for r in self.__inspectorResults ] )
) )

self.__popup.popup()
self.__popup.popup( parent = self )

return True

Expand Down
4 changes: 2 additions & 2 deletions python/GafferUI/EditScopeUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ def __drop( self, widget, event ) :
with GafferUI.ListContainer( GafferUI.ListContainer.Orientation.Horizontal, spacing = 4 ) :
GafferUI.Image( "warningSmall.png" )
GafferUI.Label( "<h4>The Edit Scope cannot be set while nothing is viewed</h4>" )
self.__popup.popup()
self.__popup.popup( parent = self )
elif dropNode :
upstream = Gaffer.NodeAlgo.findAllUpstream( inputNode, self.__editScopePredicate )
if self.__editScopePredicate( inputNode ) :
Expand All @@ -465,7 +465,7 @@ def __drop( self, widget, event ) :
with GafferUI.ListContainer( GafferUI.ListContainer.Orientation.Horizontal, spacing = 4 ) :
GafferUI.Image( "warningSmall.png" )
GafferUI.Label( "<h4>{} cannot be used as it is not upstream of {}</h4>".format( dropNode.getName(), inputNode.getName() ) )
self.__popup.popup()
self.__popup.popup( parent = self )

self.__frame.setHighlighted( False )

Expand Down
2 changes: 1 addition & 1 deletion python/GafferUI/GraphEditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ def __popupNodeMenu( self ) :
GafferUI.Image( "warningSmall.png" )
GafferUI.Label( "Node Graph Not Editable" )

self.__readOnlyPopup.popup( center = self.bound().center() )
self.__readOnlyPopup.popup( center = self.bound().center(), parent = self )

def __nodeMenuVisibilityChanged( self, widget ) :

Expand Down
4 changes: 2 additions & 2 deletions python/GafferUI/PlugPopup.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,9 @@ def __init__( self, plugs, title = None, warning = None, **kw ) :
self.visibilityChangedSignal().connect( Gaffer.WeakMethod( self.__visibilityChanged ), scoped = False )
self.focusChangedSignal().connect( Gaffer.WeakMethod( self.__focusChanged ), scoped = False )

def popup( self, center = None ) :
def popup( self, center = None, parent = None ) :

GafferUI.PopupWindow.popup( self, center )
GafferUI.PopupWindow.popup( self, center, parent )

# Attempt to focus the first text widget. This is done after making
# the window visible, as we check child widget visibility to avoid
Expand Down
23 changes: 22 additions & 1 deletion python/GafferUI/PopupWindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
#
##########################################################################

import weakref

import imath

import Gaffer
Expand All @@ -48,13 +50,22 @@ def __init__( self, title = "GafferUI.Window", borderWidth = 8, child = None, **

GafferUI.Window.__init__( self, title, borderWidth, child = child, sizeMode = GafferUI.Window.SizeMode.Automatic, **kw )

self.__popupParent = None

self._qtWidget().setWindowFlags( QtCore.Qt.Popup )
self._qtWidget().setAttribute( QtCore.Qt.WA_TranslucentBackground )
self._qtWidget().paintEvent = Gaffer.WeakMethod( self.__paintEvent )

self.keyPressSignal().connect( Gaffer.WeakMethod( self.__keyPress ), scoped = False )

def popup( self, center = None ) :
## Note : A valid `parent` widget must be supplied if widgets in the PopupWindow
# are to inherit a display transform from the main UI.
def popup( self, center = None, parent = None ) :

if parent is not None :
self.__popupParent = weakref.ref( parent )
else :
self.__popupParent = None

if center is None :
center = GafferUI.Widget.mousePosition()
Expand All @@ -63,6 +74,16 @@ def popup( self, center = None ) :
size = self._qtWidget().sizeHint()
self.setPosition( center - imath.V2i( size.width() / 2, size.height() / 2 ) )

## Reimplemented from Widget to report the parent passed to `popup()`.
def parent( self ) :

if self.__popupParent is not None :
p = self.__popupParent()
if p is not None :
return p

return GafferUI.Widget.parent( self )

def __paintEvent( self, event ) :

painter = QtGui.QPainter( self._qtWidget() )
Expand Down
2 changes: 1 addition & 1 deletion python/GafferUI/SpreadsheetUI/_PlugTableView.py
Original file line number Diff line number Diff line change
Expand Up @@ -1127,7 +1127,7 @@ def __showEditor( self, plugs, plugBound, allowDirectEditing ) :
return

self.__editorWidget = GafferUI.PlugPopup( plugs, title = "" )
self.__editorWidget.popup( plugBound.center() )
self.__editorWidget.popup( plugBound.center(), parent = self )

widget = self.__editorWidget.plugValueWidget()
if isinstance( widget, GafferUI.StringPlugValueWidget ) :
Expand Down
2 changes: 1 addition & 1 deletion python/GafferUI/VectorDataWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -1484,7 +1484,7 @@ def _createEditorInternal( self, index ) :
self.__colorChooser = GafferUI.ColorChooser( value )
self.__popup = GafferUI.PopupWindow( "", child = self.__colorChooser )

self.__popup.popup()
self.__popup.popup( parent = self )

return self.__popup

Expand Down
80 changes: 80 additions & 0 deletions python/GafferUITest/PopupWindowTest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
##########################################################################
#
# Copyright (c) 2024, Cinesite VFX Ltd. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above
# copyright notice, this list of conditions and the following
# disclaimer.
#
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided with
# the distribution.
#
# * Neither the name of John Haddon nor the names of
# any other contributors to this software may be used to endorse or
# promote products derived from this software without specific prior
# written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
##########################################################################

import unittest
import weakref

import GafferUI
import GafferUITest

class PopupWindowTest( GafferUITest.TestCase ) :

def testDisplayTransform( self ) :

displayTransform1 = lambda x : x * 2
displayTransform2 = lambda x : x * 3

window = GafferUI.Window()
self.assertIs( window.displayTransform(), GafferUI.Widget.identityDisplayTransform )
window.setDisplayTransform( displayTransform1 )
self.assertIs( window.displayTransform(), displayTransform1 )

popup = GafferUI.PopupWindow()
self.assertEqual( popup.displayTransform(), GafferUI.Widget.identityDisplayTransform )
popup.popup()
self.assertEqual( popup.displayTransform(), GafferUI.Widget.identityDisplayTransform )

popup.popup( parent = window )
self.assertEqual( popup.displayTransform(), displayTransform1 )

popup.setDisplayTransform( displayTransform2 )
self.assertEqual( popup.displayTransform(), displayTransform2 )

def testParentWindowLifetime( self ) :

window = GafferUI.Window()
popup = GafferUI.PopupWindow()
popup.popup( parent = window )

weakWindow = weakref.ref( window )
weakPopup = weakref.ref( popup )
del window, popup

self.assertIsNone( weakWindow() )
self.assertIsNone( weakPopup() )

if __name__ == "__main__":
unittest.main()
1 change: 1 addition & 0 deletions python/GafferUITest/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@
from .PythonEditorTest import PythonEditorTest
from .BoxIOUITest import BoxIOUITest
from .AnnotationsGadgetTest import AnnotationsGadgetTest
from .PopupWindowTest import PopupWindowTest

if __name__ == "__main__":
unittest.main()

0 comments on commit f021e75

Please sign in to comment.