Overloads the base QGraphicsItem itemChange method to \
        handle snapping and locking of an object as the user \
        moves it around in the scene.
        
        :param      change      <int>
        :param      value       <variant>
        
        :return     <variant>

def itemChange(self, change, value):
        """
        Overloads the base QGraphicsItem itemChange method to \
        handle snapping and locking of an object as the user \
        moves it around in the scene.
        
        :param      change      <int>
        :param      value       <variant>
        
        :return     <variant>
        """
        value = unwrapVariant(value)
        
        if change == self.ItemSelectedChange:
            eff = self.graphicsEffect()
            eff.setColor(self.highlightColor() if value else QColor(0, 0, 0 ,0))
        
        # only operate when it is a visible, geometric change
        if not (self.isVisible() and change == self.ItemPositionChange):
            return super(XNode, self).itemChange(change, value)
            
        scene = self.scene()
        # only operate when we have a scene
        if not scene:
            return super(XNode, self).itemChange(change, value)
            
        point = unwrapVariant(value)
        
        # update the x position
        if self.isXLocked():
            point.setX( self.pos().x() )
        elif self.isXSnappedToGrid():
            offset_x = self.rect().width() / 2.0
            center_x = point.x() + offset_x
            center_x -= center_x % scene.cellWidth()
            
            point.setX(center_x - offset_x)
            
        # update the y position
        if self.isYLocked():
            point.setY( self.pos().y() )
        elif self.isYSnappedToGrid():
            offset_y = self.rect().height() / 2.0
            center_y = point.y() + offset_y
            center_y -= center_y % scene.cellHeight()
            
            point.setY(center_y - offset_y)
            
        # create the return value
        new_value = wrapVariant(point)
        
        # call the base method to operate on the new point
        result = super(XNode, self).itemChange(change, new_value)
        
        # emit the geometry changed signal
        self.emitGeometryChanged(point)
        
        # return the result
        return result