def __init__(self, *args, **kwargs): RanaModule.__init__(self, *args, **kwargs) self.tt = 0 self.connected = False self.set('speed', None) self.set('metersPerSecSpeed', None) self.set('bearing', None) self.set('elevation', None) self.status = "Unknown" self._enabled = False self.provider = None self.startSignal = Signal() self.stopSignal = Signal() self.positionUpdate = Signal() # check if the device handles location by itself if not self.modrana.dmod.handles_location: method = self.modrana.dmod.location_type if method == "qt_mobility": self.log.info("using Qt Mobility") from . import qt_mobility self.provider = qt_mobility.QtMobility(self) elif method == "gpsd": # GPSD self.log.info("using GPSD") from . import gps_daemon self.provider = gps_daemon.GPSD(self) # watch if debugging needs to be enabled self.modrana.watch("gpsDebugEnabled", self._debugCB, runNow=True)
def __init__(self): self._objs = {} self._objs_lock = threading.RLock() self._global_index = 0 self._errors = {} self._main_thread = threading.currentThread() # signals self.thread_status_changed = Signal() self.thread_progress_changed = Signal() self.thread_removed = Signal()
def __init__(self, rendererPreset): # QtModule.QDialog.__init__(self) # # Define signals for PyQt5 # if usePySide or usePyQt5: # self.presetChanged = Signal() self.savePreset = Signal() # self.rendererPreset = rendererPreset self.labelsReady = False self.buildGui()
def __init__ ( self, rendererPreset ) : # QtModule.QDialog.__init__ ( self ) # # Define signals for PyQt5 # if usePySide or usePyQt5 : # self.presetChanged = Signal () self.savePreset = Signal () # self.rendererPreset = rendererPreset self.labelsReady = False self.buildGui ()
def __init__(self, parent, editNode=None): # QtModule.QWidget.__init__(self, parent) # # Define signals for PyQt5 # if usePySide or usePyQt5: # self.changeNodeLabel = Signal() # self.editNode = editNode #self.debugPrint() self.buildGui() self.setNode(editNode)
def __init__ ( self, parent ) : # QtModule.QGraphicsView.__init__ ( self, parent ) # # Define signals for PyQt5 # if usePySide or usePyQt5 : # self.mouseDoubleClickSignal = Signal () # self.state = 'idle' self.panStartPos = None self.pixmap = None # set scene scene = QtModule.QGraphicsScene ( self ) scene.setSceneRect ( 0, 0, 256, 256 ) #scene.setItemIndexMethod ( QtGui.QGraphicsScene.NoIndex ) self.setScene ( scene ) # qt graphics stuff #self.setCacheMode ( QtGui.QGraphicsView.CacheBackground ) self.setRenderHint ( QtGui.QPainter.Antialiasing ) self.setTransformationAnchor ( QtModule.QGraphicsView.AnchorUnderMouse ) self.setResizeAnchor ( QtModule.QGraphicsView.AnchorViewCenter ) self.setDragMode ( QtModule.QGraphicsView.RubberBandDrag ) self.setMouseTracking ( False ) self.BgBrush = QtGui.QBrush ( QtGui.QColor ( 128, 128, 128 ) )
def __init__ ( self, parent ) : # QtModule.QWidget.__init__ ( self, parent ) # # Define signals for PyQt5 # if usePySide or usePyQt5 : # self.selectionChangedSignal = Signal () self.addItem = Signal () self.removeItem = Signal () self.renameItem = Signal () # self.saved_text = '' self.approvedNewName = '' self.buildGui ()
def __init__ ( self, parent ) : # QtModule.QWidget.__init__ ( self, parent ) # # Define signals for PyQt5 # if usePySide or usePyQt5 : # self.changeParamName = Signal () self.changeParamLabel = Signal () self.changeParamIsShader = Signal () self.changeParamType = Signal () self.changeParamDetail = Signal () self.changeParamProvider = Signal () self.changeParamSubtype = Signal () self.changeParamRange = Signal () self.changeParamValue = Signal () self.changeParamDefValue = Signal () # self.param = None self.param_default = None self.paramWidgets = { 'string' : StringWidget ,'image' : StringWidget ,'rib' : StringWidget ,'surface' : StringWidget ,'displacement' : StringWidget ,'light' : StringWidget ,'volume' : StringWidget ,'float' : FloatWidget ,'int' : IntWidget ,'color' : ColorWidget ,'normal' : NormalWidget ,'transform' : PointWidget ,'point' : PointWidget ,'vector' : VectorWidget ,'matrix' : MatrixWidget ,'text' : TextWidget ,'control' : ControlWidget ,'shader' : StringWidget ,'geom' : StringWidget } self.buildGui()
def buildGui(self): # # Define signals for PyQt5 # if usePySide or usePyQt5: # self.clicked = Signal() self.ui = Ui_ColorWidget_field() self.ui.setupUi(self)
def __init__(self, *args, **kwargs): RanaModule.__init__(self, *args, **kwargs) self.notificationText = "" self.timeout = 5000 self.position = 'middle' self.expirationTimestamp = time.time() self.draw = False self.redrawn = None self.wipOverlayEnabled = Signal() self._showWorkInProgressOverlay = False self.workStartTimestamp = None self._wipOverlayText = "" # this indicates if the notification about # background processing should be shown self._tasks = {} self._tasksLock = threading.RLock() ## for WiP overlay testing #self._tasks = { # "foo" : ("foo", None), # "bar" : ("bar", None), # "baz" : ("baz", None) #} # key is an unique task name (unique for each instance of a task) # and value is a (status, progress) tuple self.tasksChanged = Signal() # connect thread manager signals to task status changes threadMgr.threadStatusChanged.connect(self.setTaskStatus) threadMgr.threadProgressChanged.connect(self.setTaskProgress) threadMgr.threadRemoved.connect(self.removeTask) # also with GTK GUI, assure screen is redrawn properly # when WiP overlay changes if gs.GUIString == "GTK": self.wipOverlayEnabled.connect(self._doRefresh) self.tasksChanged.connect(self._doRefresh) # we handle notification only with the GTK GUI and when the device module does not # support showing them if not self.modrana.dmod.hasNotificationSupport(): self.modrana.notificationTriggered.connect(self._startCustomNotificationCB)
def __init__ ( self ) : # QtModule.QWidget.__init__ ( self ) # # Define signals for PyQt5 # if usePySide or usePyQt5 : # self.nodeParamChangedSignal = Signal () self.nodeLabelChangedSignal = Signal () # self.gfxNode = None self.inputParamListTab = None self.outputParamListTab = None self.showConnected = False self.buildGui () self.updateGui () self.connectSignals ()
def __init__ ( self, parent ) : # QtModule.QWidget.__init__ ( self, parent ) # # Define signals for PyQt5 # if usePySide or usePyQt5 : # self.setActiveNodeList = Signal () self.addNode = Signal () # self.nodesLib = '' self.nodesDir = '' # This is always the same self.ui = Ui_nodeList () self.ui.setupUi ( self ) self.ui.treeView.setDragEnabled ( True ) #self.ui.treeView.setRootIsDecorated( True ) self.connectSignals () self.updateGui ()
def buildGui(self): # # Define signals for PyQt5 # if usePySide or usePyQt5: # self.clicked = Signal() # if self.param.isArray(): self.ui = Ui_ColorWidget_array() else: self.ui = Ui_ColorWidget_field() self.ui.setupUi(self)
def __init__(self, parent): # QtModule.QWidget.__init__(self, parent) # # Define signals for PyQt5 # if usePySide or usePyQt5: # self.selectionChangedSignal = Signal() self.addItem = Signal() self.removeItem = Signal() self.renameItem = Signal() # self.saved_text = '' self.approvedNewName = '' self.buildGui()
def __init__(self, parent, value=None, idx=None): # QtModule.QWidget.__init__(self, parent) # # Define signals for PyQt5 # if usePySide or usePyQt5: # self.clicked = Signal() # #print ( '>>> ColorField.init' ) self.value = value self.idx = idx self.buildGui()
def __init__(self, parent, editNode=None): # QtModule.QWidget.__init__(self, parent) # # Define signals for PyQt5 # if usePySide or usePyQt5: # self.changeNodeLabel = Signal() # self.editNode = editNode # self.debugPrint() self.buildGui() self.setNode(editNode)
def main(): parser=ArgumentParser() parser.add_argument("--log", "-l", required=True) parser.add_argument("--output", "-o", required=True) args=parser.parse_args() signal=Signal.read_3d_csv(args.log) print("Length: %d" % len(signal.time)) time_diffs=np.diff(signal.time) print("dt: %f..%f" % (min(time_diffs), max(time_diffs))) cutter=LogCutter(signal) working_figure=plt.gcf() display_signal(signal, False) #print(working_figure.number) cutter.connect(working_figure) plt.show() subsignal=Signal.get_subsignal(signal, cutter.left_bound, cutter.right_bound) Signal.save_csv(subsignal, args.output)
def __init__ ( self, param, gfxNode, ignoreSubtype = False ) : # QtModule.QWidget.__init__ ( self ) # # Define signals for PyQt5 # if usePySide or usePyQt5 : # self.nodeParamRemoved = Signal () # self.param = param self.gfxNode = gfxNode self.ignoreSubtype = ignoreSubtype # if widget is used in NodeEditor, then ignoreSubtype = True self.buildGeneralGui () self.buildGui () self.ui.updateGui ( self.param.value )
def __init__ ( self, xml_param = None, isRibParam = False ) : # super ( NodeParam, self ).__init__ () # # Define signals for PyQt5 # if usePySide or usePyQt5 : # self.paramChangedSignal = Signal () self.id = None self.name = None self.label = None self.type = None self.help = None # short description self.default = None self.value = None self.shaderParam = False self.isRibParam = isRibParam self.display = True self.enabled = True self.removable = False # extra parameter description self.detail = '' # variable, uniform self.provider = '' # primitive, connection, constant, variable, expression # ui decorative parameters self.subtype = '' self.range = '' self.space = None # actual for color, point, vector, normal, matrix self.spaceDef = None # default value space self.arraySize = None # otherwise, it should be a list of values ( or empty list ) self.defaultArray = [] self.valueArray = [] self.spaceArray = [] # array elements spaces self.spaceDefArray = [] # default array elements spaces if xml_param != None : self.parseFromXML ( xml_param )
def __init__ ( self, view ) : # QtModule.QGraphicsScene.__init__ ( self ) # # Define signals for PyQt5 # if usePySide or usePyQt5 : # self.startNodeConnector = Signal () #QtCore.pyqtSignal ( QtModule.QGraphicsObject, QtCore.QPointF ) self.traceNodeConnector = Signal () #QtCore.pyqtSignal ( QtModule.QGraphicsObject, QtCore.QPointF ) self.endNodeConnector = Signal () #QtCore.pyqtSignal ( QtModule.QGraphicsObject, QtCore.QPointF ) self.startNodeLink = Signal () #( QtModule.QGraphicsObject ) # QtModule.QGraphicsItem self.traceNodeLink = Signal () #QtCore.pyqtSignal ( QtModule.QGraphicsObject, QtCore.QPointF ) self.endNodeLink = Signal () #QtCore.pyqtSignal ( QtModule.QGraphicsObject, QtCore.QPointF ) self.onGfxNodeRemoved = Signal () #QtCore.pyqtSignal ( QtModule.QGraphicsObject ) self.onGfxLinkRemoved = Signal () #QtCore.pyqtSignal ( QtModule.QGraphicsObject ) self.nodeUpdated = Signal () #QtCore.pyqtSignal ( QtModule.QGraphicsItem ) self.gfxNodeParamChanged = Signal () #QtCore.pyqtSignal ( QtModule.QGraphicsItem, QtCore.QObject ) # self.view = view self.connectSignals ()
def onclick(self, event): click_x=event.xdata if event.button==1 and click_x<self.right_bound: self.left_bound=click_x elif event.button==3 and click_x>self.left_bound: self.right_bound=click_x for subplot_ax in self.figure.axes: if len(subplot_ax.lines) > 1: subplot_ax.lines[-1].remove() subplot_ax.lines[-1].remove() subplot_ax.axvline(x=self.left_bound, visible=True, color="yellow") subplot_ax.axvline(x=self.right_bound, visible=True, color="red") self.figure.canvas.draw() subsignal=Signal.get_subsignal(self.signal, self.left_bound, self.right_bound) if self.callback: plt.close(self.callback) self.callback=plt.figure() plt.figure(self.callback.number) display_signal(subsignal, True) plt.figure(self.figure.number)
class NodeParam ( QtCore.QObject ) : # isInput = True isRibParam = False id = 0 # # __init__ # def __init__ ( self, xml_param = None, isRibParam = False ) : # super ( NodeParam, self ).__init__ () # # Define signals for PyQt5 # if usePySide or usePyQt5 : # self.paramChangedSignal = Signal () self.id = None self.name = None self.label = None self.type = None self.help = None # short description self.default = None self.value = None self.shaderParam = False self.isRibParam = isRibParam self.display = True self.enabled = True self.removable = False # extra parameter description self.detail = '' # variable, uniform self.provider = '' # primitive, connection, constant, variable, expression # ui decorative parameters self.subtype = '' self.range = '' self.space = None # actual for color, point, vector, normal, matrix self.spaceDef = None # default value space self.arraySize = None # otherwise, it should be a list of values ( or empty list ) self.defaultArray = [] self.valueArray = [] self.spaceArray = [] # array elements spaces self.spaceDefArray = [] # default array elements spaces if xml_param != None : self.parseFromXML ( xml_param ) # # isArray # def isArray ( self ) : return ( self.arraySize is not None ) # # setup # def setup ( self, name, label = '', detail = None, provider = None ) : # self.name = name if label == '' or label is None : self.label = name else: self.label = label self.detail = detail self.provider = provider # # copy # def copy ( self ) : assert 0, 'copy needs to be implemented!' # # copySetup # def copySetup ( self, newParam ) : # #if DEBUG_MODE : print '>> NodeParam( %s ).copySetup' % self.label newParam.id = self.id newParam.name = self.name newParam.label = self.label newParam.type = self.type newParam.help = self.help newParam.isInput = self.isInput newParam.shaderParam = self.shaderParam newParam.isRibParam = self.isRibParam newParam.display = self.display newParam.enabled = self.enabled newParam.removable = self.removable newParam.detail = self.detail newParam.provider = self.provider newParam.subtype = self.subtype newParam.range = self.range newParam.space = self.space newParam.spaceDef = self.spaceDef newParam.default = copy.deepcopy ( self.default ) newParam.value = copy.deepcopy ( self.value ) newParam.arraySize = self.arraySize newParam.defaultArray = copy.deepcopy ( self.defaultArray ) newParam.valueArray = copy.deepcopy ( self.valueArray ) newParam.spaceArray = copy.deepcopy ( self.spaceArray ) newParam.spaceDefArray = copy.deepcopy ( self.spaceDefArray ) # # typeToStr # def typeToStr ( self ) : # typeStr = self.detail + ' ' + self.type if self.isRibParam : if self.isArray () : arraySize = '' if self.arraySize > 0 : arraySize = str ( self.arraySize ) typeStr += '[%s]' % arraySize return typeStr.lstrip () # # encodedTypeStr # def encodedTypeStr ( self ) : assert 0, 'encodedStr needs to be implemented!' # # setValueFromStr # def setValueFromStr ( self, strValue ) : self.value = self.valueFromStr ( strValue ) # # setDefaultFromStr # def setDefaultFromStr ( self, strValue ) : self.default = self.valueFromStr ( strValue ) # # Virtual functions # # # valueFromStr # def valueFromStr ( self, strValue ) : return strValue # # getValueToStr # def getValueToStr ( self ) : # if self.value != None : return self.valueToStr ( self.value ) else : return None # # getDefaultToStr # def getDefaultToStr ( self ) : # if self.default != None : return self.valueToStr ( self.default ) else : return None # # virtual function # def valueToStr ( self, value ) : return str ( value ) # # paramChanged # def paramChanged ( self, emitSignal = True ) : # if DEBUG_MODE : print ( '>> NodeParam.paramChanged (name = %s) emit = ' % self.name ), emitSignal if emitSignal : if usePyQt4 : self.emit ( QtCore.SIGNAL ( 'paramChangedSignal(QObject)' ), self ) else : self.paramChangedSignal.emit ( self ) # # setupUI # def setupUI ( self, subtype, range ) : # self.subtype = subtype self.range = range # # setValue # def setValue ( self, value, emitSignal = True ) : # if self.value != value : self.value = value self.paramChanged ( emitSignal ) # # removeItemFromRange # def removeItemFromRange ( self, item_label ) : # newRangeList = [] if self.range != '' : # and self.subtype == 'selector': tmp_list = str ( self.range ).split ( ':' ) for s in tmp_list : pair = s.split ( '=' ) if len ( pair ) > 1 : label = pair [0] value = pair [1] else : label = s value = s # if label != item_label : newRangeList.append ( s ) self.range = ( ':' ).join ( newRangeList ) # # renameItemInRange # def renameItemInRange ( self, item_label, newLabel ) : # newRangeList = [] if self.range != '' : # and self.subtype == 'selector': tmp_list = str ( self.range ).split ( ':' ) for s in tmp_list : pair = s.split ( '=' ) if len ( pair ) > 1 : label = pair [0] value = pair [1] else : label = s value = s # if label == item_label : s = s.replace ( label, newLabel, 1 ) # replace only label newRangeList.append ( s ) self.range = ( ':' ).join ( newRangeList ) # # parseFromXML # def parseFromXML ( self, xml_param ) : # self.name = str ( xml_param.attributes ().namedItem ( 'name' ).nodeValue () ) self.label = str ( xml_param.attributes ().namedItem ( 'label' ).nodeValue () ) if self.label == '' : self.label = self.name self.type = str ( xml_param.attributes ().namedItem ( 'type' ).nodeValue () ) self.shaderParam = xml_param.attributes ().namedItem ( 'shaderParam' ).nodeValue () == '1' self.detail = str ( xml_param.attributes ().namedItem ( 'detail' ).nodeValue () ) self.provider = str ( xml_param.attributes ().namedItem ( 'provider' ).nodeValue () ) self.subtype = str ( xml_param.attributes ().namedItem ( 'subtype' ).nodeValue () ) self.range = str ( xml_param.attributes ().namedItem ( 'range' ).nodeValue () ) self.display = True if not xml_param.attributes ().namedItem ( 'display' ).isNull () : self.display = xml_param.attributes ().namedItem ( 'display' ).nodeValue () == '1' self.enabled = True if not xml_param.attributes ().namedItem ( 'enabled' ).isNull () : self.enabled = xml_param.attributes ().namedItem ( 'enabled' ).nodeValue () == '1' self.removable = False if not xml_param.attributes ().namedItem ( 'removable' ).isNull () : self.removable = xml_param.attributes ().namedItem ( 'removable' ).nodeValue () == '1' if not xml_param.attributes ().namedItem ( 'space' ).isNull () : space = str ( xml_param.attributes ().namedItem ( 'space' ).nodeValue () ) if space != '' : self.space = space self.spaceDef = space if not xml_param.attributes ().namedItem ( 'spaceDef' ).isNull () : spaceDef = str ( xml_param.attributes ().namedItem ( 'spaceDef' ).nodeValue () ) if spaceDef != '' : self.spaceDef = space if not xml_param.attributes ().namedItem ( 'arraySize' ).isNull () : self.arraySize = int ( xml_param.attributes ().namedItem ( 'arraySize' ).nodeValue () ) self.setDefaultFromStr ( xml_param.attributes ().namedItem ( 'default' ).nodeValue () ) # after reading array values, space for each element is stored to self.spaceArray, # so we need to copy it to self.spaceDefArray for default value self.spaceDefArray = copy.deepcopy ( self.spaceArray ) if not xml_param.attributes ().namedItem ( 'value' ).isNull () : self.setValueFromStr ( xml_param.attributes ().namedItem ( 'value' ).nodeValue () ) else : self.value = copy.deepcopy ( self.default ) help_tag = xml_param.namedItem ( 'help' ) if not help_tag.isNull () : self.help = str ( help_tag.toElement ().text () ) # # parseToXML # def parseToXML ( self, dom ) : # xmlnode = dom.createElement( 'property' ) if self.name != None : xmlnode.setAttribute ( 'name', self.name ) if self.label != None : xmlnode.setAttribute ( 'label', self.label ) if self.type != None : xmlnode.setAttribute ( 'type', self.type ) if self.shaderParam : xmlnode.setAttribute ( 'shaderParam', True ) if not self.display : xmlnode.setAttribute ( 'display', False ) if not self.enabled : xmlnode.setAttribute ( 'enabled', False ) if self.removable : xmlnode.setAttribute ( 'removable', True ) if self.detail != '' : xmlnode.setAttribute ( 'detail', self.detail ) if self.provider != '' : xmlnode.setAttribute ( 'provider', self.provider ) # ui decorative parameters if self.subtype != '' : xmlnode.setAttribute ( 'subtype', self.subtype ) if self.range != '' : xmlnode.setAttribute ( 'range', self.range ) if self.space != None : if self.space != '' : xmlnode.setAttribute ( 'space', self.space ) # write default value space only if it differs from value space if self.spaceDef != None : if self.spaceDef != '' and self.spaceDef != self.space : xmlnode.setAttribute ( 'spaceDef', self.spaceDef ) if self.default != None : value = self.getDefaultToStr () if not self.type in VALID_RIB_NODE_TYPES : value = value.strip ( '\"' ) xmlnode.setAttribute ( 'default', value ) if self.value != None : value = self.getValueToStr () if not self.type in VALID_RIB_NODE_TYPES : value = value.strip ( '\"' ) xmlnode.setAttribute ( 'value', value ) if self.arraySize != None : xmlnode.setAttribute ( 'arraySize', self.arraySize ) if self.help != None : # append node help (short description) help_tag = dom.createElement ( 'help' ) help_text = dom.createTextNode ( self.help ) help_tag.appendChild ( help_text ) xmlnode.appendChild ( help_tag ) return xmlnode
class meRendererSetup ( QtModule.QDialog ) : # # __init__ # def __init__ ( self, rendererPreset ) : # QtModule.QDialog.__init__ ( self ) # # Define signals for PyQt5 # if usePySide or usePyQt5 : # self.presetChanged = Signal () self.savePreset = Signal () # self.rendererPreset = rendererPreset self.labelsReady = False self.buildGui () # # buildGui # def buildGui ( self ) : # build the gui created with QtDesigner import sys self.ui = Ui_meRendererSetup () self.ui.setupUi ( self ) font = QtGui.QFont () if ( sys.platform == 'win32' ) : # Runing on windows, override font sizes from Designer to default font.setPointSize ( 8 ) else : font.setPointSize ( 10 ) self.ui.labelPreset.setFont ( font ) self.ui.listPreset.setFont ( font ) self.ui.newButton.setFont ( font ) self.ui.deleteButton.setFont ( font ) self.ui.cancelButton.setFont ( font ) self.ui.okButton.setFont ( font ) self.ui.saveButton.setFont ( font ) self.ui.tabs.setFont ( font ) self.ui.labelName.setFont ( font ) self.ui.labelCmd.setFont ( font ) self.ui.labelFlags.setFont ( font ) self.ui.labelCompiler.setFont ( font ) self.ui.labelShaderInfo.setFont ( font ) self.ui.labelDefines.setFont ( font ) self.ui.labelShaderExt.setFont ( font ) self.ui.labelShaderExt.setFont ( font ) self.ui.labelTexMake.setFont ( font ) self.ui.labelTexInfo.setFont ( font ) self.ui.labelTexViewer.setFont ( font ) self.ui.labelTexExt.setFont ( font ) self.labelsReady = False for label in self.rendererPreset.getPresetNames () : self.ui.listPreset.addItem ( label ) self.labelsReady = True presetName = self.rendererPreset.getCurrentPresetName () idx = self.ui.listPreset.findText ( presetName ) print ">> buildGui:: set current renderer to: %s (%d)" % ( presetName, idx ) #self.ui.listPreset.setCurrentIndex ( -1 ) self.ui.listPreset.setCurrentIndex ( idx ) # # getDataFromGui # def getDataFromGui ( self ) : # ckeck if current_renderer still exists after deleting preset #print ">> getDataFromGui:: current renderer to: %s" % self.rendererPreset.getCurrentPresetName() self.rendererPreset.currentPreset.RendererName = str ( self.ui.lineCmd.text () ) self.rendererPreset.currentPreset.RendererFlags = str ( self.ui.lineFlags.text () ) self.rendererPreset.currentPreset.ShaderCompiler = str ( self.ui.lineCompiler.text () ) self.rendererPreset.currentPreset.ShaderInfo = str ( self.ui.lineShaderInfo.text () ) self.rendererPreset.currentPreset.ShaderDefines = str ( self.ui.lineDefines.text () ) self.rendererPreset.currentPreset.ShaderExt = str ( self.ui.lineShaderExt.text () ) self.rendererPreset.currentPreset.TextureMake = str ( self.ui.lineTexMake.text () ) self.rendererPreset.currentPreset.TextureInfo = str ( self.ui.lineTexInfo.text () ) self.rendererPreset.currentPreset.TextureViewer = str ( self.ui.lineTexViewer.text () ) self.rendererPreset.currentPreset.TextureExt = str ( self.ui.lineTexExt.text () ) # # onIndexChanged # def onIndexChanged ( self, name ) : if DEBUG_MODE : print ">> onIndexChanged:: nam = %s self.labelsReady == %d" % ( name, self.labelsReady ) #if DEBUG_MODE : print self.ui.listPreset.currentText () name = self.ui.listPreset.currentText () if ( self.labelsReady and name != '' ) : # change current renderer self.rendererPreset.setCurrentPresetByName ( str ( name ) ) self.updateGui () # # updateGui # def updateGui ( self ) : # redraw gui elements #print ">> updateGui:: current renderer: %s" % self.rendererPreset.getCurrentPresetName() if len ( self.rendererPreset.presetsList ) > 0 : if self.rendererPreset.currentPreset is not None : self.ui.lineName.setText ( self.rendererPreset.getCurrentPresetName () ) self.ui.lineCmd.setText ( self.rendererPreset.currentPreset.RendererName ) self.ui.lineFlags.setText ( self.rendererPreset.currentPreset.RendererFlags ) self.ui.lineCompiler.setText ( self.rendererPreset.currentPreset.ShaderCompiler ) self.ui.lineShaderInfo.setText ( self.rendererPreset.currentPreset.ShaderInfo ) self.ui.lineDefines.setText ( self.rendererPreset.currentPreset.ShaderDefines ) self.ui.lineShaderExt.setText ( self.rendererPreset.currentPreset.ShaderExt ) self.ui.lineTexMake.setText ( self.rendererPreset.currentPreset.TextureMake ) self.ui.lineTexInfo.setText ( self.rendererPreset.currentPreset.TextureInfo ) self.ui.lineTexViewer.setText ( self.rendererPreset.currentPreset.TextureViewer ) self.ui.lineTexExt.setText ( self.rendererPreset.currentPreset.TextureExt ) self.ui.deleteButton.setEnabled ( True ) self.ui.tab1.setEnabled ( True ) self.ui.tab2.setEnabled ( True) self.ui.tab3.setEnabled ( True ) else : self.ui.deleteButton.setEnabled ( False ) self.ui.tab1.setEnabled ( False ) self.ui.tab2.setEnabled ( False ) self.ui.tab3.setEnabled ( False ) self.ui.lineName.clear () self.ui.lineCmd.clear () self.ui.lineFlags.clear () self.ui.lineCompiler.clear () self.ui.lineShaderInfo.clear () self.ui.lineDefines.clear () self.ui.lineShaderExt.clear () self.ui.lineTexMake.clear () self.ui.lineTexInfo.clear () self.ui.lineTexViewer.clear () self.ui.lineTexExt.clear () # # onNewPreset # def onNewPreset ( self ) : # create new empty preset title = 'Untitled' newLabel = title #self.labelsReady = False i = 0 while True : if newLabel in self.rendererPreset.getPresetNames () : newLabel = title + str ( i ) i += 1 continue else : break; self.rendererPreset.addPreset ( newLabel ) #self.labelsReady = True self.ui.listPreset.addItem ( newLabel ) idx = self.ui.listPreset.findText ( newLabel ) self.ui.listPreset.setCurrentIndex ( -1 ) self.ui.listPreset.setCurrentIndex ( idx ) #self.updateGui () # # onDeletePreset # def onDeletePreset ( self ) : # delete existing preset if len ( self.rendererPreset.presetsList ) > 0 : msgBox = QtModule.QMessageBox () ret = msgBox.warning ( self, 'Warning', "Do you really want to delete this preset?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.No ) if ret == QtModule.QMessageBox.Yes : self.rendererPreset.deleteCurrentPreset () i = self.ui.listPreset.currentIndex () self.ui.listPreset.removeItem ( i ) self.rendererPreset.setCurrentPresetByName ( str ( self.ui.listPreset.currentText () ) ) # # onEditLabel # def onEditLabel ( self ) : # edit label newLabel = str ( self.ui.lineName.text () ) if ( self.rendererPreset.getCurrentPresetName () != newLabel ) : if newLabel not in self.rendererPreset.getPresetNames () : self.rendererPreset.renameCurrentPreset ( newLabel ) # rename current preset ComboBox item to new label i = self.ui.listPreset.currentIndex () self.ui.listPreset.setItemText ( i, newLabel ) else : # this label already exists, so restore to previose self.ui.lineName.setText ( self.rendererPreset.getCurrentPresetName () ) # # onSave # def onSave ( self ) : # get data from Gui for current renderer before saving self.getDataFromGui () if usePyQt4 : self.emit ( QtCore.SIGNAL ( 'presetChanged' ) ) self.emit ( QtCore.SIGNAL ( 'savePreset' ) ) else : self.presetChanged.emit () self.savePreset.emit () #self.done ( 0 ) # # onSelect # def onSelect ( self ) : # get data from Gui for current renderer before saving self.getDataFromGui () if usePyQt4 : self.emit( QtCore.SIGNAL ( 'presetChanged' ) ) else : self.presetChanged.emit () self.done ( 0 )
class NodeNamesEditor ( QtModule.QWidget ) : # # __init__ # def __init__ ( self, parent ) : # QtModule.QWidget.__init__ ( self, parent ) # # Define signals for PyQt5 # if usePySide or usePyQt5 : # self.selectionChangedSignal = Signal () self.addItem = Signal () self.removeItem = Signal () self.renameItem = Signal () # self.saved_text = '' self.approvedNewName = '' self.buildGui () # # buildGui # def buildGui ( self ): # build the gui created with QtDesigner self.ui = Ui_NodeNamesEditor ( ) self.ui.setupUi ( self ) # # setName # def setName ( self, newName ) : # if newName == '' : if self.saved_text != '' : newName = self.saved_text self.ui.name_lineEdit.setText ( newName ) self.saved_text = newName # # onAddItem # def onAddItem ( self ) : # if DEBUG_MODE : print '>> NodeNamesEditor: onAddItem' new_text = str ( self.ui.name_lineEdit.text () ).strip () if new_text != '' : if usePyQt4 : self.emit ( QtCore.SIGNAL ( 'addItem' ), new_text ) else : self.addItem.emit ( new_text ) # # onRemoveItem # def onRemoveItem ( self ) : # if DEBUG_MODE : print '>> NodeNamesEditor::onRemoveItem' list_item = self.ui.listWidget.currentItem () if list_item is not None : item_text = str ( list_item.text () ) #self.ui.listWidget.takeItem ( self.ui.listWidget.currentRow () ) #self.ui.listWidget.removeItemWidget ( list_item ) if usePyQt4 : self.emit ( QtCore.SIGNAL ( 'removeItem' ), item_text ) else : self.removeItem.emit ( item_text ) # # onRenameItem # def onRenameItem ( self ) : # if DEBUG_MODE : print '>> NodeNamesEditor.onRenameItem' new_text = str ( self.ui.name_lineEdit.text () ).strip () if new_text == '' : if self.saved_text != '' : new_text = self.saved_text self.ui.name_lineEdit.setText ( new_text ) list_item = self.ui.listWidget.currentItem () if list_item is not None : # e.g. listWidget is not empty old_text = list_item.text () if new_text != old_text : if usePyQt4 : self.emit ( QtCore.SIGNAL( 'renameItem' ), old_text, new_text ) else : self.renameItem.emit ( old_text, new_text ) else : self.ui.listWidget.clearSelection () self.ui.listWidget.setCurrentItem ( None ) # # onSelectionChanged # def onSelectionChanged ( self ) : # if DEBUG_MODE : print '>> NodeNamesEditor.onSelectionChanged' list_item = self.ui.listWidget.currentItem () if list_item is not None : self.saved_text = str ( list_item.text() ) self.ui.name_lineEdit.setText ( self.saved_text ) if usePyQt4 : self.emit ( QtCore.SIGNAL ( 'selectionChangedSignal' ), self.saved_text ) else : self.selectionChangedSignal.emit ( self.saved_text )
class ImageView ( QtModule.QGraphicsView ) : # # __init__ # def __init__ ( self, parent ) : # QtModule.QGraphicsView.__init__ ( self, parent ) # # Define signals for PyQt5 # if usePySide or usePyQt5 : # self.mouseDoubleClickSignal = Signal () # self.state = 'idle' self.panStartPos = None self.pixmap = None # set scene scene = QtModule.QGraphicsScene ( self ) scene.setSceneRect ( 0, 0, 256, 256 ) #scene.setItemIndexMethod ( QtGui.QGraphicsScene.NoIndex ) self.setScene ( scene ) # qt graphics stuff #self.setCacheMode ( QtGui.QGraphicsView.CacheBackground ) self.setRenderHint ( QtGui.QPainter.Antialiasing ) self.setTransformationAnchor ( QtModule.QGraphicsView.AnchorUnderMouse ) self.setResizeAnchor ( QtModule.QGraphicsView.AnchorViewCenter ) self.setDragMode ( QtModule.QGraphicsView.RubberBandDrag ) self.setMouseTracking ( False ) self.BgBrush = QtGui.QBrush ( QtGui.QColor ( 128, 128, 128 ) ) # # keyPressEvent # def keyPressEvent ( self, event ) : # print ">> ImageView.keyPressEvent" QtModule.QGraphicsView.keyPressEvent ( self, event) # # wheelEvent # def wheelEvent ( self, event ) : # #print ">> ImageView.wheelEvent" # QtGui.QGraphicsView.wheelEvent( self, event) import sys scale = -1.0 if 'linux' in sys.platform: scale = 1.0 import math if not usePyQt5 : scaleFactor = math.pow( 2.0, scale * event.delta() / 600.0 ) else : delta = event.angleDelta () #print ( '>> delta rx = %d ry = %d' % ( delta.x (), delta.y () ) ) scaleFactor = math.pow( 2.0, scale * delta.y () / 600.0 ) # self.matrix () is depicated factor = self.transform ().scale ( scaleFactor, scaleFactor ).mapRect ( QtCore.QRectF ( -1, -1, 2, 2 ) ).width () if factor < 0.07 or factor > 100: return self.scale ( scaleFactor, scaleFactor ) # # mousePressEvent # def mousePressEvent ( self, event ) : # #print ">> ImageView.mousePressEvent" if ( event.button () == QtCore.Qt.MidButton or ( event.button () == QtCore.Qt.LeftButton and event.modifiers () == QtCore.Qt.ShiftModifier ) ) : if self.state == 'idle': self.panStartPos = self.mapToScene ( event.pos () ) self.state = 'pan' return QtModule.QGraphicsView.mousePressEvent ( self, event ) # # mouseDoubleClickEvent # def mouseDoubleClickEvent ( self, event ) : # #print ">> ImageView.mouseDoubleClickEvent" if usePyQt4 : self.emit ( QtCore.SIGNAL ( 'mouseDoubleClickSignal' ) ) else : self.mouseDoubleClickSignal.emit () QtModule.QGraphicsView.mouseDoubleClickEvent ( self, event ) # # mouseMoveEvent # def mouseMoveEvent ( self, event ) : # #print ">> ImageView.mouseMoveEvent" if self.state == 'pan' : panCurrentPos = self.mapToScene ( event.pos () ) panDeltaPos = panCurrentPos - self.panStartPos # update view matrix self.setInteractive ( False ) self.translate ( panDeltaPos.x (), panDeltaPos.y () ) self.setInteractive ( True ) else : QtModule.QGraphicsView.mouseMoveEvent ( self, event ) # # mouseReleaseEvent # def mouseReleaseEvent ( self, event ): # #print ">> ImageView.mouseReleaseEvent" if self.state == 'pan' : self.state = 'idle' self.panStartPos = None QtModule.QGraphicsView.mouseReleaseEvent ( self, event ) # # viewportEvent # def viewportEvent ( self, event ) : #case QEvent::TouchBegin: # case QEvent::TouchUpdate: # case QEvent::TouchEnd: if event.type () == QtCore.QEvent.TouchBegin : print ">> ImageView: QEvent.TouchBegin" return QtModule.QGraphicsView.viewportEvent ( self, event ) # # setImage # def setImage ( self, imageName ) : # self.pixmap = QtGui.QPixmap () wi = 256 hi = 256 if imageName != '' : print ">> ImageView.setImage name = %s" % imageName imageReader = QtGui.QImageReader ( imageName ) if imageReader.canRead () : image = imageReader.read () if not self.pixmap.convertFromImage ( image ) : print "!! QPixmap can't convert %s" % imageName else: print "!! QImageReader can't read %s..." % imageName # print imageReader.supportedImageFormats () print "!! Lets try PIL module ..." import Image image = Image.open ( imageName ) # image.verify() import os from global_vars import app_global_vars tmpname = app_global_vars [ 'TempPath' ] + '/' + os.path.basename ( imageName + '.png' ) print "** Save %s ..." % tmpname image.save ( tmpname ) self.pixmap = QtGui.QPixmap ( tmpname ) if not self.pixmap.isNull (): wi = self.pixmap.width () hi = self.pixmap.height () else: print "!! ImageView: isNull()" self.scene ().setSceneRect ( 0, 0, wi, hi ) self.scene ().update () # # drawBackground # def drawBackground ( self, painter, rect ) : # painter.setRenderHint ( QtGui.QPainter.Antialiasing ) painter.setRenderHint ( QtGui.QPainter.SmoothPixmapTransform ) painter.fillRect ( rect, self.BgBrush ) if self.pixmap is not None: painter.drawPixmap ( 0, 0, self.pixmap ) # # resetZoom # def resetZoom ( self ) : # self.setInteractive ( False ) self.resetTransform () self.setInteractive ( True )
class NodeParamEditor ( QtModule.QWidget ) : # # __init__ # def __init__ ( self, parent ) : # QtModule.QWidget.__init__ ( self, parent ) # # Define signals for PyQt5 # if usePySide or usePyQt5 : # self.changeParamName = Signal () self.changeParamLabel = Signal () self.changeParamIsShader = Signal () self.changeParamType = Signal () self.changeParamDetail = Signal () self.changeParamProvider = Signal () self.changeParamSubtype = Signal () self.changeParamRange = Signal () self.changeParamValue = Signal () self.changeParamDefValue = Signal () # self.param = None self.param_default = None self.paramWidgets = { 'string' : StringWidget ,'image' : StringWidget ,'rib' : StringWidget ,'surface' : StringWidget ,'displacement' : StringWidget ,'light' : StringWidget ,'volume' : StringWidget ,'float' : FloatWidget ,'int' : IntWidget ,'color' : ColorWidget ,'normal' : NormalWidget ,'transform' : PointWidget ,'point' : PointWidget ,'vector' : VectorWidget ,'matrix' : MatrixWidget ,'text' : TextWidget ,'control' : ControlWidget ,'shader' : StringWidget ,'geom' : StringWidget } self.buildGui() # # def __delete__ ( self, obj ) : # print '* NodeParamEditor closed... %s' % str( obj ) # # buildGui # def buildGui ( self ) : # build the gui created with QtDesigner self.ui = Ui_NodeParamEditor ( ) self.ui.setupUi ( self ) # correct UI sizes for some controls self.ui.check_enabled.setMinimumSize ( QtCore.QSize ( UI.CHECK_WIDTH, UI.HEIGHT ) ) self.ui.check_enabled.setMaximumSize ( QtCore.QSize ( UI.CHECK_WIDTH, UI.HEIGHT ) ) self.ui.check_display.setMinimumSize ( QtCore.QSize ( UI.CHECK_WIDTH, UI.HEIGHT ) ) self.ui.check_display.setMaximumSize ( QtCore.QSize ( UI.CHECK_WIDTH, UI.HEIGHT ) ) self.ui.check_shader.setMinimumSize ( QtCore.QSize ( UI.CHECK_WIDTH, UI.HEIGHT ) ) self.ui.check_shader.setMaximumSize ( QtCore.QSize ( UI.CHECK_WIDTH, UI.HEIGHT ) ) for label in VALID_PARAM_TYPES : self.ui.type_comboBox.addItem ( label ) self.ui.type_comboBox.setCurrentIndex ( -1 ) self.ui.type_comboBox.setMinimumSize ( QtCore.QSize ( UI.COMBO_WIDTH, UI.COMBO_HEIGHT ) ) self.ui.type_comboBox.setMaximumSize ( QtCore.QSize( UI.MAX, UI.COMBO_HEIGHT ) ) # temporary disabled, until "how to do it gracefully" will be clear ... self.ui.type_comboBox.setEnabled ( False ) for label in [ 'None', 'uniform', 'varying', ] : self.ui.detail_comboBox.addItem ( label ) self.ui.detail_comboBox.setCurrentIndex ( -1 ) self.ui.detail_comboBox.setMinimumSize ( QtCore.QSize ( UI.COMBO_WIDTH, UI.COMBO_HEIGHT ) ) self.ui.detail_comboBox.setMaximumSize ( QtCore.QSize( UI.MAX, UI.COMBO_HEIGHT ) ) for label in [ 'None', 'internal', 'external', 'primitive', 'attribute' ] : self.ui.provider_comboBox.addItem ( label ) self.ui.provider_comboBox.setCurrentIndex ( -1 ) self.ui.provider_comboBox.setMinimumSize ( QtCore.QSize ( UI.COMBO_WIDTH, UI.COMBO_HEIGHT ) ) self.ui.provider_comboBox.setMaximumSize ( QtCore.QSize( UI.MAX, UI.COMBO_HEIGHT ) ) for label in [ 'None', 'slider', 'switch', 'selector', 'file', 'button' ] : self.ui.subtype_comboBox.addItem ( label ) self.ui.subtype_comboBox.setCurrentIndex ( -1 ) self.ui.subtype_comboBox.setMinimumSize ( QtCore.QSize ( UI.COMBO_WIDTH, UI.COMBO_HEIGHT ) ) self.ui.subtype_comboBox.setMaximumSize ( QtCore.QSize( UI.MAX, UI.COMBO_HEIGHT ) ) # # As paramWidet is monitoring a change of param.value only, # we need to cynchronize changing of param_default.value with param.default # def onParamDefValueChanged ( self, param ) : # if DEBUG_MODE : print '* onParamDefValueChanged' self.param.default = self.param_default.value if usePyQt4 : self.emit ( QtCore.SIGNAL ( 'changeParamDefValue' ), self.param ) else : self.changeParamDefValue.emit ( self.param ) # # onParamValueChanged # def onParamValueChanged ( self, param ) : # if DEBUG_MODE : print '* onParamValueChanged' self.param.value = param.value if usePyQt4 : self.emit ( QtCore.SIGNAL ( 'changeParamValue' ), self.param ) else : self.changeParamValue.emit ( self.param ) # # connectSignals # def connectSignals ( self ) : # if usePyQt4 : self.connect ( self.param_default, QtCore.SIGNAL ( 'paramChangedSignal(QObject)' ), self.onParamDefValueChanged ) self.connect ( self.param, QtCore.SIGNAL ( 'paramChangedSignal(QObject)' ), self.onParamValueChanged ) self.connect ( self.ui.name_lineEdit, QtCore.SIGNAL ( 'editingFinished()' ), self.onEditParamName ) self.connect ( self.ui.label_lineEdit, QtCore.SIGNAL ( 'editingFinished()' ), self.onEditParamLabel ) self.connect ( self.ui.check_enabled, QtCore.SIGNAL ( 'stateChanged(int)' ), self.onEditParamEnabled ) self.connect ( self.ui.check_display, QtCore.SIGNAL ( 'stateChanged(int)' ), self.onEditParamDisplay ) self.connect ( self.ui.check_shader, QtCore.SIGNAL ( 'stateChanged(int)' ), self.onEditParamShader ) self.connect ( self.ui.type_comboBox, QtCore.SIGNAL ( 'activated(int)' ), self.onEditParamType ) self.connect ( self.ui.detail_comboBox, QtCore.SIGNAL ( 'activated(int)' ), self.onEditParamDetail ) self.connect ( self.ui.provider_comboBox, QtCore.SIGNAL ( 'activated(int)' ), self.onEditParamProvider ) self.connect ( self.ui.subtype_comboBox, QtCore.SIGNAL ( 'activated(int)' ), self.onEditParamSubtype ) self.connect ( self.ui.range_lineEdit, QtCore.SIGNAL ( 'editingFinished()' ), self.onEditParamRange ) self.connect ( self.ui.descr_plainTextEdit, QtCore.SIGNAL ( 'textChanged()' ), self.onEditParamHelp ) else : self.param_default.paramChangedSignal.connect ( self.onParamDefValueChanged ) self.param.paramChangedSignal.connect ( self.onParamValueChanged ) self.ui.name_lineEdit.editingFinished.connect ( self.onEditParamName ) self.ui.label_lineEdit.editingFinished.connect ( self.onEditParamLabel ) self.ui.check_enabled.stateChanged.connect ( self.onEditParamEnabled ) self.ui.check_display.stateChanged.connect ( self.onEditParamDisplay ) self.ui.check_shader.stateChanged.connect ( self.onEditParamShader ) self.ui.type_comboBox.activated.connect ( self.onEditParamType ) self.ui.detail_comboBox.activated.connect ( self.onEditParamDetail ) self.ui.provider_comboBox.activated.connect ( self.onEditParamProvider ) self.ui.subtype_comboBox.activated.connect ( self.onEditParamSubtype ) self.ui.range_lineEdit.editingFinished.connect ( self.onEditParamRange ) self.ui.descr_plainTextEdit.textChanged.connect ( self.onEditParamHelp ) # # disconnectSignals # def disconnectSignals ( self ) : # if usePyQt4 : if self.param_default is not None : self.disconnect ( self.param_default, QtCore.SIGNAL ( 'paramChangedSignal(QObject)' ), self.onParamDefValueChanged ) if self.param is not None : self.disconnect ( self.param, QtCore.SIGNAL ( 'paramChangedSignal(QObject)' ), self.onParamValueChanged ) self.disconnect ( self.ui.name_lineEdit, QtCore.SIGNAL ( 'editingFinished()' ), self.onEditParamName ) self.disconnect ( self.ui.label_lineEdit, QtCore.SIGNAL ( 'editingFinished()' ), self.onEditParamLabel ) self.disconnect ( self.ui.check_enabled, QtCore.SIGNAL ( 'stateChanged(int)' ), self.onEditParamEnabled ) self.disconnect ( self.ui.check_display, QtCore.SIGNAL ( 'stateChanged(int)' ), self.onEditParamDisplay ) self.disconnect ( self.ui.check_shader, QtCore.SIGNAL ( 'stateChanged(int)' ), self.onEditParamShader ) self.disconnect ( self.ui.type_comboBox, QtCore.SIGNAL ( 'activated(int)' ), self.onEditParamType ) self.disconnect ( self.ui.detail_comboBox, QtCore.SIGNAL ( 'activated(int)' ), self.onEditParamDetail ) self.disconnect ( self.ui.provider_comboBox, QtCore.SIGNAL ( 'activated(int)' ), self.onEditParamProvider ) self.disconnect ( self.ui.subtype_comboBox, QtCore.SIGNAL ( 'activated(int)' ), self.onEditParamSubtype ) self.disconnect ( self.ui.descr_plainTextEdit, QtCore.SIGNAL ( 'textChanged()' ), self.onEditParamHelp ) else : if self.param_default is not None : self.param_default.paramChangedSignal.disconnect ( self.onParamDefValueChanged ) if self.param is not None : self.param.paramChangedSignal.disconnect ( self.onParamValueChanged ) self.ui.name_lineEdit.editingFinished.disconnect ( self.onEditParamName ) self.ui.label_lineEdit.editingFinished.disconnect ( self.onEditParamLabel ) self.ui.check_enabled.stateChanged.disconnect ( self.onEditParamEnabled ) self.ui.check_display.stateChanged.disconnect ( self.onEditParamDisplay ) self.ui.check_shader.stateChanged.disconnect ( self.onEditParamShader ) self.ui.type_comboBox.activated.disconnect ( self.onEditParamType ) self.ui.detail_comboBox.activated.disconnect ( self.onEditParamDetail ) self.ui.provider_comboBox.activated.disconnect ( self.onEditParamProvider ) self.ui.subtype_comboBox.activated.disconnect ( self.onEditParamSubtype ) self.ui.range_lineEdit.editingFinished.disconnect ( self.onEditParamRange ) self.ui.descr_plainTextEdit.textChanged.disconnect ( self.onEditParamHelp ) # # reset # def reset ( self ) : # self.ui.name_lineEdit.setText ( '' ) self.ui.label_lineEdit.setText ( '' ) self.ui.check_enabled.setChecked ( True ) self.ui.check_display.setChecked ( True ) self.ui.check_shader.setChecked ( False ) self.ui.type_comboBox.setCurrentIndex( -1 ) self.ui.detail_comboBox.setCurrentIndex ( -1 ) self.ui.provider_comboBox.setCurrentIndex ( -1 ) self.ui.subtype_comboBox.setCurrentIndex ( -1 ) self.ui.range_lineEdit.setText ( '' ) doc = QtGui.QTextDocument () doc.setPlainText ( '' ) layout = QtModule.QPlainTextDocumentLayout ( doc ) doc.setDocumentLayout ( layout ) self.ui.descr_plainTextEdit.setDocument ( doc ) # # Remove stackedWidget's layout every time, # when current parameter (or it's type) is changing # def removeValueWidget ( self ) : # while True : currentWidget = self.ui.value_stackedWidget.currentWidget () if currentWidget is not None : #print '> removeWidget: %s' % str( currentWidget ) self.ui.value_stackedWidget.removeWidget ( currentWidget ) else : break # # setParam # def setParam ( self, param ) : # self.removeValueWidget() self.disconnectSignals() self.param = param if self.param is not None : #import copy self.param_default = self.param.copy() # duplicate param for default value editing self.param_default.value = param.default self.ui.name_lineEdit.setText ( self.param.name ) self.ui.label_lineEdit.setText ( self.param.label ) self.ui.check_enabled.setChecked ( self.param.enabled ) self.ui.check_display.setChecked ( self.param.display ) self.ui.check_shader.setChecked ( self.param.shaderParam ) self.ui.type_comboBox.setCurrentIndex ( self.ui.type_comboBox.findText ( self.param.type ) ) self.ui.detail_comboBox.setCurrentIndex ( self.ui.detail_comboBox.findText ( self.param.detail ) ) self.ui.provider_comboBox.setCurrentIndex ( self.ui.provider_comboBox.findText ( self.param.provider ) ) self.ui.subtype_comboBox.setCurrentIndex ( self.ui.subtype_comboBox.findText ( self.param.subtype ) ) self.ui.range_lineEdit.setText ( self.param.range ) doc = QtGui.QTextDocument () help_text = '' if self.param.help != None : help_text = self.param.help doc.setPlainText ( help_text ) layout = QtModule.QPlainTextDocumentLayout ( doc ) doc.setDocumentLayout( layout ) self.ui.descr_plainTextEdit.setDocument ( doc ) # # setup param values view # paramsLayout = QtModule.QGridLayout () paramsLayout.setContentsMargins ( 2, 2, 2, 2 ) paramsLayout.setSizeConstraint ( QtModule.QLayout.SetNoConstraint ) paramsLayout.setVerticalSpacing ( 4 ) paramsLayout.setColumnStretch ( 1, 1 ) paramsLayout.setRowStretch ( 2, 1 ) frame = QtModule.QFrame () frame.setLayout ( paramsLayout ) if self.param.type in self.paramWidgets.keys () : print '>> Create %s param widget' % self.param.type # create paramWidget without GfxNode and ignoreSubtype = True self.ui.value_widget = apply ( self.paramWidgets [ self.param.type ], [ self.param, None, True ] ) self.ui.value_widget.label.setText ( 'Current Value' ) paramsLayout.addLayout ( self.ui.value_widget.label_vl, 0, 0, 1, 1 ) paramsLayout.addLayout ( self.ui.value_widget.param_vl, 0, 1, 1, 1 ) self.ui.def_value_widget = apply ( self.paramWidgets [ self.param_default.type ], [ self.param_default, None, True ] ) self.ui.def_value_widget.label.setText ( 'Default Value' ) paramsLayout.addLayout ( self.ui.def_value_widget.label_vl, 1, 0, 1, 1 ) paramsLayout.addLayout ( self.ui.def_value_widget.param_vl, 1, 1, 1, 1 ) spacer = QtModule.QSpacerItem ( 20, 20, QtModule.QSizePolicy.Minimum, QtModule.QSizePolicy.Expanding ) paramsLayout.addItem ( spacer, 2, 0, 1, 1 ) self.ui.value_stackedWidget.addWidget ( frame ) self.connectSignals () else : self.reset () # # onEditParamName # def onEditParamName ( self ) : # # !!! ListWidget item for param also should be changed # oldName = self.param.name newName = str ( self.ui.name_lineEdit.text () ).strip () if newName == '' : newName = oldName self.ui.name_lineEdit.setText ( newName ) if newName != oldName : self.param.name = newName if usePyQt4 : self.emit( QtCore.SIGNAL ( 'changeParamName' ), oldName, newName ) else : self.changeParamName.emit ( oldName, newName ) # # onEditParamLabel # def onEditParamLabel ( self ) : # oldName = self.param.label newName = str ( self.ui.label_lineEdit.text () ).strip () if newName == '' : newName = oldName self.ui.label_lineEdit.setText ( newName ) if newName != oldName : self.param.label = newName if usePyQt4 : self.emit ( QtCore.SIGNAL ( 'changeParamLabel' ), oldName, newName ) else : self.changeParamLabel.emit ( oldName, newName ) # # onEditParamEnabled # def onEditParamEnabled ( self, value ) : # self.param.enabled = self.ui.check_enabled.isChecked () # # onEditParamEnabled # def onEditParamDisplay ( self, value ) : # self.param.display = self.ui.check_display.isChecked () # # onEditParamShader # def onEditParamShader ( self, value ) : # self.param.shaderParam = self.ui.check_shader.isChecked () if usePyQt4 : self.emit ( QtCore.SIGNAL ( 'changeParamIsShader' ), self.param ) else : self.changeParamIsShader.emit ( self.param ) # # onEditParamType # def onEditParamType ( self, idx ) : # # !!! UI for param.value and param.default also should be changed # self.param.type = str ( self.ui.type_comboBox.itemText ( idx ) ) if usePyQt4 : self.emit ( QtCore.SIGNAL ( 'changeParamType' ), self.param ) else : self.changeParamType.emit ( self.param ) # # onEditParamDetail # def onEditParamDetail ( self, idx ) : # self.param.detail = str ( self.ui.detail_comboBox.itemText ( idx ) ) if usePyQt4 : self.emit ( QtCore.SIGNAL ( 'changeParamDetail' ), self.param ) else : self.changeParamDetail.emit ( self.param ) # # onEditParamProvider # def onEditParamProvider ( self, idx ) : # self.param.provider = str ( self.ui.provider_comboBox.itemText ( idx ) ) if usePyQt4 : self.emit ( QtCore.SIGNAL ( 'changeParamProvider' ), self.param ) else : self.changeParamProvider.emit ( self.param ) # # onEditParamSubtype # def onEditParamSubtype ( self, idx ) : # self.param.subtype = str ( self.ui.subtype_comboBox.itemText ( idx ) ) if usePyQt4 : self.emit ( QtCore.SIGNAL ( 'changeParamSubtype' ), self.param ) else : self.changeParamSubtype.emit ( self.param ) # # onEditParamRange # def onEditParamRange ( self ) : # self.param.range = str ( self.ui.range_lineEdit.text () ) if usePyQt4 : self.emit ( QtCore.SIGNAL ( 'changeParamRange' ), self.param ) else : self.changeParamRange.emit ( self.param ) # # onEditParamHelp # def onEditParamHelp ( self ) : # self.param.help = str ( self.ui.descr_plainTextEdit.toPlainText () )
class NodePropertiesEditor(QtModule.QWidget): # # __init__ # def __init__(self, parent, editNode=None): # QtModule.QWidget.__init__(self, parent) # # Define signals for PyQt5 # if usePySide or usePyQt5: # self.changeNodeLabel = Signal() # self.editNode = editNode # self.debugPrint() self.buildGui() self.setNode(editNode) # # buildGui # def buildGui(self): # build the gui created with QtDesigner self.ui = Ui_NodePropertiesEditor() self.ui.setupUi(self) # # setNode # def setNode(self, editNode): # self.disconnectSignals() self.editNode = editNode if self.editNode is not None: # name = self.editNode.name if self.editNode.name is None: name = "" self.ui.name_lineEdit.setText(name) label = self.editNode.label if self.editNode.label is None: label = "" self.ui.label_lineEdit.setText(label) author = self.editNode.author if self.editNode.author is None: author = "" self.ui.author_lineEdit.setText(author) master = self.editNode.master if self.editNode.master is None: master = "" self.ui.master_lineEdit.setText(master) icon = self.editNode.icon if self.editNode.icon is None: icon = "" self.ui.icon_lineEdit.setText(icon) # print '* self.editNode.help = %s' % self.editNode.help doc = QtGui.QTextDocument() help_text = "" if self.editNode.help != None: help_text = self.editNode.help doc.setPlainText(help_text) layout = QtModule.QPlainTextDocumentLayout(doc) doc.setDocumentLayout(layout) self.ui.help_plainTextEdit.setDocument(doc) self.ui.id_lineEdit.setText(str(self.editNode.id)) self.ui.type_comboBox.setEditable(False) self.ui.type_comboBox.setMinimumSize(QtCore.QSize(UI.COMBO_WIDTH, UI.COMBO_HEIGHT)) self.ui.type_comboBox.setMaximumSize(QtCore.QSize(UI.MAX, UI.COMBO_HEIGHT)) currentIdx = -1 i = 0 for label in VALID_NODE_TYPES: self.ui.type_comboBox.addItem(label) if label == self.editNode.type: currentIdx = i i += 1 self.ui.type_comboBox.setCurrentIndex(currentIdx) # temporary disabled, until "how to do it gracefully" will be clear ... self.ui.type_comboBox.setEnabled(False) self.connectSignals() # # connectSignals # def connectSignals(self): # QtCore.QObject. if usePyQt4: self.connect(self.ui.name_lineEdit, QtCore.SIGNAL("editingFinished()"), self.onEditNodeStrAttrName) self.connect(self.ui.label_lineEdit, QtCore.SIGNAL("editingFinished()"), self.onEditNodeStrAttrLabel) self.connect(self.ui.master_lineEdit, QtCore.SIGNAL("editingFinished()"), self.onEditNodeStrAttrMaster) self.connect(self.ui.author_lineEdit, QtCore.SIGNAL("editingFinished()"), self.onEditNodeStrAttrAuthor) self.connect(self.ui.icon_lineEdit, QtCore.SIGNAL("editingFinished()"), self.onEditNodeStrAttrIcon) self.connect(self.ui.type_comboBox, QtCore.SIGNAL("activated(int)"), self.onEditNodeType) self.connect(self.ui.help_plainTextEdit, QtCore.SIGNAL("textChanged()"), self.onEditNodeTxtAttr) else: self.ui.name_lineEdit.editingFinished.connect(self.onEditNodeStrAttrName) self.ui.label_lineEdit.editingFinished.connect(self.onEditNodeStrAttrLabel) self.ui.master_lineEdit.editingFinished.connect(self.onEditNodeStrAttrMaster) self.ui.author_lineEdit.editingFinished.connect(self.onEditNodeStrAttrAuthor) self.ui.icon_lineEdit.editingFinished.connect(self.onEditNodeStrAttrIcon) self.ui.type_comboBox.activated.connect(self.onEditNodeType) self.ui.help_plainTextEdit.textChanged.connect(self.onEditNodeTxtAttr) # # disconnectSignals # def disconnectSignals(self): # if usePyQt4: if self.editNode is not None: self.disconnect(self.ui.name_lineEdit, QtCore.SIGNAL("editingFinished()"), self.onEditNodeStrAttrName) self.disconnect(self.ui.label_lineEdit, QtCore.SIGNAL("editingFinished()"), self.onEditNodeStrAttrLabel) self.disconnect( self.ui.master_lineEdit, QtCore.SIGNAL("editingFinished()"), self.onEditNodeStrAttrMaster ) self.disconnect( self.ui.author_lineEdit, QtCore.SIGNAL("editingFinished()"), self.onEditNodeStrAttrAuthor ) self.disconnect(self.ui.icon_lineEdit, QtCore.SIGNAL("editingFinished()"), self.onEditNodeStrAttrIcon) self.disconnect(self.ui.type_comboBox, QtCore.SIGNAL("activated(int)"), self.onEditNodeType) self.disconnect(self.ui.help_plainTextEdit, QtCore.SIGNAL("textChanged()"), self.onEditNodeTxtAttr) else: if self.editNode is not None: self.ui.name_lineEdit.editingFinished.disconnect(self.onEditNodeStrAttrName) self.ui.label_lineEdit.editingFinished.disconnect(self.onEditNodeStrAttrLabel) self.ui.master_lineEdit.editingFinished.disconnect(self.onEditNodeStrAttrMaster) self.ui.author_lineEdit.editingFinished.disconnect(self.onEditNodeStrAttrAuthor) self.ui.icon_lineEdit.editingFinished.disconnect(self.onEditNodeStrAttrIcon) self.ui.type_comboBox.activated.disconnect(self.onEditNodeType) self.ui.help_plainTextEdit.textChanged.disconnect(self.onEditNodeTxtAttr) # # # doesn't work ... # def onEditNodeStrAttr(self, attr=None): # if attr is not None and self.editNode is not None: if attr == "name": self.editNode.name = str(self.ui.name_lineEdit.text()) elif attr == "label": self.editNode.label = str(self.ui.label_lineEdit.text()) elif attr == "master": self.editNode.master = str(self.ui.master_lineEdit.text()) elif attr == "author": self.editNode.author = str(self.ui.author_lineEdit.text()) elif attr == "icon": self.editNode.icon = str(self.ui.icon_lineEdit.text()) # # # def onEditNodeStrAttrName(self): self.editNode.name = str(self.ui.name_lineEdit.text()) def onEditNodeStrAttrLabel(self): # oldLabel = self.editNode.label newLabel = str(self.ui.label_lineEdit.text()).strip() if newLabel == "": if usePyQt4: self.disconnect(self.ui.label_lineEdit, QtCore.SIGNAL("editingFinished()"), self.onEditNodeStrAttrLabel) else: self.ui.label_lineEdit.editingFinished.disconnect(self.onEditNodeStrAttrLabel) newLabel = oldLabel self.ui.label_lineEdit.setText(newLabel) if usePyQt4: self.connect(self.ui.label_lineEdit, QtCore.SIGNAL("editingFinished()"), self.onEditNodeStrAttrLabel) else: self.ui.label_lineEdit.editingFinished.connect(self.onEditNodeStrAttrLabel) if newLabel != oldLabel: self.editNode.label = newLabel if usePyQt4: self.emit(QtCore.SIGNAL("changeNodeLabel"), oldLabel, newLabel) else: self.changeNodeLabel.emit(oldLabel, newLabel) # # onEditNodeStrAttrMaster # def onEditNodeStrAttrMaster(self): # self.editNode.master = str(self.ui.master_lineEdit.text()) # # onEditNodeStrAttrAuthor # def onEditNodeStrAttrAuthor(self): # self.editNode.author = str(self.ui.author_lineEdit.text()) # # onEditNodeStrAttrIcon # def onEditNodeStrAttrIcon(self): # self.editNode.icon = str(self.ui.icon_lineEdit.text()) # # onEditNodeTxtAttr # def onEditNodeTxtAttr(self): # self.editNode.help = str(self.ui.help_plainTextEdit.toPlainText()) # # onEditNodeType # def onEditNodeType(self, idx): # self.editNode.type = str(self.ui.type_comboBox.itemText(idx))
class WorkAreaScene ( QtModule.QGraphicsScene ) : # # __init__ # def __init__ ( self, view ) : # QtModule.QGraphicsScene.__init__ ( self ) # # Define signals for PyQt5 # if usePySide or usePyQt5 : # self.startNodeConnector = Signal () #QtCore.pyqtSignal ( QtModule.QGraphicsObject, QtCore.QPointF ) self.traceNodeConnector = Signal () #QtCore.pyqtSignal ( QtModule.QGraphicsObject, QtCore.QPointF ) self.endNodeConnector = Signal () #QtCore.pyqtSignal ( QtModule.QGraphicsObject, QtCore.QPointF ) self.startNodeLink = Signal () #( QtModule.QGraphicsObject ) # QtModule.QGraphicsItem self.traceNodeLink = Signal () #QtCore.pyqtSignal ( QtModule.QGraphicsObject, QtCore.QPointF ) self.endNodeLink = Signal () #QtCore.pyqtSignal ( QtModule.QGraphicsObject, QtCore.QPointF ) self.onGfxNodeRemoved = Signal () #QtCore.pyqtSignal ( QtModule.QGraphicsObject ) self.onGfxLinkRemoved = Signal () #QtCore.pyqtSignal ( QtModule.QGraphicsObject ) self.nodeUpdated = Signal () #QtCore.pyqtSignal ( QtModule.QGraphicsItem ) self.gfxNodeParamChanged = Signal () #QtCore.pyqtSignal ( QtModule.QGraphicsItem, QtCore.QObject ) # self.view = view self.connectSignals () # # connectSignals # def connectSignals ( self ) : if usePyQt4 : QtCore.QObject.connect ( self, QtCore.SIGNAL ( 'selectionChanged()' ), self.view.onSelectionChanged ) QtCore.QObject.connect ( self, QtCore.SIGNAL ( 'startNodeLink' ), self.view.onStartNodeLink ) QtCore.QObject.connect ( self, QtCore.SIGNAL ( 'traceNodeLink' ), self.view.onTraceNodeLink ) QtCore.QObject.connect ( self, QtCore.SIGNAL ( 'endNodeLink' ), self.view.onEndNodeLink ) QtCore.QObject.connect ( self, QtCore.SIGNAL ( 'startNodeConnector' ), self.view.onStartNodeConnector ) QtCore.QObject.connect ( self, QtCore.SIGNAL ( 'traceNodeConnector' ), self.view.onTraceNodeConnector ) QtCore.QObject.connect ( self, QtCore.SIGNAL ( 'endNodeConnector' ), self.view.onEndNodeConnector ) QtCore.QObject.connect ( self, QtCore.SIGNAL ( 'onGfxNodeRemoved' ), self.view.onRemoveNode ) QtCore.QObject.connect ( self, QtCore.SIGNAL ( 'onGfxLinkRemoved' ), self.view.onRemoveLink ) else : self.selectionChanged.connect ( self.view.onSelectionChanged ) self.startNodeLink.connect ( self.view.onStartNodeLink ) self.traceNodeLink.connect ( self.view.onTraceNodeLink ) self.endNodeLink.connect ( self.view.onEndNodeLink ) self.startNodeConnector.connect ( self.view.onStartNodeConnector ) self.traceNodeConnector.connect ( self.view.onTraceNodeConnector ) self.endNodeConnector.connect ( self.view.onEndNodeConnector ) self.onGfxNodeRemoved.connect ( self.view.onRemoveNode ) self.onGfxLinkRemoved.connect ( self.view.onRemoveLink )
class Notification(RanaModule): """This module provides notification support.""" def __init__(self, *args, **kwargs): RanaModule.__init__(self, *args, **kwargs) self.notificationText = "" self.timeout = 5000 self.position = 'middle' self.expirationTimestamp = time.time() self.draw = False self.redrawn = None self.wipOverlayEnabled = Signal() self._showWorkInProgressOverlay = False self.workStartTimestamp = None self._wipOverlayText = "" # this indicates if the notification about # background processing should be shown self._tasks = {} self._tasksLock = threading.RLock() ## for WiP overlay testing #self._tasks = { # "foo" : ("foo", None), # "bar" : ("bar", None), # "baz" : ("baz", None) #} # key is an unique task name (unique for each instance of a task) # and value is a (status, progress) tuple self.tasksChanged = Signal() # connect thread manager signals to task status changes threadMgr.threadStatusChanged.connect(self.setTaskStatus) threadMgr.threadProgressChanged.connect(self.setTaskProgress) threadMgr.threadRemoved.connect(self.removeTask) # also with GTK GUI, assure screen is redrawn properly # when WiP overlay changes if gs.GUIString == "GTK": self.wipOverlayEnabled.connect(self._doRefresh) self.tasksChanged.connect(self._doRefresh) # we handle notification only with the GTK GUI and when the device module does not # support showing them if not self.modrana.dmod.hasNotificationSupport(): self.modrana.notificationTriggered.connect(self._startCustomNotificationCB) def _doRefresh(self, ignore): self.set('needRedraw', True) def handleMessage(self, message, messageType, args): """the first part is the message, that will be displayed, there can also by some parameters, delimited by # NEW: you can also use a message list for the notification first goes 'm', the message and then the timeout in seconds EXAMPLE: ml:notification:m:Hello world!;5 """ if messageType == 'ml' and message == 'm': # advanced message list based notification if args: timeout = self.timeout if len(args) >= 2: # convert to float, multiply by 1000 to convert to ms # and then convert to integer number of ms timeout = int(float(args[1])*1000) messageText = args[0] self.modrana.notify(messageText, timeout) elif messageType == 'ml' and message == 'workInProgressOverlay': if args: if args[0] == "enable": self._startWorkInProgressOverlay() if args[0] == "disable": self._stopWorkInProgressOverlay() elif messageType and message == "cancelTask": if args: self.cancelTask(args) else: parameterList = message.split('#') if len(parameterList) >= 2: messageText = parameterList[0] timeout = self.timeout self.modrana.notify(messageText, timeout) if len(parameterList) == 2: try: # override the default timeout and convert to ms timeout = int(parameterList[1])*1000 except Exception: self.log.exception("wrong timeout, using default 5 seconds") self.modrana.notify(messageText, timeout) else: self.log.error("wrong message: %s", message) def setTaskStatus(self, taskName, status): """Set textual status of the given WiP task :param taskName: task to modify :type taskName: str :param status: textual task status :type status: str """ with self._tasksLock: oldStatus, progress = self._tasks.get(taskName, (None, None)) # replace the task with updated one self._tasks[taskName] = (status, progress) self.tasksChanged(self._tasks) if status: self._startWorkInProgressOverlay() def setTaskProgress(self, taskName, progress): """Set numeric progress of the given WiP task :param taskName: task to modify :type taskName: str :param progress: numeric task progress in the range of 0.0 to 1.0 :type progress: float """ with self._tasksLock: status, oldProgress = self._tasks.get(taskName, (None, None)) # replace the task with updated one self._tasks[taskName] = (status, progress) self.tasksChanged(self._tasks) if progress is not None: self._startWorkInProgressOverlay() def removeTask(self, taskName): """Remove given task from WiP tracking :param taskName: name of the task to cancel :type taskName: str """ with self._tasksLock: try: del self._tasks[taskName] self.tasksChanged(self._tasks) except KeyError: self.log.error("error, can't remove unknown task: %s", taskName) if self._tasks == {}: self._stopWorkInProgressOverlay() def cancelTask(self, taskName): """Cancel a task - this both cancels the callback for the thread handling the task and removes the task from tracking :param taskName: task to cancel :type taskName: str """ threadMgr.cancel_thread(taskName) # and finally stop tracking the task self.removeTask(taskName) self.log.info("task %s has been cancelled", taskName) def _startWorkInProgressOverlay(self): """start background work notification""" if not self._showWorkInProgressOverlay: self._showWorkInProgressOverlay = True self.workStartTimestamp = time.time() self.wipOverlayEnabled(True) def _stopWorkInProgressOverlay(self): """stop background work notification""" self._showWorkInProgressOverlay = False self.wipOverlayEnabled(False) #def getWorkInProgressOverlayText(self): # elapsedSeconds = int(time.time() - self.workStartTimestamp) # if elapsedSeconds: # 0s doesnt look very good :) # return "%s %d s" % (self.wipOverlayText, elapsedSeconds) # else: # return self.wipOverlayText def drawWorkInProgressOverlay(self, cr): proj = self.m.get('projection', None) # we also need the projection module viewport = self.get('viewport', None) menus = self.m.get('menu', None) with self._tasksLock: if self._tasks and proj and viewport and menus: # we need to have both the viewport and projection modules available # also the menu module for the text taskCount = len(self._tasks) # background cr.set_source_rgba(0.5, 0.5, 1, 0.5) (sx, sy, w, h) = viewport itemHeight = h * 0.2 (bx, by, bw, bh) = (0, 0, w, itemHeight * taskCount) cr.rectangle(bx, by, bw, bh) cr.fill() taskIndex = 0 for taskName, taskState in six.iteritems(self._tasks): # cancel button coordinates cbdx = min(w, h) / 5.0 cbdy = cbdx cbx1 = (sx + w) - cbdx cby1 = sy + cbdy * taskIndex # cancel button self.drawCancelButton(cr, coords=(cbx1, cby1, cbdx, cbdy), taskName=taskName) status, progress = taskState # draw the text border = min(w / 20.0, h / 20.0) menus.showText(cr, status, bx + border, by + border + itemHeight * taskIndex, bw - 2 * border - cbdx, 30, "white") taskIndex += 1 def drawCancelButton(self, cr, coords=None, taskName=None): """draw the cancel button TODO: this and the other context buttons should be moved to a separate module, named contextMenu or something in the same style""" menus = self.m.get('menu', None) click = self.m.get('clickHandler', None) if menus and click: if coords: #use the provided coords (x1, y1, dx, dy) = coords else: # use the bottom right corner (x, y, w, h) = self.get('viewport') dx = min(w, h) / 5.0 dy = dx x1 = (x + w) - dx y1 = y # the cancel button sends a cancel message to onlineServices # to disable currently running operation menus.drawButton(cr, x1, y1, dx, dy, '#<span foreground="red">cancel</span>', "generic:;0.5;;0.5;;", '') if taskName: message = "ms:notification:cancelTask:%s" % taskName click.registerXYWH(x1, y1, dx, dy, message, layer=2) else: click.registerXYWH(x1, y1, dx, dy, "onlineServices:cancelOperation", layer=2) def _startCustomNotificationCB(self, message, ms_timeout, icon=""): self.position = 'middle' self.notificationText = message self.expirationTimestamp = time.time() + ms_timeout/1000.0 self.draw = True # enable drawing of notifications self.set('needRedraw', True) # make sure the notification is displayed def drawMasterOverlay(self, cr): """this function is called by the menu module, both in map mode and menu mode -> its bit of a hack, but we can """ self._drawNotification(cr) if self._showWorkInProgressOverlay: self.drawWorkInProgressOverlay(cr) def _drawNotification(self, cr): """Draw the notifications on the screen on top of everything.""" if time.time() <= self.expirationTimestamp: menus = self.m.get('menu', None) proj = self.m.get('projection', None) viewport = self.get('viewport', None) if not proj or not menus or not viewport: return x, y, w, h = viewport border = min(w / 20.0, h / 20.0) proj = self.m.get('projection', None) (x1, y1) = proj.screenPos(0.5, 0.5) # middle fo the screen cr.set_source_rgba(0, 0, 1, 0.45) # transparent blue font_size = 30 # compute rendered text size textw, texth = menus.measureWrappedText(cr, self.notificationText, w - border * 2, font_size) # the background rectangle is as large as the text + borders rw = textw + 2 * border rh = texth + 2 * border # center the rectangle & text to be in the middle of the screen rx = (w - rw) / 2.0 ry = (h - rh) / 2.0 tx = rx + border ty = ry + border # draw the background rectangle cr.set_line_width(2) cr.set_source_rgba(0, 0, 1, 0.45) # transparent blue cr.rectangle(rx, ry, rw, rh) # create the transparent background rectangle cr.fill() # draw the text if menus and viewport and proj: menus.showWrappedText(cr, self.notificationText, tx, ty, textw, font_size, "white") else: self.draw = False # we are finished, disable drawing notifications
class Notification(RanaModule): """This module provides notification support.""" def __init__(self, m, d, i): RanaModule.__init__(self, m, d, i) self.notificationText = "" self.timeout = 5 self.position = 'middle' self.expirationTimestamp = time.time() self.draw = False self.redrawn = None self.wipOverlayEnabled = Signal() self._showWorkInProgressOverlay = False self.workStartTimestamp = None self._wipOverlayText = "" # this indicates if the notification about # background processing should be shown self._tasks = {} self._tasksLock = threading.RLock() ## for WiP overlay testing #self._tasks = { # "foo" : ("foo", None), # "bar" : ("bar", None), # "baz" : ("baz", None) #} # key is an unique task name (unique for each instance of a task) # and value is a (status, progress) tuple self.tasksChanged = Signal() # connect thread manager signals to task status changes threadMgr.threadStatusChanged.connect(self.setTaskStatus) threadMgr.threadProgressChanged.connect(self.setTaskProgress) threadMgr.threadRemoved.connect(self.removeTask) # also with GTK GUI, assure screen is redrawn properly # when WiP overlay changes if gs.GUIString == "GTK": self.wipOverlayEnabled.connect(self._doRefresh) self.tasksChanged.connect(self._doRefresh) def _doRefresh(self, ignore): self.set('needRedraw', True) def handleMessage(self, message, messageType, args): """the first part is the message, that will be displayed, there can also by some parameters, delimited by # NEW: you can also use a message list for the notification first goes 'm', the message and then the timeout in seconds EXAMPLE: ml:notification:m:Hello world!;5 """ if messageType == 'ml' and message == 'm': # advanced message list based notification if args: timeout = self.timeout if len(args) >= 2: timeout = float(args[1]) messageText = args[0] self.handleNotification(messageText, timeout) elif messageType == 'ml' and message == 'workInProgressOverlay': if args: if args[0] == "enable": self._startWorkInProgressOverlay() if args[0] == "disable": self._stopWorkInProgressOverlay() elif messageType and message == "cancelTask": if args: self.cancelTask(args) else: parameterList = message.split('#') if len(parameterList) >= 2: messageText = parameterList[0] timeout = self.timeout self.handleNotification(messageText, timeout) if len(parameterList) == 2: try: timeout = int(parameterList[1]) # override the default timeout except Exception: import sys e = sys.exc_info()[1] print("notification: wrong timeout, using default 5 seconds") print(e) self.handleNotification(messageText, timeout) else: print("notification: wrong message: %s" % message) def setTaskStatus(self, taskName, status): """Set textual status of the given WiP task :param taskName: task to modify :type taskName: str :param status: textual task status :type status: str """ with self._tasksLock: oldStatus, progress = self._tasks.get(taskName, (None, None)) # replace the task with updated one self._tasks[taskName] = (status, progress) self.tasksChanged(self._tasks) if status: self._startWorkInProgressOverlay() def setTaskProgress(self, taskName, progress): """Set numeric progress of the given WiP task :param taskName: task to modify :type taskName: str :param progress: numeric task progress in the range of 0.0 to 1.0 :type progress: float """ with self._tasksLock: status, oldProgress = self._tasks.get(taskName, (None, None)) # replace the task with updated one self._tasks[taskName] = (status, progress) self.tasksChanged(self._tasks) if progress is not None: self._startWorkInProgressOverlay() def removeTask(self, taskName): """Remove given task from WiP tracking :param taskName: name of the task to cancel :type taskName: str """ with self._tasksLock: try: del self._tasks[taskName] self.tasksChanged(self._tasks) except KeyError: print("notification: error, can't remove unknown task: %s" % taskName) if self._tasks == {}: self._stopWorkInProgressOverlay() def cancelTask(self, taskName): """Cancel a task - this both cancels the callback for the thread handling the task and removes the task from tracking :param taskName: task to cancel :type taskName: str """ threadMgr.cancel_thread(taskName) # and finally stop tracking the task self.removeTask(taskName) print("notification: task %s has been cancelled" % taskName) def _startWorkInProgressOverlay(self): """start background work notification""" if not self._showWorkInProgressOverlay: self._showWorkInProgressOverlay = True self.workStartTimestamp = time.time() self.wipOverlayEnabled(True) def _stopWorkInProgressOverlay(self): """stop background work notification""" self._showWorkInProgressOverlay = False self.wipOverlayEnabled(False) #def getWorkInProgressOverlayText(self): # elapsedSeconds = int(time.time() - self.workStartTimestamp) # if elapsedSeconds: # 0s doesnt look very good :) # return "%s %d s" % (self.wipOverlayText, elapsedSeconds) # else: # return self.wipOverlayText def drawWorkInProgressOverlay(self, cr): proj = self.m.get('projection', None) # we also need the projection module viewport = self.get('viewport', None) menus = self.m.get('menu', None) with self._tasksLock: if self._tasks and proj and viewport and menus: # we need to have both the viewport and projection modules available # also the menu module for the text taskCount = len(self._tasks) # background cr.set_source_rgba(0.5, 0.5, 1, 0.5) (sx, sy, w, h) = viewport itemHeight = h * 0.2 (bx, by, bw, bh) = (0, 0, w, itemHeight * taskCount) cr.rectangle(bx, by, bw, bh) cr.fill() taskIndex = 0 for taskName, taskState in six.iteritems(self._tasks): # cancel button coordinates cbdx = min(w, h) / 5.0 cbdy = cbdx cbx1 = (sx + w) - cbdx cby1 = sy + cbdy * taskIndex # cancel button self.drawCancelButton(cr, coords=(cbx1, cby1, cbdx, cbdy), taskName=taskName) status, progress = taskState # draw the text border = min(w / 20.0, h / 20.0) menus.showText(cr, status, bx + border, by + border + itemHeight * taskIndex, bw - 2 * border - cbdx, 30, "white") taskIndex += 1 def drawCancelButton(self, cr, coords=None, taskName=None): """draw the cancel button TODO: this and the other context buttons should be moved to a separate module, named contextMenu or something in the same style""" menus = self.m.get('menu', None) click = self.m.get('clickHandler', None) if menus and click: if coords: #use the provided coords (x1, y1, dx, dy) = coords else: # use the bottom right corner (x, y, w, h) = self.get('viewport') dx = min(w, h) / 5.0 dy = dx x1 = (x + w) - dx y1 = y # the cancel button sends a cancel message to onlineServices # to disable currently running operation menus.drawButton(cr, x1, y1, dx, dy, '#<span foreground="red">cancel</span>', "generic:;0.5;;0.5;;", '') if taskName: message = "ms:notification:cancelTask:%s" % taskName click.registerXYWH(x1, y1, dx, dy, message, layer=2) else: click.registerXYWH(x1, y1, dx, dy, "onlineServices:cancelOperation", layer=2) def handleNotification(self, message, timeout=None, icon=""): """Handle a notification request As on some platforms, such as on Maemo 5 Fremantle, system notifications should only be triggered from the main thread, we pass the notification request to the main loop, to be dispatched once the main GUI thread becomes idle """ cron = self.m.get("cron", None) if cron: cron.addIdle(self._dispatchNotification, [message, timeout, icon]) def _dispatchNotification(self, message, timeout, icon): """Dispatch a notification using the most optimal method for the current device & platform combination NOTE: This method should be run from the main thread as there might be issues otherwise (such as the "Xlib: unexpected async reply" errors). """ # TODO: icon support if timeout is None: timeout = self.timeout print("notification: message: %s, timeout: %s" % (message, timeout)) # if some module sends a notification during init, the device module might not be loaded yet if self.modrana.dmod and self.modrana.gui: if self.dmod.hasNotificationSupport(): # use platform specific method print("notification@dmod: message: %s, timeout: %s" % (message, timeout)) self.dmod.notify(message, int(timeout) * 1000) elif self.modrana.gui.hasNotificationSupport(): self.modrana.gui.notify(message, timeout, icon) else: self._startCustomNotification(message, timeout, icon) else: self._startCustomNotification(message, timeout, icon) def _startCustomNotification(self, message, timeout, icon=""): print("notification: message: %s, timeout: %s" % (message, timeout)) self.position = 'middle' self.notificationText = message self.expirationTimestamp = time.time() + timeout self.draw = True # enable drawing of notifications self.set('needRedraw', True) # make sure the notification is displayed def drawMasterOverlay(self, cr): """this function is called by the menu module, both in map mode and menu mode -> its bit of a hack, but we can """ self.drawNotification(cr) if self._showWorkInProgressOverlay: self.drawWorkInProgressOverlay(cr) def drawNotification(self, cr): """Draw the notifications on the screen on top of everything.""" if time.time() <= self.expirationTimestamp: proj = self.m.get('projection', None) (x1, y1) = proj.screenPos(0.5, 0.5) # middle fo the screen cr.set_font_size(30) text = self.notificationText cr.set_source_rgba(0, 0, 1, 0.45) # transparent blue extents = cr.text_extents(text) (w, h) = (extents[2], extents[3]) (x, y) = (x1 - w / 2.0, y1 - h / 2.0) cr.set_line_width(2) cr.set_source_rgba(0, 0, 1, 0.45) # transparent blue (rx, ry, rw, rh) = (x - 0.25 * w, y - h * 1.5, w * 1.5, (h * 2)) cr.rectangle(rx, ry, rw, rh) # create the transparent background rectangle cr.fill() cr.set_source_rgba(1, 1, 1, 0.95) # slightly transparent white cr.move_to(x + 10, y) cr.show_text(text) # show the transparent notification text cr.stroke() cr.fill() else: self.draw = False # we are finished, disable drawing notifications
class WorkArea ( QtModule.QGraphicsView ) : # # __init__ # def __init__ ( self ) : # QtModule.QGraphicsView.__init__ ( self ) # # Define signals for PyQt5 # if usePySide or usePyQt5 : # self.selectNodes = Signal () #( list, list ) self.nodeConnectionChanged = Signal () #QtCore.pyqtSignal ( QtModule.QGraphicsObject, QtCore.QObject ) self.gfxNodeAdded = Signal () #( QtModule.QGraphicsObject ) self.gfxNodeRemoved = Signal () #( QtModule.QGraphicsObject ) # self.drawGrid = True self.gridSnap = False self.straightLinks = False self.reverseFlow = False self.gridSize = 10 self.minGap = 120 self.current_Z = 1 self.state = 'idle' self.pressed = False self.startPos = None self.lastConnectCandidate = None self.currentGfxLink = None self.inspectedNode = None self.nodeNet = None self.selectedNodes = [] self.selectedLinks = [] # set scene scene = WorkAreaScene ( self ) scene.setSceneRect ( -10000, -10000, 20000, 20000 ) #scene.setItemIndexMethod ( QtGui.QGraphicsScene.NoIndex ) self.setScene ( scene ) # qt graphics stuff self.setCacheMode ( QtModule.QGraphicsView.CacheBackground ) self.setRenderHint ( QtGui.QPainter.Antialiasing ) self.setTransformationAnchor ( QtModule.QGraphicsView.AnchorUnderMouse ) # QtGui.QGraphicsView.AnchorUnderMouse self.setResizeAnchor ( QtModule.QGraphicsView.AnchorUnderMouse ) # AnchorViewCenter self.setDragMode ( QtModule.QGraphicsView.RubberBandDrag ) self.setMouseTracking ( False ) self.setAcceptDrops ( True ) """ viewport = self.viewport() if viewport is not None : print ">> WorkArea viewport.setAcceptTouchEvents" #proxy = QtGui.QGraphicsProxyWidget () proxy = viewport.graphicsProxyWidget () if proxy is not None : proxy.setAcceptTouchEvents ( True ) #self.setAttribute ( QtGui.AcceptTouchEvents, True ) #viewport()->setAttribute(Qt::WA_AcceptTouchEvents); #setDragMode(ScrollHandDrag); #Qt::WA_AcceptTouchEvents """ self.viewBrush = QtGui.QBrush ( QtGui.QColor ( 148, 148, 148 ) ) self.setBackgroundBrush ( self.viewBrush ) # self.connectSignals () if DEBUG_MODE : print ">> WorkArea. __init__" # # connectSignals # def connectSignals ( self ) : # pass # # drawBackground # def drawBackground ( self, painter, rect ) : # sc_rect = self.sceneRect () bbrush = QtGui.QBrush( QtGui.QColor ( 148, 148, 148 ) ) ## painter.background() painter.fillRect ( rect, bbrush ) if self.drawGrid : # print( "grid size = %d" % self.gridSize ) gr_pen = QtGui.QPen ( QtGui.QColor ( 180, 180, 180 ) ) gr_pen.setWidth ( 0 ) painter.setPen ( gr_pen ) for x in range ( int ( sc_rect.x () ), int ( sc_rect.right () ), self.gridSize ): painter.drawLine ( x, sc_rect.y (), x, sc_rect.bottom () ) for y in range ( int ( sc_rect.y () ), int ( sc_rect.bottom () ), self.gridSize ): painter.drawLine ( sc_rect.x (), y, sc_rect.right (), y ) # # Returns a list of GfxNodes in the scene for given type # or all nodes if type == None # def getGfxNodesByType ( self, type = None ) : # resultList = [] for item in self.scene ().items () : if ( isinstance ( item, GfxNode ) or isinstance ( item, GfxSwatchNode ) or ( isinstance ( item, GfxNodeConnector ) and item.isNode () ) ) : if type is None or item.node.type == type : resultList.append ( item ) return resultList # # Returns a list of GfxNodes in the scene for given format # or all nodes if type == None # def getGfxNodesByFormat ( self, format = None ) : # resultList = [] for item in self.scene ().items () : if ( isinstance ( item, GfxNode ) or isinstance ( item, GfxSwatchNode ) or ( isinstance ( item, GfxNodeConnector ) and item.isNode () ) ) : if format is None or item.node.format == format : resultList.append ( item ) return resultList # # Returns GfxNodes for given Node # def getGfxNodesByNode ( self, node = None ) : # gfxNode = None for item in self.scene ().items () : if ( isinstance ( item, GfxNode ) or isinstance ( item, GfxSwatchNode ) or ( isinstance ( item, GfxNodeConnector ) and item.isNode () ) ) : if item.node == node : gfxNode = item break return gfxNode # # selectAllNodes # def getAllGfxNodes ( self ) : return self.getGfxNodesByType ( None ) # # selectAllNodes # def selectAllNodes ( self ) : # for item in self.getAllGfxNodes () : item.setSelected ( True ) # # selectAbove # def selectAbove ( self, upperGfxNode ) : # if DEBUG_MODE : print '>> WorkArea::selectAbove node (%s) links:' % upperGfxNode.node.label for link_list in upperGfxNode.node.outputLinks.values () : for link in link_list : # link.printInfo () if self.nodeNet.hasThisLink ( link ) : gfxNode = self.getGfxNodesByNode ( link.dstNode ) gfxNode.setSelected ( True ) self.selectAbove ( gfxNode ) else : if DEBUG_MODE : print '!! invalid link ...' # # updateBelow # def updateBelow ( self, upperGfxNode, removeLinks = False ) : # if DEBUG_MODE : print '>> WorkArea::updateBelow upperGfxNode.node (%s) children:' % upperGfxNode.node.label for node in upperGfxNode.node.childs : if DEBUG_MODE : print '* %s' % node.label gfxNode = self.getGfxNodesByNode ( node ) gfxNode.updateGfxNode ( removeLinks ) self.updateBelow ( gfxNode, removeLinks ) # # selectBelow # def selectBelow ( self, upperGfxNode ) : # if DEBUG_MODE : print '>> WorkArea::selectBelow upperGfxNode.node (%s) children:' % upperGfxNode.node.label for node in upperGfxNode.node.childs : if DEBUG_MODE : print '* %s' % node.label gfxNode = self.getGfxNodesByNode ( node ) gfxNode.setSelected ( True ) self.selectBelow ( gfxNode ) # # setNodeNetwork # def setNodeNetwork ( self, nodeNet ) : self.nodeNet = nodeNet # # clear # def clear ( self ): # if DEBUG_MODE : print '>> WorkArea:: clearing nodes ...' for item in self.scene ().items () : self.scene ().removeItem ( item ) self.nodeNet.clear () self.state = 'idle' self.panStartPos = None self.lastConnectCandidate = None self.currentGfxLink = None self.inspectedNode = None # # addGfxLink # def addGfxLink ( self, link ) : # if DEBUG_MODE : print '>> WorkArea::addGfxLink (id=%d)' % link.id gfxLink = GfxLink ( link ) ( srcNode, srcParam ) = link.getSrc () ( dstNode, dstParam ) = link.getDst () srcConnector = None dstConnector = None for item in self.scene ().items (): if isinstance ( item, GfxNode ) or isinstance ( item, GfxSwatchNode ) : if item.node == srcNode : srcConnector = item.getOutputConnectorByParam ( srcParam ) elif item.node == dstNode : dstConnector = item.getInputConnectorByParam ( dstParam ) elif isinstance ( item, GfxNodeConnector ) and item.isNode () : if item.node == srcNode : srcConnector = item elif item.node == dstNode : dstConnector = item if ( srcConnector != None and dstConnector != None ) : break gfxLink.setSrcConnector ( srcConnector ) gfxLink.setDstConnector ( dstConnector ) gfxLink.adjust () self.scene ().addItem ( gfxLink ) # # Node already in NodeNet, so add new GfxNode to scene # def addGfxNode ( self, node, pos = None ) : # #print ( ">> WorkArea: addGfxNode %s" % node.label ) if node.type == 'connector' : gfxNode = GfxNodeConnector ( node.inputParams [ 0 ], node = node ) elif node.type == 'note' : gfxNode = GfxNote ( node ) elif node.type == 'swatch' : gfxNode = GfxSwatchNode ( node ) else : gfxNode = GfxNode ( node ) scene = self.scene () if pos != None : gfxNode.moveBy ( pos.x(), pos.y() ) #for item in scene.selectedItems (): item.setSelected ( False ) scene.addItem ( gfxNode ) gfxNode.setSelected ( True ) if usePyQt4 : self.emit ( QtCore.SIGNAL ( 'gfxNodeAdded' ), gfxNode ) else : self.gfxNodeAdded.emit ( gfxNode ) # # adjustLinks # def adjustLinks ( self ) : # for item in self.scene ().items () : if isinstance ( item, GfxLink ): item.adjust () # # fitGfxNodesInView # def fitGfxNodesInView ( self, gfxNodeList ) : # nodeNetRect = QtCore.QRectF () for gfxNode in gfxNodeList : nodeRect = gfxNode.sceneBoundingRect () if nodeNetRect.isNull () : nodeNetRect = nodeRect nodeNetRect = nodeNetRect.united ( nodeRect ) if nodeNetRect.isValid () : self.fitInView ( nodeNetRect, QtCore.Qt.KeepAspectRatio ) # # onSelectionChanged # def onSelectionChanged ( self ) : # #print ">> WorkArea: onSelectionChanged " self.selectedNodes = [] self.selectedLinks = [] selected = self.scene ().selectedItems () for item in selected: if isinstance ( item, GfxNode ) : self.selectedNodes.append ( item ) elif isinstance ( item, GfxNote ) : self.selectedNodes.append ( item ) elif isinstance ( item, GfxNodeConnector ) : self.selectedNodes.append ( item ) elif isinstance ( item, GfxSwatchNode ) : self.selectedNodes.append ( item ) elif isinstance ( item, GfxLink ) : self.selectedLinks.append ( item ) if usePyQt4 : self.emit ( QtCore.SIGNAL ( 'selectNodes' ), self.selectedNodes, self.selectedLinks ) else : self.selectNodes.emit ( self.selectedNodes, self.selectedLinks ) # # lastConnectCandidateReset # def lastConnectCandidateReset ( self ) : # if self.lastConnectCandidate is not None : self.lastConnectCandidate.hilite( False ) self.lastConnectCandidate = None # # isLinkAcceptable # def isLinkAcceptable ( self, connector, connectCandidate ) : # isAcceptable = False if isinstance ( connectCandidate, GfxNodeConnector ): # do not connect to itself if connectCandidate != connector : # do not connect to the same node if connectCandidate.parentItem () != connector.parentItem () : # do not connect the same link to connector twice if not connectCandidate.hasThisLink ( self.currentGfxLink ) : # connect only to similar type if connector.param.encodedTypeStr() == connectCandidate.param.encodedTypeStr () : if not connectCandidate.isNode () : # connect only input with output and vice versa if connector.param.isInput != connectCandidate.param.isInput : isAcceptable = True else : # we have nodeConnector isAcceptable = True return isAcceptable # # onStartNodeLink # #@QtCore.pyqtSlot( GfxNodeConnector ) def onStartNodeLink ( self, connector ): # #if DEBUG_MODE : print '>> WorkArea::onStartNodeLink' #if DEBUG_MODE : print connector srcNode = connector.getNode () srcParam = connector.param if DEBUG_MODE : print '>> WorkArea::onStartNodeLink from %s (%s)' % ( srcNode.label, srcParam.label ) srcConnector = connector self.state = 'traceNodeLink' self.lastConnectCandidate = None if connector.isInput () and connector.isLinked () : oldLink = connector.getFirstGfxLink () srcConnector = oldLink.srcConnector oldLink.remove () gfxLink = GfxLink ( None, srcConnector ) self.scene ().addItem ( gfxLink ) self.currentGfxLink = gfxLink self.currentGfxLink.isLinkSelected = True # # onTraceNodeLink # def onTraceNodeLink ( self, connector, scenePos ) : # node = connector.parentItem().node # print ">> WorkArea: onDrawNodeLink from %s (%d %d)" % ( node.label, scenePos.x(), scenePos.y() ) if usePyQt4 : connectCandidate = self.scene ().itemAt ( scenePos ) else : connectCandidate = self.scene ().itemAt ( scenePos, self.transform () ) srcConnector = self.currentGfxLink.srcConnector swappedLink = False if srcConnector is None : # link has swapped connectors srcConnector = self.currentGfxLink.dstConnector swappedLink = True if self.isLinkAcceptable ( srcConnector, connectCandidate ) : if connectCandidate != self.lastConnectCandidate : self.lastConnectCandidateReset () connectCandidate.hilite ( True ) self.lastConnectCandidate = connectCandidate # link_node = connectCandidate.parentItem ().node # print ">> WorkArea: onDrawNodeLink to %s" % link_node.label else : scenePos = self.lastConnectCandidate.getCenterPoint () # snap to last position pass # self.lastConnectCandidateReset () else : self.lastConnectCandidateReset () #if self.currentGfxLink is not None : if swappedLink : self.currentGfxLink.setSrcPoint ( scenePos ) else : self.currentGfxLink.setDstPoint ( scenePos ) # # onEndNodeLink # def onEndNodeLink ( self, connector, scenePos ) : # srcConnector = self.currentGfxLink.srcConnector dstConnector = self.currentGfxLink.dstConnector swappedLink = False if srcConnector is None : # link has swapped connectors swappedLink = True if self.lastConnectCandidate is None : self.currentGfxLink.remove () #self.emit( QtCore.SIGNAL( 'nodeParamChanged' ), srcConnector.parentItem(), srcConnector.param ) #self.emit( QtCore.SIGNAL( 'nodeParamChanged' ), dstConnector.parentItem(), dstConnector.param ) else : if self.lastConnectCandidate.isNode () : # if connection was made to ConnectorNode if dstConnector is None : self.lastConnectCandidate.removeInputGfxLinks () else : # remove old link first if it exists if self.lastConnectCandidate.isInput () and self.lastConnectCandidate.isLinked () : #oldLink = self.lastConnectCandidate.getFirstLink () #oldLink.remove () self.lastConnectCandidate.removeInputGfxLinks () self.currentGfxLink.isLinkSelected = False self.currentGfxLink.update () srcNode = dstNode = None srcParam = dstParam = None if swappedLink : srcNode = self.lastConnectCandidate.getNode () srcParam = self.lastConnectCandidate.param if self.lastConnectCandidate.isNode () : srcParam = self.lastConnectCandidate.getFirstOutputParam () dstNode = dstConnector.getNode () dstParam = dstConnector.param self.currentGfxLink.setSrcConnector ( self.lastConnectCandidate ) else : srcNode = srcConnector.getNode () srcParam = srcConnector.param dstNode = self.lastConnectCandidate.getNode () dstParam = self.lastConnectCandidate.param if self.lastConnectCandidate.isNode () : dstParam = self.lastConnectCandidate.getFirstInputParam () self.currentGfxLink.setDstConnector ( self.lastConnectCandidate ) link = NodeLink.build ( srcNode, dstNode, srcParam, dstParam ) #if not dstParam.isInput : # swap source and destination # self.currentGfxLink.swapConnectors () # link.swapNodes () self.currentGfxLink.link = link self.nodeNet.addLink ( link ) if usePyQt4 : self.emit ( QtCore.SIGNAL ( 'nodeConnectionChanged' ), self.currentGfxLink.dstConnector.getGfxNode (), self.currentGfxLink.dstConnector.param ) else : self.nodeConnectionChanged.emit ( self.currentGfxLink.dstConnector.getGfxNode (), self.currentGfxLink.dstConnector.param ) self.lastConnectCandidateReset () self.currentGfxLink = None self.state = 'idle' # # onStartNodeConnector # def onStartNodeConnector ( self, connector, scenePos ) : # if DEBUG_MODE : print '>> WorkArea::onStartNodeConnector' self.state = 'traceNodeConnector' newNode = ConnectorNode () self.nodeNet.addNode ( newNode ) newParam = connector.param.copy () newParam.isInput = False newInParam = newParam.copy () newOutParam = newParam.copy () newNode.addInputParam ( newInParam ) newNode.addOutputParam ( newOutParam ) newConnector = GfxNodeConnector ( newParam, connector.radius, node = newNode ) newConnector.brush = connector.brush newConnector.setPos ( scenePos ) newConnector.moveBy ( -connector.radius, -connector.radius ) self.lastConnectCandidate = newConnector self.scene ().addItem ( newConnector ) newConnector.hilite ( True ) srcNode = connector.getNode () srcParam = connector.getOutputParam () dstNode = newConnector.getNode () dstParam = newConnector.getInputParam () # # swap link direction only for connectors # in open chain connected to input node parameter # swappedLink = False if connector.isConnectedToInput () and not connector.isConnectedToOutput () : if DEBUG_MODE : print '*** swap link direction ***' swappedLink = True srcNode = newConnector.getNode () srcParam = newConnector.getOutputParam () dstNode = connector.getNode () dstParam = connector.getInputParam () link = NodeLink.build ( srcNode, dstNode, srcParam, dstParam ) # if swappedLink : link.swapNodes () self.nodeNet.addLink ( link ) #if DEBUG_MODE : self.nodeNet.printInfo () # preserve existing links for parameter connectors if connector.isLinked () and not connector.isNode () : if connector.isInput () : #print '*** preserve input ***' # TODO!!! # This is very rough code -- needs to be wrapped in functions gfxLinks = connector.getInputGfxLinks () for gfxLink in gfxLinks : gfxLink.setDstConnector ( newConnector ) # remove gfxLink from previouse connector connector.removeGfxLink ( gfxLink ) # adjust destination for node link newConnector.getNode ().attachInputParamToLink ( newConnector.getInputParam (), gfxLink.link ) newConnector.getNode ().addChild ( gfxLink.link.srcNode ) connector.getNode ().removeChild ( gfxLink.link.srcNode ) gfxLink.link.dstNode = newConnector.getNode () gfxLink.link.dstParam = newConnector.getInputParam () else : #print '*** preserve output ***' gfxLinks = connector.getOutputGfxLinks () for gfxLink in gfxLinks : gfxLink.setSrcConnector ( newConnector ) # remove gfxLink from previouse connector connector.removeGfxLink ( gfxLink ) # adjust source for node link connector.getNode ().detachOutputParamFromLink ( gfxLink.link.srcParam, gfxLink.link ) newConnector.getNode ().attachOutputParamToLink ( newConnector.getOutputParam (), gfxLink.link ) #newConnector.getNode ().childs.add ( connector.getNode () ) gfxLink.link.dstNode.addChild ( newConnector.getNode () ) gfxLink.link.dstNode.removeChild ( connector.getNode () ) gfxLink.link.srcNode = newConnector.getNode () gfxLink.link.srcParam = newConnector.getOutputParam () #if DEBUG_MODE : self.nodeNet.printInfo () gfxLink = GfxLink ( link, connector, newConnector ) self.scene ().addItem ( gfxLink ) # # onTraceNodeConnector # def onTraceNodeConnector ( self, connector, scenePos ) : # #if DEBUG_MODE : print '>> WorkArea::onTraceNodeConnector' if self.lastConnectCandidate is not None : self.lastConnectCandidate.setPos ( scenePos ) self.lastConnectCandidate.moveBy ( -connector.radius, -connector.radius ) # # onEndNodeConnector # def onEndNodeConnector ( self, connector, scenePos ) : # if DEBUG_MODE : print '>> WorkArea::onEndNodeConnector' print '>> lastConnectCandidate.node.type = %s' % self.lastConnectCandidate.node.type self.lastConnectCandidateReset () self.state = 'idle' # # onRemoveNode # def onRemoveNode ( self, gfxNode ) : # print ">> WorkArea.onRemoveNode %s (id = %d)" % ( gfxNode.node.label, gfxNode.node.id ) if usePyQt4 : self.emit ( QtCore.SIGNAL ( 'gfxNodeRemoved' ), gfxNode ) else : self.gfxNodeRemoved.emit ( gfxNode ) self.scene ().removeItem ( gfxNode ) self.nodeNet.removeNode ( gfxNode.node ) #if DEBUG_MODE : self.nodeNet.printInfo () # # onRemoveLink # def onRemoveLink ( self, gfxLink ) : # print ">> WorkArea.onRemoveLink ..." self.scene ().removeItem ( gfxLink ) if gfxLink.link is not None : print "*** (id = %d)" % ( gfxLink.link.id ) srcConnector = gfxLink.srcConnector dstConnector = gfxLink.dstConnector self.nodeNet.removeLink ( gfxLink.link ) if srcConnector is not None : if DEBUG_MODE : print '*** srcConnector.parentItem().node.label = %s ' % srcConnector.getNode ().label #self.emit( QtCore.SIGNAL( 'nodeConnectionChanged' ), srcConnector.parentItem(), srcConnector.param ) if dstConnector is not None : if DEBUG_MODE : print '*** dstConnector.parentItem().node.label = %s ' % dstConnector.getNode ().label if usePyQt4 : self.emit ( QtCore.SIGNAL ( 'nodeConnectionChanged' ), dstConnector.getGfxNode (), dstConnector.param ) else : self.nodeConnectionChanged.emit ( dstConnector.getGfxNode (), dstConnector.param ) # # removeSelected # def removeSelected ( self ) : # if DEBUG_MODE : print '>> WorkArea.removeSelected: (before) nodes = %d links = %d' % ( len ( self.nodeNet.nodes.values () ), len ( self.nodeNet.links.values () ) ) selected = self.scene().selectedItems() for item in selected: if ( isinstance ( item, GfxLink ) or isinstance ( item, GfxNode ) or isinstance ( item, GfxNote ) or isinstance ( item, GfxSwatchNode ) or ( isinstance ( item, GfxNodeConnector ) and item.isNode () ) ) : item.remove () if DEBUG_MODE : print '>> WorkArea.removeSelected (after) nodes = %d links = %d' % ( len ( self.nodeNet.nodes.values ()), len ( self.nodeNet.links.values ()) ) # # dragEnterEvent # def dragEnterEvent ( self, event ) : # print '>> WorkArea.onDragEnterEvent' #for form_str in event.mimeData().formats(): # print str ( form_str ) # if form_str == 'text/uri-list' : # print event.mimeData().data( 'text/uri-list' ) mimedata = event.mimeData () if mimedata.hasFormat ( 'application/x-text' ) or mimedata.hasFormat ( 'text/uri-list' ): event.accept () else: event.ignore () # # dragMoveEvent # def dragMoveEvent ( self, event ) : #print ">> WorkArea.dragMoveEvent" mimedata = event.mimeData () if mimedata.hasFormat ( 'application/x-text' ) or mimedata.hasFormat ( 'text/uri-list' ): event.setDropAction ( QtCore.Qt.CopyAction ) event.accept () else: event.ignore () # # dropEvent # def dropEvent ( self, event ) : # import os if DEBUG_MODE : print ">> WorkArea.dropEvent" file_list = [] mimedata = event.mimeData () if mimedata.hasFormat ( 'application/x-text' ) : # decode drop stuff data = mimedata.data ( 'application/x-text' ) stream = QtCore.QDataStream ( data, QtCore.QIODevice.ReadOnly ) if usePyQt4 : filename = QtCore.QString () else : filename = '' if not usePyQt5 : if usePySide : filename = stream.readString () else : stream >> filename else : filename = stream.readBytes () if DEBUG_MODE : print '* read itemFilename = %s' % ( filename ) file_list.append ( filename ) event.setDropAction ( QtCore.Qt.CopyAction ) event.accept () elif mimedata.hasFormat ( 'text/uri-list' ) : data = str ( mimedata.data( 'text/uri-list' ).data() ) #print data for item in data.split () : filename = str ( QtCore.QUrl( item ).toLocalFile () ) ( name, ext ) = os.path.splitext( os.path.basename( filename ) ) if DEBUG_MODE : print ':: %s (%s)' % ( filename, ext ) if ext == '.xml' : file_list.append ( filename ) else: event.ignore () for file_name in file_list : self.insertNodeNet ( file_name, self.mapToScene( event.pos () ) ) # # keyPressEvent # def keyPressEvent ( self, event ) : #print ">> WorkArea.keyPressEvent" QtModule.QGraphicsView.keyPressEvent ( self, event) # # wheelEvent # def wheelEvent ( self, event ) : #print ">> WorkArea.wheelEvent" # QtGui.QGraphicsView.wheelEvent( self, event) import sys, math scale = -1.0 if 'linux' in sys.platform: scale = 1.0 if not usePyQt5 : scaleFactor = math.pow( 2.0, scale * event.delta () / 600.0 ) else : delta = event.angleDelta () #print ( '>> delta rx = %d ry = %d' % ( delta.x (), delta.y () ) ) scaleFactor = math.pow( 2.0, scale * delta.y () / 600.0 ) # self.matrix () is depicated factor = self.transform ().scale ( scaleFactor, scaleFactor ).mapRect ( QtCore.QRectF ( -1, -1, 2, 2 ) ).width () if factor < 0.07 or factor > 100: return self.scale ( scaleFactor, scaleFactor ) # # mousePressEvent # def mousePressEvent ( self, event ) : #print ">> WorkArea.mousePressEvent" #self.setFocus () self.startPos = self.mapToScene ( event.pos () ) self.pressed = True button = event.button () modifiers = event.modifiers () if ( button == QtCore.Qt.MidButton or ( button == QtCore.Qt.LeftButton and modifiers == QtCore.Qt.ShiftModifier ) ) : self.state = 'pan' return if button == QtCore.Qt.RightButton and modifiers == QtCore.Qt.ShiftModifier : self.state = 'zoom' return QtModule.QGraphicsView.mousePressEvent ( self, event ) # # mouseDoubleClickEvent # def mouseDoubleClickEvent ( self, event ) : # #print ">> WorkArea.mouseDoubleClickEvent" selected = self.scene ().selectedItems () QtModule.QGraphicsView.mouseDoubleClickEvent ( self, event ) # # mouseMoveEvent # def mouseMoveEvent ( self, event ) : #print ">> WorkArea.mouseMoveEvent" #if self.pressed : currentPos = self.mapToScene( event.pos() ) if self.state == 'pan' : deltaPos = currentPos - self.startPos self.setInteractive ( False ) self.translate ( deltaPos.x (), deltaPos.y () ) self.setInteractive ( True ) elif self.state == 'zoom' : # import sys, math deltaPos = currentPos - self.startPos scale = -1.0 if 'linux' in sys.platform: scale = 1.0 scaleFactor = math.pow ( 2.0, scale * max ( deltaPos.x (), deltaPos.y () ) / 200.0 ) # factor = self.transform ().scale ( scaleFactor, scaleFactor ).mapRect ( QtCore.QRectF( -1, -1, 2, 2 ) ).width () if factor < 0.07 or factor > 100: return # update view matrix self.setInteractive ( False ) self.scale ( scaleFactor, scaleFactor ) self.translate ( -deltaPos.x () * scaleFactor, -deltaPos.y () * scaleFactor ) self.setInteractive ( True ) #self.startPos = currentPos else : QtModule.QGraphicsView.mouseMoveEvent ( self, event ) # # mouseReleaseEvent # def mouseReleaseEvent ( self, event ) : #print ">> WorkArea.mouseReleaseEvent" if self.state in [ 'pan', 'zoom' ] : self.state = 'idle' self.startPos = None self.pressed = False QtModule.QGraphicsView.mouseReleaseEvent ( self, event ) # # resetZoom # def resetZoom ( self ) : # if DEBUG_MODE : print ( ">> WorkArea.resetZoom" ) self.setInteractive ( False ) self.resetTransform() self.centerOn ( 0.0, 0.0 ) self.setInteractive ( True ) # # viewportEvent # def viewportEvent ( self, event ) : #case QEvent::TouchBegin: # case QEvent::TouchUpdate: # case QEvent::TouchEnd: if event.type() == QtCore.QEvent.TouchBegin : if DEBUG_MODE : print ( ">> WorkArea.QEvent.TouchBegin" ) return QtModule.QGraphicsView.viewportEvent ( self, event ) # # deselectAllNodes # def deselectAllNodes ( self ) : selected = self.scene().selectedItems() for item in selected : item.setSelected ( False ) # # openNodeNet # def openNodeNet ( self, filename, pos = None ) : # ( nodes, links ) = self.nodeNet.open ( normPath ( filename ) ) for node in nodes : self.addGfxNode ( node ) for link in links : self.addGfxLink ( link ) # # insertNodeNet # # Called by signal 'addNode' def insertNodeNet ( self, filename, pos = None ) : # if DEBUG_MODE : print ( '>> WorkArea.insertNodeNet filename = ' + filename ) if DEBUG_MODE : print ( ">> WorkArea.insertNodeNet (before) nodes = %d links = %d" % ( len(self.nodeNet.nodes.values()), len(self.nodeNet.links.values()) ) ) ( nodes, links ) = self.nodeNet.insert ( normPath ( filename ) ) if pos == None : # on dblclk -- insert node at left border of sceneBound sceneBound = self.scene().itemsBoundingRect () if not sceneBound.isNull () : x_offset = sceneBound.x() - self.minGap pos = QtCore.QPointF ( x_offset, 0 ) self.deselectAllNodes () for node in nodes : self.addGfxNode ( node, pos ) for link in links : self.addGfxLink ( link ) if DEBUG_MODE : print ( '>> WorkArea.insertNodeNet (after) nodes = %d links = %d' % ( len ( self.nodeNet.nodes.values ()), len ( self.nodeNet.links.values () ) ) ) # # copyNodes # def copyNodes ( self, clipboard, cutNodes = False ) : # if DEBUG_MODE : print ( '>> WorkArea.copyNodes ( cutNodes = %s )' % str ( cutNodes ) ) dupNodeNet = NodeNetwork ( 'clipboard' ) for gfxNode in self.selectedNodes : dupNode = gfxNode.node.copy () dupNodeNet.addNode ( dupNode ) for gfxNode in self.selectedNodes : for link in gfxNode.node.getInputLinks () : #link.printInfo () dupLink = link.copy () dupDstNode = dupNodeNet.getNodeByID ( gfxNode.node.id ) if dupDstNode is not None : dupDstParam = dupDstNode.getInputParamByName ( link.dstParam.name ) dupLink.setDst ( dupDstNode, dupDstParam ) ( srcNode, srcParam ) = dupLink.getSrc () dupSrcNode = dupNodeNet.getNodeByID ( srcNode.id ) if dupSrcNode is not None : # if srcNode is inside dupNodeNet dupSrcParam = dupSrcNode.getOutputParamByName ( srcParam.name ) dupLink.setSrc ( dupSrcNode, dupSrcParam ) dupNodeNet.addLink ( dupLink ) dom = QtXml.QDomDocument ( dupNodeNet.name ) dupNodeNet.parseToXML ( dom ) clipboard.clear () clipboard.setText ( dom.toString () ) # . fromUtf16 () .fromUtf8 () encode( 'utf-8' ) unicode ( dom.toByteArray () ) toString () if cutNodes : self.removeSelected () # # pasteNodes # def pasteNodes ( self, clipboard ) : # if DEBUG_MODE : print ( '>> WorkArea.pasteNodes ...' ) nodes = [] links = [] dom = QtXml.QDomDocument ( 'clipboard' ) dom.setContent ( clipboard.text () ) root = dom.documentElement () if root.nodeName () == 'node' : nodes.append ( self.nodeNet.addNodeFromXML ( root ) ) self.nodeNet.correct_id ( nodes, links ) elif root.nodeName () == 'nodenet' : #print ':: parsing nodenet from XML ...' nodeNet = NodeNetwork ( 'tmp', root ) ( nodes, links ) = self.nodeNet.add ( nodeNet ) else : print '!! unknown XML document format' return offsetPos = QtCore.QPointF ( self.minGap, self.minGap / 2 ) self.deselectAllNodes () for node in nodes : self.addGfxNode ( node, offsetPos ) for link in links : self.addGfxLink ( link ) # # duplicateNodes # def duplicateNodes ( self, preserveLinks = False ) : # if DEBUG_MODE : print ( '>> WorkArea.duplicateNode ( preserveLinks = %s )' % str ( preserveLinks ) ) dupNodeNet = NodeNetwork ( 'duplicate' ) for gfxNode in self.selectedNodes : dupNode = gfxNode.node.copy () dupNodeNet.addNode ( dupNode ) for gfxNode in self.selectedNodes : for link in gfxNode.node.getInputLinks () : #link.printInfo () dupLink = link.copy () dupDstNode = dupNodeNet.getNodeByID ( gfxNode.node.id ) if dupDstNode is not None : dupDstParam = dupDstNode.getInputParamByName ( link.dstParam.name ) dupLink.setDst ( dupDstNode, dupDstParam ) ( srcNode, srcParam ) = dupLink.getSrc () dupSrcNode = dupNodeNet.getNodeByID ( srcNode.id ) if dupSrcNode is not None : # if srcNode is inside dupNodeNet dupSrcParam = dupSrcNode.getOutputParamByName ( srcParam.name ) dupLink.setSrc ( dupSrcNode, dupSrcParam ) dupNodeNet.addLink ( dupLink ) else : # if this is outside links if preserveLinks : dupNodeNet.addLink ( dupLink ) else : dupLink.setSrc ( None, None ) dupLink.setDst ( None, None ) #if DEBUG_MODE : dupNodeNet.printInfo () ( nodes, links ) = self.nodeNet.add ( dupNodeNet ) offsetPos = QtCore.QPointF ( self.minGap, self.minGap / 2 ) self.deselectAllNodes () for node in nodes : self.addGfxNode ( node, offsetPos ) for link in links : self.addGfxLink ( link ) # # newNodeNetFromList # def nodeNetFromSelected ( self, nodeNetName, preserveLinks = False ) : # if DEBUG_MODE : print ( '>> WorkArea.nodeNetFromSelected ( preserveLinks = %s )' % str ( preserveLinks ) ) dupNodeNet = NodeNetwork ( nodeNetName ) for gfxNode in self.selectedNodes : dupNode = gfxNode.node.copy () dupNodeNet.addNode ( dupNode ) for gfxNode in self.selectedNodes : for link in gfxNode.node.getInputLinks () : #link.printInfo () dupLink = link.copy () dupDstNode = dupNodeNet.getNodeByID ( gfxNode.node.id ) if dupDstNode is not None : dupDstParam = dupDstNode.getInputParamByName ( link.dstParam.name ) dupLink.setDst ( dupDstNode, dupDstParam ) ( srcNode, srcParam ) = dupLink.getSrc () dupSrcNode = dupNodeNet.getNodeByID ( srcNode.id ) if dupSrcNode is not None : # if srcNode is inside dupNodeNet dupSrcParam = dupSrcNode.getOutputParamByName ( srcParam.name ) dupLink.setSrc ( dupSrcNode, dupSrcParam ) dupNodeNet.addLink ( dupLink ) else : # if this is outside links if preserveLinks : dupNodeNet.addLink ( dupLink ) else : dupLink.setSrc ( None, None ) dupLink.setDst ( None, None ) return dupNodeNet
class ParamWidget ( QtModule.QWidget ) : # # __init__ # def __init__ ( self, param, gfxNode, ignoreSubtype = False ) : # QtModule.QWidget.__init__ ( self ) # # Define signals for PyQt5 # if usePySide or usePyQt5 : # self.nodeParamRemoved = Signal () # self.param = param self.gfxNode = gfxNode self.ignoreSubtype = ignoreSubtype # if widget is used in NodeEditor, then ignoreSubtype = True self.buildGeneralGui () self.buildGui () self.ui.updateGui ( self.param.value ) #self.connectSignals () #self.connect( self.param, QtCore.SIGNAL( 'paramChanged(QObject)' ), self.onParamChanged ) #if DEBUG_MODE : print ">> ParamWidget (%s.%s) __init__" % ( self.gfxNode.node.label, self.param.label ) # # __del__ # def __del__ ( self ) : # if DEBUG_MODE : print ( '>> ParamWidget( %s ).__del__ ' % self.param.name ) # # connectSignals # def connectSignals ( self ) : # pass # # setEnabled # def setEnabled ( self, enabled = True ) : # for hl in self.param_vl.children () : for i in range ( hl.count () ) : obj = hl.itemAt ( i ).widget () if obj is not None : obj.setEnabled ( enabled ) # # onParamChanged # def onParamChanged ( self, param ) : # if DEBUG_MODE : print ( ">> ParamWidget( %s ).onParamChanged" % param.name ) self.ui.disconnectSignals ( self ) self.ui.updateGui ( self.param.value ) self.ui.connectSignals ( self ) #self.emit ( QtCore.SIGNAL( 'onParamChanged(QObject)' ), param ) # # buildGeneralGui # def buildGeneralGui ( self ) : #if DEBUG_MODE : print ">> ParamWidget buildGeneralGui" self.label_vl = QtModule.QVBoxLayout () self.label_vl.setSpacing ( UI.SPACING ) self.label_vl.setContentsMargins ( 0, 0, 0, 0 ) self.label_vl.setAlignment ( QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft ) self.hl = QtModule.QHBoxLayout () self.hl.setSpacing ( UI.SPACING ) self.hl.setContentsMargins ( 0, 0, 0, 0 ) self.hl.setAlignment ( QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft ) # vertical layout for parametrs values (e.g. output links or matrix rows) self.param_vl = QtModule.QVBoxLayout () self.param_vl.setSpacing ( UI.SPACING ) self.param_vl.setContentsMargins ( 0, 0, 0, 0 ) self.param_vl.setAlignment ( QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft ) # # add 'isShaderParam' check box only for RSL nodes # if self.gfxNode is not None : # # add "Use as Shader parameter" checkbox # #if ( self.gfxNode.node.type in VALID_RSL_NODE_TYPES ) and ( self.param.type in VALID_RSL_PARAM_TYPES ) and ( self.param.provider != 'attribute' ) : if ( self.gfxNode.node.format == 'rsl' ) and \ ( self.param.type in VALID_RSL_PARAM_TYPES ) and \ ( self.param.provider != 'attribute' ) : self.check = QtModule.QCheckBox ( self ) self.check.setMinimumSize ( QtCore.QSize ( UI.CHECK_WIDTH, UI.HEIGHT ) ) self.check.setMaximumSize ( QtCore.QSize ( UI.CHECK_WIDTH, UI.HEIGHT ) ) self.check.setToolTip ( 'Use as Shader parameter' ) self.check.setChecked ( self.param.shaderParam ) if usePyQt4 : self.connect ( self.check, QtCore.SIGNAL ( 'stateChanged(int)' ), self.onShaderParamChanged ) else : self.check.stateChanged.connect ( self.onShaderParamChanged ) self.hl.addWidget ( self.check ) else : spacer = QtModule.QSpacerItem ( UI.LT_SPACE, UI.HEIGHT, QtModule.QSizePolicy.Minimum, QtModule.QSizePolicy.Minimum ) self.hl.addItem ( spacer ) # # add 'remove' button for removable parameters # if self.param.removable : self.removeButton = QtModule.QToolButton ( self ) sizePolicy = QtModule.QSizePolicy ( QtModule.QSizePolicy.Fixed, QtModule.QSizePolicy.Fixed ) sizePolicy.setHorizontalStretch ( 20 ) sizePolicy.setVerticalStretch ( 20 ) sizePolicy.setHeightForWidth ( self.removeButton.sizePolicy().hasHeightForWidth() ) self.removeButton.setSizePolicy ( sizePolicy ) self.removeButton.setMaximumSize ( QtCore.QSize ( 20, 20 ) ) icon = QtGui.QIcon () icon.addPixmap ( QtGui.QPixmap ( ':/edit_icons/resources/del_list.png' ), QtGui.QIcon.Normal, QtGui.QIcon.On ) self.removeButton.setIcon ( icon ) self.removeButton.setAutoRaise ( True ) self.removeButton.setToolTip ( 'Remove parameter' ) self.removeButton.setIconSize ( QtCore.QSize ( 16, 16 ) ) self.removeButton.setObjectName ( 'removeButton' ) self.hl.addWidget ( self.removeButton ) if usePyQt4 : QtCore.QObject.connect ( self.removeButton, QtCore.SIGNAL ( 'clicked()' ), self.onRemoveItem ) else : self.removeButton.clicked.connect ( self.onRemoveItem ) self.label = ParamLabel ( self, self.param ) self.helpMark = QtModule.QLabel ( self ) palette = QtGui.QPalette () palette.setColor ( QtGui.QPalette.WindowText, QtGui.QColor ( 0, 140, 0 ) ) font1 = QtGui.QFont () font1.setBold ( True ) self.helpMark.setPalette ( palette ) self.helpMark.setFont ( font1 ) self.helpMark.setText ( '' ) self.helpMark.setMinimumSize ( QtCore.QSize ( 6, UI.HEIGHT ) ) self.helpMark.setMaximumSize ( QtCore.QSize ( 6, UI.HEIGHT ) ) self.helpMark.setEnabled ( False ) if self.param.help is not None and self.param.help != '' : self.label.setWhatsThis ( self.param.help ) self.helpMark.setWhatsThis ( self.param.help ) self.helpMark.setText ( '?' ) self.helpMark.setEnabled ( True ) self.label.setAlignment ( QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter ) #self.label.setMinimumSize ( QtCore.QSize ( UI.LABEL_WIDTH, UI.HEIGHT ) ) #self.label.setMaximumSize ( QtCore.QSize ( UI.LABEL_WIDTH, UI.HEIGHT ) ) #self.vl.addWidget ( self.gui ) self.hl.addWidget ( self.label ) self.hl.addWidget ( self.helpMark ) #self.hl.addLayout ( self.param_vl ) #sp = QtModule.QSpacerItem ( 20, 20, QtModule.QSizePolicy.Expanding, QtModule.QSizePolicy.Minimum ) self.label_vl.addLayout ( self.hl ) sp_v = QtModule.QSpacerItem ( 0, 0, QtModule.QSizePolicy.Minimum, QtModule.QSizePolicy.Expanding ) self.label_vl.addItem ( sp_v ) # # onShaderParamChanged # def onShaderParamChanged ( self, value ) : # self.param.shaderParam = self.check.isChecked () self.gfxNode.updateGfxNodeParams ( True ) # # buildGui -- virtual method # should be overriden in inherited classes # def buildGui ( self ) : # pass #spacer = QtModule.QSpacerItem ( 20, 20, QtModule.QSizePolicy.Expanding, QtModule.QSizePolicy.Minimum ) #self.hl.addItem ( spacer ) # # onRemoveItem # def onRemoveItem ( self ) : # if DEBUG_MODE : print '>> ParamWidget( %s ).onRemoveItem ' % self.param.name if usePyQt4 : self.emit ( QtCore.SIGNAL ( 'nodeParamRemoved' ), self.param ) else : self.nodeParamRemoved.emit ( self.param )
class NodeParamView ( QtModule.QWidget ) : # # __init__ # def __init__ ( self ) : # QtModule.QWidget.__init__ ( self ) # # Define signals for PyQt5 # if usePySide or usePyQt5 : # self.nodeParamChangedSignal = Signal () self.nodeLabelChangedSignal = Signal () # self.gfxNode = None self.inputParamListTab = None self.outputParamListTab = None self.showConnected = False self.buildGui () self.updateGui () self.connectSignals () # # setNode # def setNode ( self, gfxNode ) : # #if DEBUG_MODE : print ">> NodeParamView.setNode" self.disconnectParamSignals () self.gfxNode = gfxNode self.inputParamListTab.setNode ( gfxNode ) self.outputParamListTab.setNode ( gfxNode ) self.nameEdit.setEnabled ( self.gfxNode is not None ) self.updateGui () self.connectParamSignals () # # connectSignals # def connectSignals ( self ) : # if usePyQt4 : self.connect ( self.nameEdit, QtCore.SIGNAL ( 'editingFinished()' ), self.nodeLabelChanged ) self.connect ( self.showConnectButton, QtCore.SIGNAL ( 'toggled(bool)' ), self.showConnections ) else : self.nameEdit.editingFinished.connect ( self.nodeLabelChanged ) self.showConnectButton.toggled.connect ( self.showConnections ) # # disconnectSignals # def disconnectSignals ( self ) : # if usePyQt4 : self.disconnect ( self.nameEdit, QtCore.SIGNAL ( 'editingFinished()' ), self.nodeLabelChanged ) self.disconnect ( self.showConnectButton, QtCore.SIGNAL ( 'toggled(bool)' ), self.showConnections ) else : self.nameEdit.editingFinished.disconnect ( self.nodeLabelChanged ) self.showConnectButton.toggled.disconnect ( self.showConnections ) # # connectParamSignals # def connectParamSignals ( self ) : #print ">> NodeParamView.connectParamSignals" if self.gfxNode is not None : for inputParam in self.gfxNode.node.inputParams : if usePyQt4 : self.connect ( inputParam, QtCore.SIGNAL ( 'paramChangedSignal(QObject)' ), self.onParamChanged ) else : inputParam.paramChangedSignal.connect ( self.onParamChanged ) for outputParam in self.gfxNode.node.outputParams : if usePyQt4 : self.connect ( outputParam, QtCore.SIGNAL ( 'paramChangedSignal(QObject)' ), self.onParamChanged ) else : outputParam.paramChangedSignal.connect ( self.onParamChanged ) # # disconnectParamSignals # def disconnectParamSignals ( self ) : #print ">> NodeParamView.disconnectParamSignals" if self.gfxNode is not None : for inputParam in self.gfxNode.node.inputParams : if usePyQt4 : self.disconnect ( inputParam, QtCore.SIGNAL ( 'paramChangedSignal(QObject)' ), self.onParamChanged ) else : inputParam.paramChangedSignal.disconnect ( self.onParamChanged ) for outputParam in self.gfxNode.node.outputParams : if usePyQt4 : self.disconnect ( outputParam, QtCore.SIGNAL ( 'paramChangedSignal(QObject)' ), self.onParamChanged ) else : outputParam.paramChangedSignal.disconnect ( self.onParamChanged ) # # showConnections # def showConnections ( self, show ) : # print ">> NodeParamView.showConnections %s" % show self.showConnected = show self.inputParamListTab.showConnected = show self.outputParamListTab.showConnected = show self.inputParamListTab.updateGui () self.outputParamListTab.updateGui () # # onParamChanged # def onParamChanged ( self, param ) : # if DEBUG_MODE : print ( ">> NodeParamView.onParamChanged node = %s param = %s" % ( self.gfxNode.node.label, param.name ) ) if usePyQt4 : self.emit ( QtCore.SIGNAL ( 'nodeParamChangedSignal' ), self.gfxNode, param ) # .node else : self.nodeParamChangedSignal.emit ( self.gfxNode, param ) # .node # # nodeLabelChanged # def nodeLabelChanged ( self ) : # #if DEBUG_MODE : print ">> NodeParamView.nodeLabelChanged" if self.gfxNode is not None : from core.meCommon import getParsedLabel newLabel = getParsedLabel ( self.nameEdit.text () ) #if DEBUG_MODE : print "** newLabel = %s" % newLabel if newLabel != '' : # update label only if realy changed if newLabel != self.gfxNode.node.label : # rename node label if same name exists in NodeNet if usePyQt4 : self.emit ( QtCore.SIGNAL ( 'nodeLabelChangedSignal' ), self.gfxNode, newLabel ) else : self.nodeLabelChangedSignal.emit ( self.gfxNode, newLabel ) self.nameEdit.clear () self.nameEdit.setText ( self.gfxNode.node.label ) # # buildGui # def buildGui ( self ) : # label = QtModule.QLabel () label.setMinimumSize ( QtCore.QSize ( UI.NODE_LABEL_WIDTH, UI.HEIGHT ) ) label.setMaximumSize ( QtCore.QSize ( UI.NODE_LABEL_WIDTH, UI.HEIGHT ) ) font = QtGui.QFont () label.setFont ( font ) #label.setAlignment(QtCore.Qt.AlignCenter) label.setText ( 'Label' ) self.nameEdit = QtModule.QLineEdit () self.nameEdit.setMaximumSize ( QtCore.QSize ( UI.MAX, UI.HEIGHT ) ) self.nameEdit.setEnabled ( False ) self.showConnectButton = QtModule.QToolButton ( self ) sizePolicy = QtModule.QSizePolicy ( QtModule.QSizePolicy.Fixed, QtModule.QSizePolicy.Fixed ) sizePolicy.setHorizontalStretch ( 20 ) sizePolicy.setVerticalStretch ( 20 ) sizePolicy.setHeightForWidth ( self.showConnectButton.sizePolicy().hasHeightForWidth() ) self.showConnectButton.setSizePolicy ( sizePolicy ) self.showConnectButton.setMaximumSize ( QtCore.QSize ( 20, 20 ) ) icon = QtGui.QIcon () icon.addPixmap ( QtGui.QPixmap ( ':/show_icons/resources/show_connect.png' ), QtGui.QIcon.Normal, QtGui.QIcon.On ) self.showConnectButton.setIcon ( icon ) self.showConnectButton.setAutoRaise ( False ) self.showConnectButton.setCheckable ( True ) self.showConnectButton.setChecked ( self.showConnected ) self.showConnectButton.setToolTip ( 'Show connected parameters' ) #self.showConnectButton.setIconSize ( QtCore.QSize ( 16, 16 ) ) self.showConnectButton.setObjectName ( 'showConnectButton' ) headerLayout = QtModule.QHBoxLayout () headerLayout.setSpacing ( UI.SPACING ) headerLayout.setContentsMargins ( UI.SPACING, UI.SPACING, UI.SPACING, UI.SPACING ) headerLayout.setStretch ( 1, 1 ) headerLayout.addWidget ( label ) headerLayout.addWidget ( self.nameEdit ) headerLayout.addWidget ( self.showConnectButton ) mainLayout = QtModule.QVBoxLayout () mainLayout.addLayout ( headerLayout ) self.params_tabs = QtModule.QTabWidget ( self ) self.inputParamListTab = NodeParamListTab ( self, self.gfxNode, isInput = True, showConnected = self.showConnected ) self.params_tabs.addTab ( self.inputParamListTab, 'Input' ) self.outputParamListTab = NodeParamListTab ( self, self.gfxNode, isInput = False, showConnected = self.showConnected ) self.params_tabs.addTab ( self.outputParamListTab, 'Output' ) self.params_tabs.setCurrentIndex ( 0 ) mainLayout.addWidget ( self.params_tabs ) self.setLayout ( mainLayout ) # # updateGui # def updateGui ( self ) : # #if DEBUG_MODE : print '>> NodeParamView.updateGui' self.nameEdit.clear () if self.gfxNode is not None : self.nameEdit.setText ( self.gfxNode.node.label ) self.inputParamListTab.updateGui () self.outputParamListTab.updateGui ()
def __init__ ( self ) : # QtModule.QGraphicsView.__init__ ( self ) # # Define signals for PyQt5 # if usePySide or usePyQt5 : # self.selectNodes = Signal () #( list, list ) self.nodeConnectionChanged = Signal () #QtCore.pyqtSignal ( QtModule.QGraphicsObject, QtCore.QObject ) self.gfxNodeAdded = Signal () #( QtModule.QGraphicsObject ) self.gfxNodeRemoved = Signal () #( QtModule.QGraphicsObject ) # self.drawGrid = True self.gridSnap = False self.straightLinks = False self.reverseFlow = False self.gridSize = 10 self.minGap = 120 self.current_Z = 1 self.state = 'idle' self.pressed = False self.startPos = None self.lastConnectCandidate = None self.currentGfxLink = None self.inspectedNode = None self.nodeNet = None self.selectedNodes = [] self.selectedLinks = [] # set scene scene = WorkAreaScene ( self ) scene.setSceneRect ( -10000, -10000, 20000, 20000 ) #scene.setItemIndexMethod ( QtGui.QGraphicsScene.NoIndex ) self.setScene ( scene ) # qt graphics stuff self.setCacheMode ( QtModule.QGraphicsView.CacheBackground ) self.setRenderHint ( QtGui.QPainter.Antialiasing ) self.setTransformationAnchor ( QtModule.QGraphicsView.AnchorUnderMouse ) # QtGui.QGraphicsView.AnchorUnderMouse self.setResizeAnchor ( QtModule.QGraphicsView.AnchorUnderMouse ) # AnchorViewCenter self.setDragMode ( QtModule.QGraphicsView.RubberBandDrag ) self.setMouseTracking ( False ) self.setAcceptDrops ( True ) """ viewport = self.viewport() if viewport is not None : print ">> WorkArea viewport.setAcceptTouchEvents" #proxy = QtGui.QGraphicsProxyWidget () proxy = viewport.graphicsProxyWidget () if proxy is not None : proxy.setAcceptTouchEvents ( True ) #self.setAttribute ( QtGui.AcceptTouchEvents, True ) #viewport()->setAttribute(Qt::WA_AcceptTouchEvents); #setDragMode(ScrollHandDrag); #Qt::WA_AcceptTouchEvents """ self.viewBrush = QtGui.QBrush ( QtGui.QColor ( 148, 148, 148 ) ) self.setBackgroundBrush ( self.viewBrush ) # self.connectSignals () if DEBUG_MODE : print ">> WorkArea. __init__"
class Node ( QtCore.QObject ) : # id = 0 # # __init__ # def __init__ ( self, xml_node = None, nodenet = None ) : # QtCore.QObject.__init__ ( self ) # # Define signals for PyQt5 # if usePySide or usePyQt5 : # self.nodeUpdated = Signal () # QtCore.pyqtSignal ( [QtCore.QObject] ) self.nodeParamsUpdated = Signal () #QtCore.pyqtSignal ( [QtCore.QObject] ) # self.id = None self.name = None self.label = None self.type = None self.version = None self.format = None self.parent = None self.dirty = False self.author = None self.help = None self.icon = None self.master = None self.code = None # Node code (RSL, RIB, ... ) self.control_code = None # python code executed before node computation self.computed_code = None # code collected after compute on all connected nodes self.event_code = {} #self.event_code [ 'ParamLabelRenamed' ] = None #self.event_code [ 'ParamAdded' ] = None #self.event_code [ 'ParamRemoved' ] = None self.display = True self.computedInputParams = None self.computedOutputParams = None self.computedLocalParams = None self.computedIncludes = None self.computedLocals = None self.computedCode = None #self.previewCode = None self.inputParams = [] self.outputParams = [] self.internals = [] self.includes = [] self.inputLinks = {} self.outputLinks = {} self.childs = set() self.nodenet = nodenet # position from GfxNode self.offset = ( 0, 0 ) if xml_node != None : self.parseFromXML ( xml_node ) # # __del__ # def __del__ ( self ) : # if DEBUG_MODE : print ( '>> Node( %s ).__del__' % self.label ) # # build # @classmethod def build ( cls ) : # set unique id while building node = cls () Node.id += 1 node.id = Node.id return node # # copy # def copy ( self ) : assert 0, 'copy needs to be implemented!' # # updateNode # def updateNode ( self, emit_signal = False ) : # if DEBUG_MODE : print ( '>> Node( %s ).updateNode' % self.label ), emit_signal if emit_signal : if DEBUG_MODE : print ( '** emit signal nodeUpdated' ) if usePyQt4 : self.emit ( QtCore.SIGNAL ( 'nodeUpdated' ), self ) else : self.nodeUpdated.emit ( self ) # # updateNodeParams # def updateNodeParams ( self, emit_signal = False ) : # if DEBUG_MODE : print ( '>> Node( %s ).updateNodeParams' % self.label ), emit_signal if emit_signal : if usePyQt4 : self.emit ( QtCore.SIGNAL ( 'nodeParamsUpdated' ), self ) else : self.nodeParamsUpdated.emit ( self ) # # addChild # def addChild ( self, node ) : self.childs.add ( node ) # # removeChild # def removeChild ( self, node ) : # if node in self.childs : self.childs.remove ( node ) if DEBUG_MODE : print ( '** Node(%s).removeChild %s' % ( self.label, node.label ) ) else : if DEBUG_MODE : print ( '!! Node(%s).removeChild child %s is not in the list' % ( self.label, node.label ) ) # # printInfo # def printInfo ( self ) : # print ( ':: Node (id = %d) label = %s' % ( self.id, self.label ) ) print ( '** Node inputLinks:' ) for param in self.inputLinks.keys () : print ( '\t* param: %s (%s) linked to ' % ( param.name, param.label ) ) self.inputLinks [ param ].printInfo () print ( '** Node outputLinks:' ) #print '*****', self.outputLinks for param in self.outputLinks.keys () : print ( '\t* param: %s (%s) linked to ' % ( param.name, param.label ) ) linklist = self.outputLinks [ param ] for link in linklist : link.printInfo () print ( '** Node children:' ) for child in self.childs : print ( '\t* %s' % child.label ) # # addInputParam # def addInputParam ( self, param ) : # param.isInput = True # to be sure that name and label is unique if param.name in self.getParamsNames () : self.renameParamName ( param, param.name ) if param.label in self.getParamsLabels () : self.renameParamLabel ( param, param.label ) self.inputParams.append ( param ) if self.event_code : if 'ParamAdded' in self.event_code.keys () : exec ( self.event_code [ 'ParamAdded' ], { 'param' : param, 'self' : self } ) # # addOutputParam # def addOutputParam ( self, param ) : # param.isInput = False # to be sure that name and label is unique if param.name in self.getParamsNames () : self.renameParamName ( param, param.name ) if param.label in self.getParamsLabels () : self.renameParamLabel ( param, param.label ) self.outputParams.append ( param ) if self.event_code : if 'ParamAdded' in self.event_code.keys () : exec ( self.event_code [ 'ParamAdded' ], { 'param' : param, 'self' : self } ) # # addInternal # def addInternal ( self, newName ) : #print '--> add internal: %s' % internal internal = newName if internal != '' : from meCommon import getUniqueName internal = getUniqueName ( newName, self.internals ) self.internals.append ( internal ) return internal # # addInclude # def addInclude ( self, newName ) : #print '--> add include: %s' % include include = newName if include != '' : from meCommon import getUniqueName include = getUniqueName ( newName, self.includes ) self.includes.append ( include ) return include # # attachInputParamToLink # def attachInputParamToLink ( self, param, link ) : # self.inputLinks [ param ] = link # # attachOutputParamToLink # def attachOutputParamToLink ( self, param, link ) : # #if DEBUG_MODE : print ">> Node::attachOutputParamToLink param = %s" % param.name if not param in self.outputLinks.keys () : self.outputLinks [ param ] = [] if not link in self.outputLinks [ param ] : self.outputLinks [ param ].append ( link ) # # detachInputParam # def detachInputParam ( self, param ) : # removedLink = None if DEBUG_MODE : print ( ">> Node::detachInputParam param = %s" % param.name ) if param in self.inputLinks.keys () : removedLink = self.inputLinks.pop ( param ) return removedLink # # detachOutputParam # def detachOutputParam ( self, param ) : # removedLinks = [] if param in self.outputLinks.keys () : outputLinks = self.outputLinks [ param ] for link in outputLinks : removedLinks.append ( link ) self.outputLinks.pop ( param ) return removedLinks # # detachOutputParamFromLink # def detachOutputParamFromLink ( self, param, link ) : # removedLink = None if param in self.outputLinks.keys () : outputLinks = self.outputLinks [ param ] if link in outputLinks : removedLink = link outputLinks.remove ( link ) return removedLink # # isInputParamLinked # def isInputParamLinked ( self, param ) : return param in self.inputLinks.keys () # # isOutputParamLinked # def isOutputParamLinked ( self, param ) : return param in self.outputLinks.keys () # # getLinkedSrcNode # def getLinkedSrcNode ( self, param ) : # returns node linked to input parameter param, # skipping all ConnectorNode # #if DEBUG_MODE : print '* getLinkedSrcNode node = %s param = %s' % ( self.label, param.label ) srcNode = None srcParam = None if self.isInputParamLinked ( param ) : #if DEBUG_MODE : print '* isInputParamLinked' link = self.inputLinks [ param ] if link.srcNode.type == 'connector' : if len ( link.srcNode.inputParams ) : firstParam = link.srcNode.inputParams [0] ( srcNode, srcParam ) = link.srcNode.getLinkedSrcNode ( firstParam ) else : if DEBUG_MODE : print ( '* no inputParams at connector %s' % ( link.srcNode.label ) ) else : srcNode = link.srcNode srcParam = link.srcParam return ( srcNode, srcParam ) # # getLinkedDstNodes # def getLinkedDstNodes ( self, param, dstConnections = [] ) : # returns nodes linked to output parameter param, # skipping all ConnectorNode # #if DEBUG_MODE : print '*** getLinkedDstNodese node = %s param = %s' % ( self.label, param.label ) dstNode = None dstParam = None # dstConnections = [] if self.isOutputParamLinked ( param ) : #if DEBUG_MODE : print '* isOutputParamLinked' dstLinks = self.getOutputLinks ( param ) for link in dstLinks : if link.dstNode.type == 'connector' : #if DEBUG_MODE : print '* link.dstNode.type == connector' connectorOutputParams = link.dstNode.outputParams if len ( connectorOutputParams ) > 0 : for connectorOutputParam in connectorOutputParams : connectorDstConnections = [] retList = link.dstNode.getLinkedDstNodes ( connectorOutputParam, connectorDstConnections ) for ( retNode, retParam ) in retList : dstConnections.append ( ( retNode, retParam ) ) else : if DEBUG_MODE : print ( '* no outputParams at connector %s' % ( link.dstNode.label ) ) else : dstNode = link.dstNode dstParam = link.dstParam dstConnections.append ( ( dstNode, dstParam ) ) return dstConnections # # removeParam # def removeParam ( self, param ) : # if self.event_code : if 'ParamRemoving' in self.event_code.keys () : exec ( self.event_code [ 'ParamRemoving' ], { 'param' : param, 'self' : self } ) removedLinks = [] if param.isInput : link = self.detachInputParam ( param ) if link is not None : removedLinks.append ( link ) self.inputParams.remove ( param ) else : removedLinks = self.detachOutputParam ( param ) self.outputParams.remove ( param ) if self.event_code : if 'ParamRemoved' in self.event_code.keys () : exec ( self.event_code [ 'ParamRemoved' ], { 'param' : param, 'self' : self } ) return removedLinks # # getInputParamByName # def getInputParamByName ( self, name ) : # result = None for param in self.inputParams : if param.name == name : result = param break return result # # getOutputParamByName # def getOutputParamByName ( self, name ) : # result = None for param in self.outputParams : if param.name == name : result = param break return result # # getInputParamValueByName # def getInputParamValueByName ( self, name, CodeOnly = False ) : # result = None srcNode = srcParam = None param = self.getInputParamByName ( name ) ( srcNode, srcParam ) = self.getLinkedSrcNode ( param ) if srcNode is not None : # computation may be skipped if we need only value #if compute : srcNode.computeNode ( CodeOnly ) if self.computed_code is not None : self.computed_code += srcNode.computed_code result = srcNode.parseGlobalVars ( srcParam.getValueToStr () ) else : result = param.getValueToStr () return result # # return common list for input and output parameters # def getParamsList ( self ) : # params = self.inputParams + self.outputParams return params # # getParamsNames # def getParamsNames ( self ) : # names = [] for pm in self.getParamsList () : names.append ( pm.name ) return names # # getParamsLabels # def getParamsLabels ( self ) : # labels = [] for pm in self.getParamsList () : labels.append ( pm.label ) return labels # # getInputLinks # def getInputLinks ( self ) : # inputLinks = [] for link in self.inputLinks.values () : inputLinks.append ( link ) return inputLinks # # getOutputLinks # def getOutputLinks ( self, param = None ) : # outputLinks = [] for link_list in self.outputLinks.values () : for link in link_list : if param is not None : if link.srcParam != param : continue outputLinks.append ( link ) return outputLinks # # getInputLinkByID # def getInputLinkByID ( self, id ) : # result = None for link in self.getInputLinks () : if link.id == id : result = link break return result # # getOutputLinkByID # def getOutputLinkByID ( self, id ) : # result = None for link in self.getOutputLinks () : if link.id == id : result = link break return result # # renameParamName # def renameParamName ( self, param, newName ) : # assign new unique name to param from meCommon import getUniqueName param.name = getUniqueName ( newName, self.getParamsNames() ) return param.name # # renameParamLabel # def renameParamLabel ( self, param, newLabel ) : # oldLabel = param.label if DEBUG_MODE : print ( ">> Node( %s ).renameParamLabel oldLabel = %s newLabel = %s" % ( self.label, oldLabel, newLabel ) ) if newLabel == '' : newLabel = self.param.name # assign new unique label to param from meCommon import getUniqueName param.label = getUniqueName ( newLabel, self.getParamsLabels () ) if self.event_code : if 'ParamLabelRenamed' in self.event_code.keys () : exec ( self.event_code [ 'ParamLabelRenamed' ], { 'param' : param, 'self' : self, 'oldLabel' : oldLabel } ) return param.label # # onParamChanged # def onParamChanged ( self, param ) : # if DEBUG_MODE : print ( ">> Node: onParamChanged node = %s param = %s (pass...)" % ( self.label, param.name ) ) pass #self.emit( QtCore.SIGNAL( 'onNodeParamChanged(QObject,QObject)' ), self, param ) # # getLabel # def getLabel ( self ) : return self.label # # getName # def getName ( self ) : return self.name # # getNodenetName # def getNodenetName ( self ) : return self.nodenet.getName () # # getInstanceName # def getInstanceName ( self ) : return getParsedLabel ( self.label ) # # getParamName # def getParamName ( self, param ) : # if param.isRibParam or param.provider == 'attribute': paramName = param.name elif param.provider == 'primitive' : paramName = getParsedLabel ( param.label ) else : paramName = self.getInstanceName () + '_' + getParsedLabel ( param.label ) return paramName # # getParamDeclaration # def getParamDeclaration ( self, param ) : # result = '' result += param.typeToStr () + ' ' result += self.getParamName ( param ) if param.isArray () and not param.isRibParam : arraySize = '' if param.arraySize > 0 : arraySize = str ( param.arraySize ) result += '[%s]' % arraySize result += ' = ' + param.getValueToStr () + ';\n' return result # # parseFromXML # def parseFromXML ( self, xml_node ) : # id_node = xml_node.attributes ().namedItem ( 'id' ) if not id_node.isNull () : self.id = int ( id_node.nodeValue () ) else : if DEBUG_MODE : print ( '>> Node::parseFromXML id is None' ) self.name = str ( xml_node.attributes ().namedItem ( 'name' ).nodeValue () ) self.label = str ( xml_node.attributes ().namedItem ( 'label' ).nodeValue () ) if self.label == '' : self.label = self.name #print '-> parsing from XML node name= %s label= %s' % ( self.name, self.label ) self.version = str ( xml_node.attributes ().namedItem ( 'version' ).nodeValue () ) self.parent = str ( xml_node.attributes ().namedItem ( 'parent' ).nodeValue () ) self.format = str ( xml_node.attributes ().namedItem ( 'format' ).nodeValue () ) self.author = str ( xml_node.attributes ().namedItem ( 'author' ).nodeValue () ) self.type = str ( xml_node.attributes ().namedItem ( 'type' ).nodeValue () ) # # try to convert from old format nodes # if self.version == '' or self.version is None : if self.format == '' or self.format is None : ( self.type, self.format ) = translateOldType ( self.type ) help_tag = xml_node.namedItem ( 'help' ) if not help_tag.isNull() : self.help = help_tag.toElement ().text () self.icon = str ( xml_node.attributes ().namedItem ( 'icon' ).nodeValue () ) input_tag = xml_node.namedItem ( 'input' ) if not input_tag.isNull () : xml_paramList = input_tag.toElement ().elementsByTagName ( 'property' ) for i in range ( 0, xml_paramList.length () ) : xml_param = xml_paramList.item ( i ) # # some parameters (String, Color, Point, Vector, Normal, Matrix ...) # have different string interpretation in RIB # isRibParam = ( self.format == 'rib' ) param = createParamFromXml ( xml_param, isRibParam, True ) # #param.isInput = True self.addInputParam ( param ) output_tag = xml_node.namedItem ( 'output' ) if not output_tag.isNull () : xml_paramList = output_tag.toElement ().elementsByTagName ( 'property' ) for i in range ( 0, xml_paramList.length () ) : xml_param = xml_paramList.item ( i ) # # some parameters (Color, Point, Vector, Normal, Matrix ...) # have different string interpretation in RIB # isRibParam = ( self.format == 'rib' ) param = createParamFromXml ( xml_param, isRibParam, False ) # #param.isInput = False self.addOutputParam ( param ) internal_tag = xml_node.namedItem ( 'internal' ) if not internal_tag.isNull () : xml_internalList = internal_tag.toElement ().elementsByTagName ( 'variable' ) for i in range ( 0, xml_internalList.length () ) : var_tag = xml_internalList.item ( i ) var = str ( var_tag.attributes ().namedItem ( 'name' ).nodeValue () ) self.addInternal ( var ) include_tag = xml_node.namedItem ( 'include' ) if not include_tag.isNull () : xml_includeList = include_tag.toElement ().elementsByTagName ( 'file' ) for i in range ( 0, xml_includeList.length () ) : inc_tag = xml_includeList.item ( i ) inc = str ( inc_tag.attributes ().namedItem ( 'name' ).nodeValue () ) self.addInclude ( inc ) offset_tag = xml_node.namedItem ( 'offset' ) if not offset_tag.isNull() : x = float ( offset_tag.attributes ().namedItem ( 'x' ).nodeValue () ) y = float ( offset_tag.attributes ().namedItem ( 'y' ).nodeValue () ) self.offset = ( x, y ) control_code_tag = xml_node.namedItem ( 'control_code' ) if not control_code_tag.isNull () : code_str = str ( control_code_tag.toElement ().text () ) if code_str.lstrip () == '' : code_str = None self.control_code = code_str else : # for temp. backward compatibility control_code_tag = xml_node.namedItem ( 'param_code' ) if not control_code_tag.isNull() : code_str = str ( control_code_tag.toElement ().text () ) if code_str.lstrip () == '' : code_str = None self.control_code = code_str code_tag = xml_node.namedItem ( 'code' ) if not code_tag.isNull () : code_str = str ( code_tag.toElement ().text () ) if code_str.lstrip () == '' : code_str = None self.code = code_str event_code_tag = xml_node.namedItem ( 'event_code' ) if not event_code_tag.isNull () : xml_handlerList = event_code_tag.toElement ().elementsByTagName ( 'handler' ) for i in range ( 0, xml_handlerList.length () ) : handler_tag = xml_handlerList.item ( i ) handler_name = str ( handler_tag.attributes ().namedItem ( 'name' ).nodeValue () ) code_str = str ( handler_tag.toElement ().text () ).lstrip () if code_str == '' : code_str = None self.event_code [ handler_name ] = code_str # # parseToXML # def parseToXML ( self, dom ) : # xml_node = dom.createElement ( 'node' ) if DEBUG_MODE : print ( '>> Node::parseToXML (id = %d)' % ( self.id ) ) if self.id is None : if DEBUG_MODE : print ( '>> Node::parseToXML id is None' ) xml_node.setAttribute ( 'id', str( self.id ) ) xml_node.setAttribute ( 'name', self.name ) if self.label != None : xml_node.setAttribute ( 'label', self.label ) if self.type != None : xml_node.setAttribute ( 'type', self.type ) if self.author != None : xml_node.setAttribute ( 'author', self.author ) if self.icon != None : xml_node.setAttribute ( 'icon', self.icon ) if self.version != None : xml_node.setAttribute ( 'version', self.version ) if self.parent != None : xml_node.setAttribute ( 'parent', self.parent ) if self.format != None : xml_node.setAttribute ( 'format', self.format ) if self.help != None : # append node help (short description) help_tag = dom.createElement ( 'help' ) help_text = dom.createTextNode ( self.help ) help_tag.appendChild ( help_text ) xml_node.appendChild ( help_tag ) input_tag = dom.createElement ( 'input' ) for param in self.inputParams : #print '--> parsing param to XML: %s ...' % param.name input_tag.appendChild ( param.parseToXML ( dom ) ) xml_node.appendChild ( input_tag ) output_tag = dom.createElement ( 'output' ) for param in self.outputParams : #print '--> parsing param to XML: %s ...' % param.name output_tag.appendChild ( param.parseToXML ( dom ) ) xml_node.appendChild ( output_tag ) internal_tag = dom.createElement ( 'internal' ) for var in self.internals : var_tag = dom.createElement( 'variable' ) var_tag.setAttribute ( 'name', var ) internal_tag.appendChild ( var_tag ) xml_node.appendChild ( internal_tag ) include_tag = dom.createElement ( 'include' ) for inc in self.includes : inc_tag = dom.createElement( 'file' ) inc_tag.setAttribute ( 'name', inc ) include_tag.appendChild ( inc_tag ) xml_node.appendChild ( include_tag ) if self.control_code != None : control_code_tag = dom.createElement ( 'control_code' ) control_code_data = dom.createCDATASection ( self.control_code ) control_code_tag.appendChild ( control_code_data ) xml_node.appendChild ( control_code_tag ) if self.code != None : code_tag = dom.createElement ( 'code' ) code_data = dom.createCDATASection ( self.code ) code_tag.appendChild ( code_data ) xml_node.appendChild ( code_tag ) if self.event_code : event_code_tag = dom.createElement ( 'event_code' ) print ( '*** write event_code' ) for key in self.event_code.keys () : print ( '*** write handler "%s"' % key ) handler_tag = dom.createElement( 'handler' ) handler_tag.setAttribute ( 'name', key ) event_code_tag.appendChild ( handler_tag ) handler_data = dom.createCDATASection ( self.event_code [ key ] ) handler_tag.appendChild ( handler_data ) xml_node.appendChild ( event_code_tag ) if self.offset != None : ( x, y ) = self.offset offset_tag = dom.createElement ( 'offset' ) offset_tag.setAttribute ( 'x', str (x) ) # have to use 'str' because PySide throws offset_tag.setAttribute ( 'y', str (y) ) # Overflow error for negative values here xml_node.appendChild ( offset_tag ) return xml_node # # getHeader # def getHeader ( self ) : assert 0, 'getHeader needs to be implemented!' # # getComputedCode # def getComputedCode ( self, CodeOnly = False ) : assert 0, 'getComputedCode needs to be implemented!' # # computeNode # def computeNode ( self, CodeOnly = False ) : assert 0, 'computeNode needs to be implemented!' # # collectComputed # def collectComputed ( self, computedCode, visitedNodes, CodeOnly = False ) : # print ( '>>> Node.collectComputed (empty)' ) # # parseGlobalVars # def parseGlobalVars ( self, parsedStr ) : # print ( '>>> Node.parseGlobalVars (empty)' ) # # execControlCode # def execControlCode ( self ) : # if self.control_code != None : control_code = self.control_code.lstrip () if control_code != '' : exec control_code # # copySetup # def copySetup ( self, newNode ) : # if DEBUG_MODE : print ( '>> Node( %s ).copySetup ' % self.label ) newNode.id = self.id name = self.name if name is None : name = str ( self.type ) newNode.name = name label = self.label if label is None : label = name newNode.label = label newNode.type = self.type newNode.author = self.author newNode.help = self.help newNode.icon = self.icon newNode.master = self.master newNode.display = self.display newNode.format = self.format newNode.parent = self.parent newNode.dirty = self.dirty newNode.offset = self.offset import copy newNode.code = copy.copy ( self.code ) newNode.control_code = copy.copy ( self.control_code ) newNode.event_code = copy.copy ( self.event_code ) #self.computed_code = None newNode.internals = copy.copy ( self.internals ) newNode.includes = copy.copy ( self.includes ) newNode.inputLinks = {} newNode.outputLinks = {} #newNode.childs = set () print ( '***newNode.childs: ', newNode.childs ) #newNode.childs = copy.copy ( self.childs ) newNode.inputParams = [] for param in self.inputParams : newNode.inputParams.append ( param.copy () ) newNode.outputParams = [] for param in self.outputParams : newNode.outputParams.append ( param.copy () ) return newNode # # save Node to .xml document # def save ( self ) : # result = False dom = QtXml.QDomDocument ( self.name ) xml_code = self.parseToXML ( dom ) dom.appendChild ( xml_code ) file = QFile ( self.master ) if file.open ( QtCore.QIODevice.WriteOnly ) : if file.write ( dom.toByteArray () ) != -1 : result = True file.close() return result # # getChildrenSet # def getChildrenSet ( self, children_set = set () ) : # for node in self.childs : children_set = node.getChildrenSet ( children_set ) children_set.add ( node ) return children_set # # getChildrenList # def getChildrenList ( self, children_list = [] ) : # for node in self.childs : children_list = node.getChildrenList ( children_list ) if node not in children_list : children_list.append ( node ) return children_list
def __init__ ( self, xml_node = None, nodenet = None ) : # QtCore.QObject.__init__ ( self ) # # Define signals for PyQt5 # if usePySide or usePyQt5 : # self.nodeUpdated = Signal () # QtCore.pyqtSignal ( [QtCore.QObject] ) self.nodeParamsUpdated = Signal () #QtCore.pyqtSignal ( [QtCore.QObject] ) # self.id = None self.name = None self.label = None self.type = None self.version = None self.format = None self.parent = None self.dirty = False self.author = None self.help = None self.icon = None self.master = None self.code = None # Node code (RSL, RIB, ... ) self.control_code = None # python code executed before node computation self.computed_code = None # code collected after compute on all connected nodes self.event_code = {} #self.event_code [ 'ParamLabelRenamed' ] = None #self.event_code [ 'ParamAdded' ] = None #self.event_code [ 'ParamRemoved' ] = None self.display = True self.computedInputParams = None self.computedOutputParams = None self.computedLocalParams = None self.computedIncludes = None self.computedLocals = None self.computedCode = None #self.previewCode = None self.inputParams = [] self.outputParams = [] self.internals = [] self.includes = [] self.inputLinks = {} self.outputLinks = {} self.childs = set() self.nodenet = nodenet # position from GfxNode self.offset = ( 0, 0 ) if xml_node != None : self.parseFromXML ( xml_node )
class NodeList ( QtModule.QWidget ) : # # __init__ # def __init__ ( self, parent ) : # QtModule.QWidget.__init__ ( self, parent ) # # Define signals for PyQt5 # if usePySide or usePyQt5 : # self.setActiveNodeList = Signal () self.addNode = Signal () # self.nodesLib = '' self.nodesDir = '' # This is always the same self.ui = Ui_nodeList () self.ui.setupUi ( self ) self.ui.treeView.setDragEnabled ( True ) #self.ui.treeView.setRootIsDecorated( True ) self.connectSignals () self.updateGui () # # connectSignals # def connectSignals ( self ) : # if usePyQt4 : QtCore.QObject.connect ( self.ui.treeView, QtCore.SIGNAL ( "pressed(QModelIndex)" ), self.clicked ) QtCore.QObject.connect ( self.ui.treeView, QtCore.SIGNAL ( "doubleClicked(QModelIndex)" ), self.doubleClicked ) else : self.ui.treeView.pressed.connect ( self.clicked ) self.ui.treeView.doubleClicked.connect ( self.doubleClicked ) # # updateGui # def updateGui ( self ) : # if self.nodesLib != '' : # self.ui.treeView.setupModel( self.nodesLib.model ) self.ui.treeView.reset () self.ui.treeView.setModel ( self.nodesLib.model ) self.ui.infoText.clear () #self.ui.infoText.setText( "<i>Node:</i><br /><i>Author:</i><br />" ) # # setLibrary # def setLibrary ( self, dirName ) : # self.nodesDir = dirName self.nodesLib = NodeLibrary ( dirName ) self.updateGui() # # reloadLibrary # def reloadLibrary ( self ) : # print '>> NodeList: reloadLibrary' self.nodesLib = NodeLibrary ( self.nodesDir ) self.updateGui () # # clicked # def clicked ( self, index ) : # print ">> NodeList::clicked " item = self.nodesLib.model.itemFromIndex ( index ) self.showDescription ( item ) # # send signal to MainWindow to help distinguish which nodeList # is active for addNode getNode events # print ">> NodeList::emit setActiveNodeList" if usePyQt4 : self.emit ( QtCore.SIGNAL ( "setActiveNodeList" ), self ) else : self.setActiveNodeList.emit ( self ) # # doubleClicked # def doubleClicked ( self, index ) : # print ">> NodeList::doubleClicked " item = self.nodesLib.model.itemFromIndex ( index ) nodeKind = item.whatsThis () if nodeKind != 'folder' : if usePyQt4 : nodeFilename = item.data ( QtCore.Qt.UserRole + 4 ).toString () else : nodeFilename = item.data ( QtCore.Qt.UserRole + 4 ) print ">> NodeList::emit addNode" if usePyQt4 : self.emit ( QtCore.SIGNAL ( 'addNode' ), nodeFilename ) else : self.addNode.emit ( nodeFilename ) # # showDescription # def showDescription ( self, item ) : # print ">> NodeList::showDescription " import os nodeName = item.text () nodeKind = item.whatsThis () if usePyQt4 : nodeAuthor = item.data ( QtCore.Qt.UserRole + 1 ).toString () nodeType = item.data ( QtCore.Qt.UserRole + 2 ).toString () nodeHelp = item.data ( QtCore.Qt.UserRole + 3 ).toString () nodeFilename = item.data ( QtCore.Qt.UserRole + 4 ).toString () nodeIcon = item.data ( QtCore.Qt.UserRole + 5 ).toString () else : nodeAuthor = item.data ( QtCore.Qt.UserRole + 1 ) nodeType = item.data ( QtCore.Qt.UserRole + 2 ) nodeHelp = item.data ( QtCore.Qt.UserRole + 3 ) nodeFilename = item.data ( QtCore.Qt.UserRole + 4 ) nodeIcon = item.data ( QtCore.Qt.UserRole + 5 ) self.ui.infoText.clear () description = '' if nodeKind != 'folder' : if nodeIcon != '' : iconFileName = os.path.join ( os.path.dirname ( str ( nodeFilename ) ), str ( nodeIcon ) ) print str ( iconFileName ) description += '<img src="' + iconFileName + '" />' # width="128" height="128" description += "<table>" #description += "<tr>" #description += "<td align=right>name:</td>" #description += "<td><b>" + nodeName + "</b></td>" #description += "</tr>" #description += "<tr>" #description += "<td align=right>type:</td>" #description += "<td><b>" + nodeType +"</b></td>" #description += "</tr>" #description += "<tr>" #description += "<td align=right>filename:</td>" #description += "<td>" + nodeFilename +"</td>" #description += "</tr>" description += "<tr>" description += "<td align=left>author:</td>" description += "<td><i>" + nodeAuthor +"</i></td>" description += "</tr>" description += "</table><br />" description += "<br />" + nodeHelp +"</b><br />" self.ui.infoText.setText ( description )