def __contextMenu( self, pos ) : # build the menu and pop it up m = self._contextMenuDefinition( self.__selectedRows() ) self.__popupMenu = GafferUI.Menu( m ) self.__popupMenu.popup( self )
def __init__( self, plug, **kw ) : l = GafferUI.ListContainer( GafferUI.ListContainer.Orientation.Horizontal, spacing = 4 ) GafferUI.PlugValueWidget.__init__( self, l, plug, **kw ) mode = plug["mode"].getValue() with l: self.__indexLabel = GafferUI.Label() labelFont = QtGui.QFont( self.__indexLabel._qtWidget().font() ) labelFont.setBold( True ) labelFont.setPixelSize( 10 ) labelFontMetrics = QtGui.QFontMetrics( labelFont ) self.__indexLabel._qtWidget().setMinimumWidth( labelFontMetrics.boundingRect( "99" ).width() ) self.__modeImage = GafferUI.Image( "sourceCursor.png" ) self.__positionLabel = GafferUI.Label() self.__positionLabel._qtWidget().setMinimumWidth( labelFontMetrics.boundingRect( "9999 9999 -> 9999 9999" ).width() ) self.__swatch = GafferUI.ColorSwatch() self.__swatch._qtWidget().setFixedWidth( 12 ) self.__swatch._qtWidget().setFixedHeight( 12 ) self.__busyWidget = GafferUI.BusyWidget( size = 12 ) self.__rgbLabel = GafferUI.Label() self.__rgbLabel._qtWidget().setMinimumWidth( labelFontMetrics.boundingRect( "RGBA : 99999 99999 99999 99999" ).width() ) self.__hsvLabel = GafferUI.Label() self.__hsvLabel._qtWidget().setMinimumWidth( labelFontMetrics.boundingRect( "HSV : 99999 99999 99999" ).width() ) self.__exposureLabel = GafferUI.Label() self.__exposureLabel._qtWidget().setMinimumWidth( labelFontMetrics.boundingRect( "EV : 19.9" ).width() ) l.addChild( GafferUI.Spacer( size = imath.V2i( 0 ) ) ) if mode == GafferImageUI.ImageView.ColorInspectorPlug.Mode.Cursor: m = IECore.MenuDefinition() m.append( "/Pixel Inspector", { "command" : functools.partial( Gaffer.WeakMethod( self.__addClick ), GafferImageUI.ImageView.ColorInspectorPlug.Mode.Pixel ) } ) m.append( "/Area Inspector", { "command" : functools.partial( Gaffer.WeakMethod( self.__addClick ), GafferImageUI.ImageView.ColorInspectorPlug.Mode.Area ) } ) button = GafferUI.MenuButton( "", "plus.png", hasFrame=False, menu = GafferUI.Menu( m, title = "Add Color Inspector" ) ) else: button = GafferUI.Button( "", "delete.png", hasFrame=False ) button.clickedSignal().connect( Gaffer.WeakMethod( self.__deleteClick ), scoped = False ) self.__pixel = imath.V2i( 0 ) self.__createInspectorStartPosition = None if plug.getName() == "ColorInspectorPlug": viewportGadget = plug.node().viewportGadget() imageGadget = viewportGadget.getPrimaryChild() imageGadget.mouseMoveSignal().connect( Gaffer.WeakMethod( self.__mouseMove ), scoped = False ) imageGadget.buttonPressSignal().connect( Gaffer.WeakMethod( self.__buttonPress ), scoped = False ) imageGadget.buttonReleaseSignal().connect( Gaffer.WeakMethod( self.__buttonRelease ), scoped = False ) imageGadget.dragBeginSignal().connect( Gaffer.WeakMethod( self.__dragBegin ), scoped = False ) imageGadget.dragEnterSignal().connect( Gaffer.WeakMethod( self.__dragEnter ), scoped = False ) imageGadget.dragMoveSignal().connect( Gaffer.WeakMethod( self.__dragMove ), scoped = False ) imageGadget.dragEndSignal().connect( Gaffer.WeakMethod( self.__dragEnd ), scoped = False ) self.__swatch.buttonPressSignal().connect( Gaffer.WeakMethod( self.__buttonPress ), scoped = False ) self.__swatch.dragBeginSignal().connect( Gaffer.WeakMethod( self.__dragBegin ), scoped = False ) self.__swatch.dragEndSignal().connect( Gaffer.WeakMethod( self.__dragEnd ), scoped = False ) plug.node()["colorInspector"]["evaluator"]["pixelColor"].getInput().node().plugDirtiedSignal().connect( Gaffer.WeakMethod( self.__updateFromImageNode ), scoped = False ) plug.node().plugDirtiedSignal().connect( Gaffer.WeakMethod( self._plugDirtied ), scoped = False ) plug.node()["in"].getInput().node().scriptNode().context().changedSignal().connect( Gaffer.WeakMethod( self.__updateFromContext ), scoped = False ) Gaffer.Metadata.plugValueChangedSignal( self.getPlug().node() ).connect( Gaffer.WeakMethod( self.__plugMetadataChanged ), scoped = False ) self.__updateLabels( imath.V2i( 0 ), imath.Color4f( 0, 0, 0, 1 ) ) # Set initial state of mode icon self._plugDirtied( plug["mode"] )
def _updateFromSet(self): GafferUI.NodeSetEditor._updateFromSet(self) focusWidget = GafferUI.Widget._owner( QtWidgets.QApplication.focusWidget()) if self.__column.isAncestorOf(focusWidget): # The focus is in our editor, but it belongs to a widget we're about # to delete. Transfer the focus up so that we don't lose the focus # when we delete the widget. ## \todo Is there an argument for moving this fix to the ListContainer # itself? self.__column._qtWidget().setFocus() del self.__column[:] self.__nodeUI = None self.__nameWidget = None node = self._lastAddedNode() if not node: with self.__column: GafferUI.Spacer(imath.V2i(0)) return with self.__column: with GafferUI.ListContainer( GafferUI.ListContainer.Orientation.Horizontal, borderWidth=8, spacing=4): GafferUI.Label("<h4>Node Name</h4>") self.__nameWidget = GafferUI.NameWidget(node) ## \todo Make NameWidget support the readOnly metadata internally itself. # We can't do that easily right now, because it would need to be managing # the exact same `setEditable()` call that we're using here to propagate # our Widget readonlyness. Really our Widget readonlyness mechanism is a # bit lacking, and it should really be inherited automatically so we don't # have to propagate it like this. self.__nameWidget.setEditable( not self.getReadOnly() and not Gaffer.MetadataAlgo.readOnly(node)) with GafferUI.ListContainer( GafferUI.ListContainer.Orientation.Horizontal, spacing=4, parenting={ "horizontalAlignment": GafferUI.HorizontalAlignment.Right }, ) as infoSection: GafferUI.Label("<h4>" + node.typeName().rpartition(":")[-1] + "</h4>") button = GafferUI.Button(image="info.png", hasFrame=False) url = Gaffer.Metadata.value(node, "documentation:url") if url: button.clickedSignal().connect( lambda button: GafferUI.showURL(url), scoped=False) toolTip = "<h3>" + node.typeName().rpartition(":")[2] + "</h3>" description = Gaffer.Metadata.value(node, "description") if description: toolTip += "\n\n" + description infoSection.setToolTip(toolTip) GafferUI.MenuButton(image="gear.png", hasFrame=False, menu=GafferUI.Menu( Gaffer.WeakMethod( self.__menuDefinition))) frame = GafferUI.Frame(borderStyle=GafferUI.Frame.BorderStyle.None, borderWidth=0) self.__column.append(frame, expand=True) self.__nodeUI = GafferUI.NodeUI.create(node) self.__nodeUI.setReadOnly(self.getReadOnly()) frame.setChild(self.__nodeUI)
def callback( t ) : print t definition = IECore.MenuDefinition( [ ( "/apple/pear/banana", { "command" : lambda : callback( "banana" ) } ), ( "/apple/pear/divider", { "divider" : True } ), ( "/apple/pear/submarine", { } ), ( "/dog/inactive", { "active" : False } ), ] ) menu = GafferUI.Menu( definition ) menuBar = GafferUI.MenuBar( definition ) window = gtk.Window( gtk.WINDOW_TOPLEVEL ) window.set_size_request( 200, 100 ) window.set_title( "Menu test" ) window.connect( "delete_event", gtk.main_quit ) vbox = gtk.VBox() button = gtk.Button( "button" ) vbox.add( menuBar.gtkWidget() ) vbox.add( button ) window.add( vbox ) button.show() ## \todo Use one of the methods below to apply # a nice high end grey style to all widgets
def __init__( self, plug, **kw ) : menu = GafferUI.Menu( Gaffer.WeakMethod( self.__menuDefinition ), title="Drawing" ) menuButton = GafferUI.MenuButton( menu=menu, image = "drawingStyles.png", hasFrame=False ) GafferUI.PlugValueWidget.__init__( self, menuButton, plug, **kw )
def __headerButtonPress(self, header, event): if event.buttons != event.Buttons.Right: return False column = self._qtWidget().columnAt(event.line.p0.x) cellPlug = self._qtWidget().model().plugForIndex( self._qtWidget().model().index(0, column)) assert (cellPlug.ancestor( Gaffer.Spreadsheet.RowPlug) == cellPlug.ancestor( Gaffer.Spreadsheet.RowsPlug).defaultRow()) menuDefinition = IECore.MenuDefinition() menuDefinition.append( "/Set Label...", { "command": functools.partial(Gaffer.WeakMethod(self.__setColumnLabel), cellPlug), "active": not Gaffer.MetadataAlgo.readOnly(cellPlug), }) menuDefinition.append( "/Set Description...", { "command": functools.partial( Gaffer.WeakMethod(self.__setColumnDescription), cellPlug), "active": not Gaffer.MetadataAlgo.readOnly(cellPlug), }) sectionNames = _SectionChooser.sectionNames( self._qtWidget().model().rowsPlug()) currentSection = _SectionChooser.getSection(cellPlug) for sectionName in sectionNames: menuDefinition.append( "/Move to Section/{}".format(sectionName), { "command": functools.partial(Gaffer.WeakMethod(self.__moveToSection), cellPlug, sectionName=sectionName), "active": not Gaffer.MetadataAlgo.readOnly(cellPlug) and sectionName != currentSection, }) if sectionNames: menuDefinition.append("/Move to Section/__divider__", {"divider": True}) menuDefinition.append( "/Move to Section/New...", { "command": functools.partial(Gaffer.WeakMethod(self.__moveToSection), cellPlug), "active": not Gaffer.MetadataAlgo.readOnly(cellPlug), }) menuDefinition.append("/DeleteDivider", {"divider": True}) menuDefinition.append( "/Delete Column", { "command": functools.partial(Gaffer.WeakMethod(self.__deleteColumn), cellPlug), "active": self.__canDeleteColumn(cellPlug) }) self.__headerMenu = GafferUI.Menu(menuDefinition) self.__headerMenu.popup() return True
def _nodeMenu( self ) : if self.__nodeMenu is None : self.__nodeMenu = GafferUI.Menu( GafferUI.NodeMenu.acquire( self.scriptNode().applicationRoot() ).definition(), searchable=True ) return self.__nodeMenu
def __init__(self, plug): self.__grid = GafferUI.GridContainer(spacing=4) GafferUI.PlugValueWidget.__init__(self, self.__grid, plug) model = _PlugTableModel(plug, self.getContext(), self._qtWidget()) selectionModel = QtCore.QItemSelectionModel(model, self._qtWidget()) with self.__grid: self.__sectionChooser = _SectionChooser(plug, parenting={ "index": (1, 0), }) self.__sectionChooser.currentSectionChangedSignal().connect( Gaffer.WeakMethod(self.__currentSectionChanged), scoped=False) with GafferUI.ListContainer( parenting={ "index": (0, 1), "alignment": (GafferUI.HorizontalAlignment.Left, GafferUI.VerticalAlignment.Bottom), }): self.__defaultLabel = GafferUI.Label("Default") self.__defaultLabel._qtWidget().setIndent(6) GafferUI.Spacer(imath.V2i(1, 8)) self.__defaultTable = _PlugTableView(selectionModel, _PlugTableView.Mode.Defaults, parenting={ "index": (1, 1), }) with GafferUI.ListContainer(parenting={ "index": (2, 1), "alignment": (GafferUI.HorizontalAlignment.Left, GafferUI.VerticalAlignment.Top) }, ): GafferUI.Spacer(imath.V2i(1, 4), maximumSize=imath.V2i(1, 4)) addColumnButton = GafferUI.MenuButton( image="plus.png", hasFrame=False, toolTip="Click to add column, or drop plug to connect", menu=GafferUI.Menu( Gaffer.WeakMethod(self.__addColumnMenuDefinition))) addColumnButton.dragEnterSignal().connect(Gaffer.WeakMethod( self.__addColumnButtonDragEnter), scoped=False) addColumnButton.dragLeaveSignal().connect(Gaffer.WeakMethod( self.__addColumnButtonDragLeave), scoped=False) addColumnButton.dropSignal().connect(Gaffer.WeakMethod( self.__addColumnButtonDrop), scoped=False) self.__rowNamesTable = _PlugTableView(selectionModel, _PlugTableView.Mode.RowNames, parenting={ "index": (0, 2), }) self.__cellsTable = _PlugTableView(selectionModel, _PlugTableView.Mode.Cells, parenting={ "index": (1, 2), }) _LinkedScrollBar(GafferUI.ListContainer.Orientation.Vertical, [self.__cellsTable, self.__rowNamesTable], parenting={ "index": (2, 2), "alignment": (GafferUI.HorizontalAlignment.Left, GafferUI.VerticalAlignment.None_) }) _LinkedScrollBar(GafferUI.ListContainer.Orientation.Horizontal, [self.__cellsTable, self.__defaultTable], parenting={ "index": (1, 3), }) addRowButton = GafferUI.Button( image="plus.png", hasFrame=False, toolTip="Click to add row, or drop new row names", parenting={"index": (0, 4)}) addRowButton.clickedSignal().connect(Gaffer.WeakMethod( self.__addRowButtonClicked), scoped=False) addRowButton.dragEnterSignal().connect(Gaffer.WeakMethod( self.__addRowButtonDragEnter), scoped=False) addRowButton.dragLeaveSignal().connect(Gaffer.WeakMethod( self.__addRowButtonDragLeave), scoped=False) addRowButton.dropSignal().connect(Gaffer.WeakMethod( self.__addRowButtonDrop), scoped=False) if isinstance(plug.node(), Gaffer.Reference): # Currently we only allow new rows to be added to references # that had no rows when they were exported. We don't want to # get into merge hell trying to combine user-added and referenced # rows, particularly as we are planning to add row-reordering # features in future. for row in plug.children()[1:]: if not plug.node().isChildEdit(row): addRowButton.setVisible(False) break # Because dragging plugs to the add button involves making # an output connection from the spreadsheet, it doesn't make # sense to allow it on promoted plugs. if not isinstance(plug.node(), Gaffer.Spreadsheet): addColumnButton.setVisible(False) self.__statusLabel = GafferUI.Label( "", parenting={ "index": (slice(1, 3), 4), "alignment": (GafferUI.HorizontalAlignment.Left, GafferUI.VerticalAlignment.Top) }) # The status label occupies the same column as `cellsTable`, and has a dynamic width based on the length # of the status text. Ignore the width in X so that the column width is dictated solely by `cellsTable`, # otherwise large status labels can force cells off the screen. self.__statusLabel._qtWidget().setSizePolicy( QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Fixed) for widget in [addRowButton, addColumnButton]: widget.enterSignal().connect(Gaffer.WeakMethod( self.__enterToolTippedWidget), scoped=False) widget.leaveSignal().connect(Gaffer.WeakMethod( self.__leaveToolTippedWidget), scoped=False) for widget in [self.__defaultTable, self.__cellsTable]: widget.mouseMoveSignal().connect(Gaffer.WeakMethod( self.__cellsMouseMove), scoped=False) widget.leaveSignal().connect(Gaffer.WeakMethod(self.__cellsLeave), scoped=False) Gaffer.Metadata.plugValueChangedSignal(plug.node()).connect( Gaffer.WeakMethod(self.__plugMetadataChanged), scoped=False) self.__updateVisibleSections() self.__updateDefaultRowVisibility()
def _updateFromSet(self): GafferUI.NodeSetEditor._updateFromSet(self) del self.__column[:] self.__nodeUI = None self.__nameWidget = None node = self._lastAddedNode() if not node: return with self.__column: with GafferUI.ListContainer( GafferUI.ListContainer.Orientation.Horizontal, borderWidth=8, spacing=4): GafferUI.Label("<h4>Node Name</h4>") self.__nameWidget = GafferUI.NameWidget(node) ## \todo Make NameWidget support the readOnly metadata internally itself. # We can't do that easily right now, because it would need to be managing # the exact same `setEditable()` call that we're using here to propagate # our Widget readonlyness. Really our Widget readonlyness mechanism is a # bit lacking, and it should really be inherited automatically so we don't # have to propagate it like this. self.__nameWidget.setEditable( not self.getReadOnly() and not Gaffer.MetadataAlgo.readOnly(node)) with GafferUI.ListContainer( GafferUI.ListContainer.Orientation.Horizontal, spacing=4) as infoSection: GafferUI.Label("<h4>" + node.typeName().rpartition(":")[-1] + "</h4>") button = GafferUI.Button(image="info.png", hasFrame=False) url = Gaffer.Metadata.value(node, "documentation:url") if url: button.clickedSignal().connect( lambda button: GafferUI.showURL(url), scoped=False) toolTip = "<h3>" + node.typeName().rpartition(":")[2] + "</h3>" description = Gaffer.Metadata.nodeDescription(node) if description: toolTip += "\n\n" + description infoSection.setToolTip(toolTip) GafferUI.MenuButton(image="gear.png", hasFrame=False, menu=GafferUI.Menu( Gaffer.WeakMethod( self.__menuDefinition))) frame = GafferUI.Frame(borderStyle=GafferUI.Frame.BorderStyle.None, borderWidth=0) self.__column.append(frame, expand=True) self.__nodeUI = GafferUI.NodeUI.create(node) self.__nodeUI.setReadOnly(self.getReadOnly()) frame.setChild(self.__nodeUI)
def __init__(self, path, previewTypes=[], allowMultipleSelection=False, bookmarks=None, **kw): self.__column = GafferUI.ListContainer( GafferUI.ListContainer.Orientation.Vertical, spacing=8) GafferUI.Widget.__init__(self, self.__column, **kw) # we use this temporary path for our child widgets while constructing, and then call # self.setPath() to replace it with the real thing. this lets us avoid duplicating the # logic we need in setPath(). tmpPath = Gaffer.DictPath({}, "/") with self.__column: # row for manipulating current directory with GafferUI.ListContainer( GafferUI.ListContainer.Orientation.Horizontal, spacing=0): self.__displayModeButton = GafferUI.Button( image="pathListingTree.png", hasFrame=False) self.__displayModeButton.setToolTip( "Toggle between list and tree views") self.__displayModeButtonClickedConnection = self.__displayModeButton.clickedSignal( ).connect(Gaffer.WeakMethod(self.__displayModeButtonClicked)) self.__bookmarksButton = GafferUI.MenuButton( image="bookmarks.png", hasFrame=False, menu=GafferUI.Menu( Gaffer.WeakMethod(self.__bookmarksMenuDefinition)), ) self.__bookmarksButton.setToolTip("Bookmarks") self.__bookmarksButtonDragEnterConnection = self.__bookmarksButton.dragEnterSignal( ).connect(Gaffer.WeakMethod(self.__bookmarksButtonDragEnter)) self.__bookmarksButtonDragLeaveConnection = self.__bookmarksButton.dragLeaveSignal( ).connect(Gaffer.WeakMethod(self.__bookmarksButtonDragLeave)) self.__bookmarksButtonDropConnection = self.__bookmarksButton.dropSignal( ).connect(Gaffer.WeakMethod(self.__bookmarksButtonDrop)) reloadButton = GafferUI.Button(image="refresh.png", hasFrame=False) reloadButton.setToolTip("Refresh view") self.__reloadButtonClickedConnection = reloadButton.clickedSignal( ).connect(Gaffer.WeakMethod(self.__reloadButtonClicked)) upButton = GafferUI.Button(image="pathUpArrow.png", hasFrame=False) upButton.setToolTip("Up one level") self.__upButtonClickedConnection = upButton.clickedSignal( ).connect(Gaffer.WeakMethod(self.__upButtonClicked)) GafferUI.Spacer(IECore.V2i(4, 4)) self.__dirPathWidget = GafferUI.PathWidget(tmpPath) # directory listing and preview widget with GafferUI.SplitContainer( GafferUI.SplitContainer.Orientation.Horizontal, parenting={"expand": True}) as splitContainer: self.__directoryListing = GafferUI.PathListingWidget( tmpPath, allowMultipleSelection=allowMultipleSelection) self.__displayModeChangedConnection = self.__directoryListing.displayModeChangedSignal( ).connect(Gaffer.WeakMethod(self.__displayModeChanged)) if len(previewTypes): self.__previewWidget = GafferUI.CompoundPathPreview( tmpPath, childTypes=previewTypes) else: self.__previewWidget = None if len(splitContainer) > 1: splitContainer.setSizes( [2, 1]) # give priority to the listing over the preview # filter section self.__filterFrame = GafferUI.Frame( borderWidth=0, borderStyle=GafferUI.Frame.BorderStyle.None) self.__filter = None # path self.__pathWidget = GafferUI.PathWidget(tmpPath) self.__pathWidget.setVisible(allowMultipleSelection == False) self.__pathSelectedSignal = GafferUI.WidgetSignal() self.__listingSelectionChangedConnection = self.__directoryListing.selectionChangedSignal( ).connect(Gaffer.WeakMethod(self.__listingSelectionChanged)) self.__listingSelectedConnection = self.__directoryListing.pathSelectedSignal( ).connect(Gaffer.WeakMethod(self.__pathSelected)) self.__pathWidgetSelectedConnection = self.__pathWidget.activatedSignal( ).connect(Gaffer.WeakMethod(self.__pathSelected)) self.__path = None self.setPath(path) self.setBookmarks(bookmarks)
def __popupLayoutMenu(self, splitContainer): m = IECore.MenuDefinition() layouts = GafferUI.Layouts.acquire(self.scriptNode().applicationRoot()) for c in layouts.registeredEditors(): m.append( "/" + IECore.CamelCase.toSpaced(c), {"command": IECore.curry(self.__addChild, splitContainer, c)}) m.append("/divider", {"divider": True}) removeItemAdded = False splitContainerParent = splitContainer.parent() if isinstance(splitContainerParent, GafferUI.SplitContainer): m.append( "Remove Panel", { "command": IECore.curry( self.__join, splitContainerParent, 1 - splitContainerParent.index(splitContainer)) }) removeItemAdded = True tabbedContainer = splitContainer[0] if tabbedContainer: currentTab = tabbedContainer.getCurrent() if currentTab: m.append( "/Remove " + tabbedContainer.getLabel(currentTab), { "command": IECore.curry(self.__removeCurrentTab, tabbedContainer) }) removeItemAdded = True if removeItemAdded: m.append("/divider2", {"divider": True}) m.append( "/Split Left", { "command": IECore.curry(self.__split, splitContainer, GafferUI.SplitContainer.Orientation.Horizontal, 0) }) m.append( "/Split Right", { "command": IECore.curry(self.__split, splitContainer, GafferUI.SplitContainer.Orientation.Horizontal, 1) }) m.append( "/Split Bottom", { "command": IECore.curry(self.__split, splitContainer, GafferUI.SplitContainer.Orientation.Vertical, 1) }) m.append( "/Split Top", { "command": IECore.curry(self.__split, splitContainer, GafferUI.SplitContainer.Orientation.Vertical, 0) }) self.__layoutMenu = GafferUI.Menu( m) # must store it somewhere else it'll die self.__layoutMenu.popup()
def _updateFromSet( self ) : GafferUI.NodeSetEditor._updateFromSet( self ) focusWidget = GafferUI.Widget._owner( QtWidgets.QApplication.focusWidget() ) if self.__column.isAncestorOf( focusWidget ) : # The focus is in our editor, but it belongs to a widget we're about # to delete. Transfer the focus up so that we don't lose the focus # when we delete the widget. ## \todo Is there an argument for moving this fix to the ListContainer # itself? self.__column._qtWidget().setFocus() del self.__column[:] self.__nodeUI = None self.__nameWidget = None node = self._lastAddedNode() if not node : with self.__column : GafferUI.Spacer( imath.V2i( 0 ) ) return with self.__column : with GafferUI.ListContainer( GafferUI.ListContainer.Orientation.Horizontal, borderWidth=8, spacing=4 ) : GafferUI.Label( "<h4>Node Name</h4>" ) self.__nameWidget = GafferUI.NameWidget( node ) with GafferUI.ListContainer( GafferUI.ListContainer.Orientation.Horizontal, spacing=4, parenting = { "horizontalAlignment" : GafferUI.HorizontalAlignment.Right }, ) as infoSection : GafferUI.Label( "<h4>" + node.typeName().rpartition( ":" )[-1] + "</h4>" ) button = GafferUI.Button( image = "info.png", hasFrame = False ) url = Gaffer.Metadata.value( node, "documentation:url" ) if url : button.clickedSignal().connect( lambda button : GafferUI.showURL( url ), scoped = False ) toolTip = "# " + node.typeName().rpartition( ":" )[2] description = Gaffer.Metadata.value( node, "description" ) if description : toolTip += "\n\n" + description infoSection.setToolTip( toolTip ) GafferUI.MenuButton( image = "gear.png", hasFrame = False, menu = GafferUI.Menu( Gaffer.WeakMethod( self.__menuDefinition ) ) ) frame = GafferUI.Frame( borderStyle=GafferUI.Frame.BorderStyle.None_, borderWidth=0 ) self.__column.append( frame, expand=True ) self.__nodeUI = GafferUI.NodeUI.create( node ) self.__nodeUI.setReadOnly( self.getReadOnly() ) frame.setChild( self.__nodeUI )
def testBuildFully(self): # We count calls to our dynamic sub menu generator under a variety of # sub menu and sub sub menu scenarios. callCounts = { "subMenuA": 0, "subMenuB": 0, "subMenuC": 0, "subMenuD": 0, "subMenuDSubMenu": 0, "subMenuE": 0, "subMenuESubMenu": 0, "subMenuF": 0, "subMenuFSubMenu": 0, "subMenuI": 0 } def buildSubMenu(identifier, addChildSubMenu=False, childSubMenuHasShortCuts=True): callCounts[identifier] += 1 smd = IECore.MenuDefinition() smd.append("/%s_itemA" % identifier, {}) if addChildSubMenu: smd.append( "/%s_subMenu" % identifier, { "subMenu": functools.partial(buildSubMenu, "%sSubMenu" % identifier, False), "hasShortCuts": childSubMenuHasShortCuts }) return smd md = IECore.MenuDefinition() md.append("/staticItem1", {}) md.append("/subMenuA", {"subMenu": functools.partial(buildSubMenu, "subMenuA")}) md.append( "/subMenuB", { "subMenu": functools.partial(buildSubMenu, "subMenuB"), "hasShortCuts": False }) md.append( "/subMenuC", { "subMenu": functools.partial(buildSubMenu, "subMenuC"), "hasShortCuts": True }) # Sub sub menus under parents with/without short cuts md.append( "/subMenuD", {"subMenu": functools.partial(buildSubMenu, "subMenuD", True)}) md.append("/subMenuE", { "subMenu": functools.partial(buildSubMenu, "subMenuE", True, False) }) md.append( "/subMenuF", { "subMenu": functools.partial(buildSubMenu, "subMenuF", True), "hasShortCuts": False }) md.append("/subMenuG/staticItemA", {}) # Indirect sub sub menu md.append( "/subMenuH/implicitSubMenu/dynamicSubMenu", { "subMenu": functools.partial(buildSubMenu, "subMenuI"), "hasShortCuts": False }) # Full build m = GafferUI.Menu(md) m._buildFully() ma = m._qtWidget().actions() self.assertEqual([a.text() for a in ma], [ "staticItem1", "subMenuA", "subMenuB", "subMenuC", "subMenuD", "subMenuE", "subMenuF", "subMenuG", "subMenuH" ]) self.assertEqual([a.text() for a in ma[1].menu().actions()], ["subMenuA_itemA"]) self.assertEqual([a.text() for a in ma[2].menu().actions()], ["subMenuB_itemA"]) self.assertEqual([a.text() for a in ma[3].menu().actions()], ["subMenuC_itemA"]) self.assertEqual([a.text() for a in ma[4].menu().actions()], ["subMenuD_itemA", "subMenuD_subMenu"]) self.assertEqual( [a.text() for a in ma[4].menu().actions()[1].menu().actions()], ["subMenuDSubMenu_itemA"]) self.assertEqual([a.text() for a in ma[5].menu().actions()], ["subMenuE_itemA", "subMenuE_subMenu"]) self.assertEqual( [a.text() for a in ma[5].menu().actions()[1].menu().actions()], ["subMenuESubMenu_itemA"]) self.assertEqual([a.text() for a in ma[6].menu().actions()], ["subMenuF_itemA", "subMenuF_subMenu"]) self.assertEqual( [a.text() for a in ma[6].menu().actions()[1].menu().actions()], ["subMenuFSubMenu_itemA"]) self.assertEqual([a.text() for a in ma[7].menu().actions()], ["staticItemA"]) self.assertEqual([a.text() for a in ma[8].menu().actions()], ["implicitSubMenu"]) self.assertEqual( [a.text() for a in ma[8].menu().actions()[0].menu().actions()], ["dynamicSubMenu"]) self.assertEqual([ a.text() for a in ma[8].menu().actions()[0].menu().actions() [0].menu().actions() ], ["subMenuI_itemA"]) self.assertEqual( callCounts, { "subMenuA": 1, "subMenuB": 1, "subMenuC": 1, "subMenuD": 1, "subMenuDSubMenu": 1, "subMenuE": 1, "subMenuESubMenu": 1, "subMenuF": 1, "subMenuFSubMenu": 1, "subMenuI": 1 }) # For short cuts m = GafferUI.Menu(md) m._buildFully(forShortCuts=True) ma = m._qtWidget().actions() self.assertEqual([a.text() for a in ma], [ "staticItem1", "subMenuA", "subMenuC", "subMenuD", "subMenuE", "subMenuG", "subMenuH" ]) self.assertEqual([a.text() for a in ma[1].menu().actions()], ["subMenuA_itemA"]) self.assertEqual([a.text() for a in ma[2].menu().actions()], ["subMenuC_itemA"]) self.assertEqual([a.text() for a in ma[3].menu().actions()], ["subMenuD_itemA", "subMenuD_subMenu"]) self.assertEqual( [a.text() for a in ma[3].menu().actions()[1].menu().actions()], ["subMenuDSubMenu_itemA"]) self.assertEqual([a.text() for a in ma[4].menu().actions()], ["subMenuE_itemA"]) self.assertEqual([a.text() for a in ma[5].menu().actions()], ["staticItemA"]) self.assertEqual([a.text() for a in ma[6].menu().actions()], ["implicitSubMenu"]) self.assertEqual( [a.text() for a in ma[6].menu().actions()[0].menu().actions()], []) self.assertEqual( callCounts, { "subMenuA": 2, "subMenuB": 1, "subMenuC": 2, "subMenuD": 2, "subMenuDSubMenu": 2, "subMenuE": 2, "subMenuESubMenu": 1, "subMenuF": 1, "subMenuFSubMenu": 1, "subMenuI": 1 })
def _headerWidget(self): with GafferUI.ListContainer( GafferUI.ListContainer.Orientation.Horizontal) as result: collapseButton = GafferUI.Button(image="collapsibleArrowRight.png", hasFrame=False) self.__collapseButtonConnection = collapseButton.clickedSignal( ).connect(Gaffer.WeakMethod(self.__collapseButtonClicked)) GafferUI.Spacer(IECore.V2i(2)) # find parameters which belong in the header ############################################ preHeaderParameters = [] headerParameters = [] for parameter in self.__parameterHandler.parameter().values(): with IECore.IgnoredExceptions(KeyError): if parameter.userData( )["UI"]["classVectorParameterPreHeader"].value: preHeaderParameters.append(parameter) with IECore.IgnoredExceptions(KeyError): if parameter.userData( )["UI"]["classVectorParameterHeader"].value: headerParameters.append(parameter) # make the header ################# # things before the layer button for parameter in preHeaderParameters: GafferCortexUI.ParameterValueWidget.create( self.__parameterHandler.childParameterHandler(parameter)) # the layer button layerButton = GafferUI.MenuButton( image="classVectorParameterHandle.png", hasFrame=False) compoundPlugValueWidget = self.ancestor(_PlugValueWidget) parentParameter = compoundPlugValueWidget._parameter() cls = parentParameter.getClass( self.__parameterHandler.parameter().name, True) layerButtonToolTip = "<h3>%s v%d</h3>" % (cls[1], cls[2]) if cls[0].description: layerButtonToolTip += "<p>%s</p>" % cls[0].description layerButtonToolTip += "<p>Click to reorder or remove.</p>" layerButton.setToolTip(layerButtonToolTip) layerButton.setMenu( GafferUI.Menu( IECore.curry( Gaffer.WeakMethod( compoundPlugValueWidget._layerMenuDefinition), self.__parameterHandler.parameter().name))) GafferUI.Spacer(IECore.V2i(2)) # the label if "label" in self.getPlug(): self.__label = GafferUI.Label( self.getPlug()["label"].getValue(), horizontalAlignment=GafferUI.Label.HorizontalAlignment.Left ) self.__label._qtWidget().setFixedWidth( GafferUI.PlugWidget.labelWidth()) ## \todo Naughty! self.__label.setToolTip( compoundPlugValueWidget._parameterToolTip( self.__parameterHandler.childParameterHandler( self.__parameterHandler.parameter()["label"]), ), ) self.__labelButtonPressConnection = self.__label.buttonPressSignal( ).connect(Gaffer.WeakMethod(self.__labelButtonPress)) self.__plugSetConnection = self.getPlug().node().plugSetSignal( ).connect(Gaffer.WeakMethod(self.__plugSet)) # parameters after the label for parameter in headerParameters: GafferCortexUI.ParameterValueWidget.create( self.__parameterHandler.childParameterHandler(parameter)) # prevent things expanding in an unwanted way GafferUI.Spacer(IECore.V2i(1), IECore.V2i(999999, 1), parenting={"expand": True}) return result
def __labelButtonPress( self, label, event ) : self.__labelMenu = GafferUI.Menu( IECore.MenuDefinition( [ ( "Change label...", { "command" : Gaffer.WeakMethod( self.__changeLabel ) } ), ] ) ) self.__labelMenu.popup( parent=label )
def __init__( self, plug, **kw ) : menu = GafferUI.Menu( Gaffer.WeakMethod( self.__menuDefinition ) ) menuButton = GafferUI.MenuButton( menu=menu, image = "grid.png", hasFrame=False ) GafferUI.PlugValueWidget.__init__( self, menuButton, plug, **kw )
def __contextMenu(self, widget): definition = IECore.MenuDefinition() if widget is self.inputWidget(): definition.append( "/Execute Selection" if widget.selectedText() else "/Execute", { "command": self.execute, "shortCut": "Enter", }) definition.append("/ExecuteDivider", {"divider": True}) definition.append( "/Copy", { "command": functools.partial( self.scriptNode().ancestor( Gaffer.ApplicationRoot).setClipboardContents, IECore.StringData(widget.selectedText())), "active": bool(widget.selectedText()) }) if widget is self.inputWidget(): definition.append( "/Paste", { "command": functools.partial( widget.insertText, self.scriptNode().ancestor(Gaffer.ApplicationRoot). getClipboardContents().value, ), "active": isinstance( self.scriptNode().ancestor( Gaffer.ApplicationRoot).getClipboardContents(), IECore.StringData) }) definition.append("/CopyPasteDivider", {"divider": True}) definition.append( "/Select All", { "command": widget._qtWidget().selectAll, "active": bool(widget.getText()) }) definition.append("/SelectDivider", {"divider": True}) definition.append( "/Clear", { "command": functools.partial(widget.setText, ""), "active": bool(widget.getText()) }) self.__popupMenu = GafferUI.Menu(definition) self.__popupMenu.popup(parent=self) return True