예제 #1
0
    def dropEvent(self, event):
        """ Execute the pipeline at the particular location """
        mimeData = event.mimeData()        
        if (hasattr(mimeData, 'versionId') and
            hasattr(mimeData, 'controller')):
            event.accept()
            versionId = mimeData.versionId
            controller = mimeData.controller
            pipeline = controller.vistrail.getPipeline(versionId)

            inspector = PipelineInspector()
            inspector.inspect_spreadsheet_cells(pipeline)
            inspector.inspect_ambiguous_modules(pipeline)
            if len(inspector.spreadsheet_cells)==1:
                localPos = self.sheet.viewport().mapFromGlobal(QtGui.QCursor.pos())
                row = self.sheet.rowAt(localPos.y())
                col = self.sheet.columnAt(localPos.x())
                if (row!=-1 and col!=-1):
                    pipeline = self.setPipelineToLocateAt(row, col, pipeline)
            executePipelineWithProgress(pipeline, 'Execute Cell',
                                        controller=controller,
                                        locator=controller.locator,
                                        current_version=versionId,
                                        reason='Drop Version')
        else:
            event.ignore()
예제 #2
0
def decodeConfiguration(pipeline, cells):
    """ decodeConfiguration(pipeline: Pipeline,
        cells: configuration) -> decoded cells
    Convert cells of type [{(type,id): (row, column)}) to
    (mId, row, col) in a particular pipeline

    """
    decodedCells = []
    inspector = PipelineInspector()
    inspector.inspect_spreadsheet_cells(pipeline)
    inspector.inspect_ambiguous_modules(pipeline)
    orig_pipeline = pipeline

    for id_list in inspector.spreadsheet_cells:
        pipeline = orig_pipeline
        id_iter = iter(id_list)
        m = pipeline.modules[id_iter.next()]
        m_id = m.id
        for m_id in id_iter:
            pipeline = m.pipeline
            m = pipeline.modules[m_id]
        name = m.name

        if len(id_list) == 1 and m_id in inspector.annotated_modules:
            idx = inspector.annotated_modules[m_id]
        elif tuple(id_list) in inspector.annotated_modules:
            idx = inspector.annotated_modules[tuple(id_list)]
        else:
            idx = -1
        (vRow, vCol) = cells[(name, idx)]
        if len(id_list) == 1:
            decodedCells.append((m_id, vRow, vCol))
        else:
            decodedCells.append((tuple(id_list), vRow, vCol))
    return decodedCells
예제 #3
0
 def __init__(self, parent=None):
     """ QPipelineView(parent: QWidget) -> QPipelineView
     Initialize the graphics view and its properties
     
     """
     QPipelineView.__init__(self, parent)
     self.setWindowTitle('Annotated Pipeline')
     self.inspector = PipelineInspector()
예제 #4
0
 def __init__(self, parent=None):
     """ QPipelineView(parent: QWidget) -> QPipelineView
     Initialize the graphics view and its properties
     
     """
     QPipelineView.__init__(self, parent)
     self.setWindowTitle('Annotated Pipeline')
     self.inspector = PipelineInspector()
예제 #5
0
    def __init__(self, parent=None):
        """ QVirtualCellWindow(parent: QWidget) -> QVirtualCellWindow
        Initialize the widget

        """
        QtGui.QFrame.__init__(self, parent)
        self.setFrameShape(QtGui.QFrame.StyledPanel)
        self.setWindowTitle('Spreadsheet Virtual Cell')
        vLayout = QtGui.QVBoxLayout(self)
        vLayout.setMargin(2)
        vLayout.setSpacing(0)
        self.setLayout(vLayout)

        label = QtGui.QLabel('Arrange the cell(s) below to construct'
                             ' a virtual cell')
        font = QtGui.QFont(label.font())
        label.setFont(font)
        label.setWordWrap(True)
        vLayout.addWidget(label)

        hLayout = QtGui.QVBoxLayout()
        hLayout.setMargin(0)
        hLayout.setSpacing(0)
        vLayout.addLayout(hLayout)
        self.config = QVirtualCellConfiguration()
        self.config.setSizePolicy(QtGui.QSizePolicy.Maximum,
                                  QtGui.QSizePolicy.Maximum)
        hLayout.addWidget(self.config)
        hPadWidget = QtGui.QWidget()
        hLayout.addWidget(hPadWidget)
        hPadWidget.setSizePolicy(QtGui.QSizePolicy.Expanding,
                                 QtGui.QSizePolicy.Ignored)

        vPadWidget = QtGui.QWidget()
        vLayout.addWidget(vPadWidget)
        vPadWidget.setSizePolicy(QtGui.QSizePolicy.Expanding,
                                 QtGui.QSizePolicy.Expanding)

        self.inspector = PipelineInspector()
        self.pipeline = None
예제 #6
0
def decodeConfiguration(pipeline, cells):
    """ decodeConfiguration(pipeline: Pipeline,
        cells: configuration) -> decoded cells
    Convert cells of type [{(type,id): (row, column)}) to
    (mId, row, col) in a particular pipeline

    """
    decodedCells = []
    inspector = PipelineInspector()
    inspector.inspect_spreadsheet_cells(pipeline)
    inspector.inspect_ambiguous_modules(pipeline)
    orig_pipeline = pipeline

    for id_list in inspector.spreadsheet_cells:
        pipeline = orig_pipeline
        id_iter = iter(id_list)
        m = pipeline.modules[id_iter.next()]
        m_id = m.id
        for m_id in id_iter:
            pipeline = m.pipeline
            m = pipeline.modules[m_id]
        name = m.name

        if len(id_list) == 1 and m_id in inspector.annotated_modules:
            idx = inspector.annotated_modules[m_id]
        elif tuple(id_list) in inspector.annotated_modules:
            idx = inspector.annotated_modules[tuple(id_list)]
        else:
            idx = -1
        (vRow, vCol) = cells[(name, idx)]
        if len(id_list) == 1:
            decodedCells.append((m_id, vRow, vCol))
        else:
            decodedCells.append((tuple(id_list), vRow, vCol))
    return decodedCells
예제 #7
0
    def dropEvent(self, event):
        """ Execute the pipeline at the particular location """
        mimeData = event.mimeData()
        if (hasattr(mimeData, 'versionId')
                and hasattr(mimeData, 'controller')):
            event.accept()
            versionId = mimeData.versionId
            controller = mimeData.controller
            pipeline = controller.vistrail.getPipeline(versionId)

            inspector = PipelineInspector()
            inspector.inspect_spreadsheet_cells(pipeline)
            inspector.inspect_ambiguous_modules(pipeline)
            if len(inspector.spreadsheet_cells) == 1:
                localPos = self.sheet.viewport().mapFromGlobal(
                    QtGui.QCursor.pos())
                row = self.sheet.rowAt(localPos.y())
                col = self.sheet.columnAt(localPos.x())
                if (row != -1 and col != -1):
                    pipeline = self.setPipelineToLocateAt(row, col, pipeline)
            executePipelineWithProgress(pipeline,
                                        'Execute Cell',
                                        controller=controller,
                                        locator=controller.locator,
                                        current_version=versionId,
                                        reason='Drop Version')
        else:
            event.ignore()
예제 #8
0
    def __init__(self, parent=None):
        """ QVirtualCellWindow(parent: QWidget) -> QVirtualCellWindow
        Initialize the widget

        """
        QtGui.QFrame.__init__(self, parent)
        self.setFrameShape(QtGui.QFrame.StyledPanel)
        self.setWindowTitle('Spreadsheet Virtual Cell')
        vLayout = QtGui.QVBoxLayout(self)
        vLayout.setMargin(2)
        vLayout.setSpacing(0)
        self.setLayout(vLayout)
        
        label = QtGui.QLabel('Arrange the cell(s) below to construct'
                             ' a virtual cell')
        font = QtGui.QFont(label.font())
        label.setFont(font)
        label.setWordWrap(True)        
        vLayout.addWidget(label)

        hLayout = QtGui.QVBoxLayout()
        hLayout.setMargin(0)
        hLayout.setSpacing(0)
        vLayout.addLayout(hLayout)
        self.config = QVirtualCellConfiguration()
        self.config.setSizePolicy(QtGui.QSizePolicy.Maximum,
                                  QtGui.QSizePolicy.Maximum)
        hLayout.addWidget(self.config)
        hPadWidget = QtGui.QWidget()
        hLayout.addWidget(hPadWidget)
        hPadWidget.setSizePolicy(QtGui.QSizePolicy.Expanding,
                                 QtGui.QSizePolicy.Ignored)

        vPadWidget = QtGui.QWidget()
        vLayout.addWidget(vPadWidget)
        vPadWidget.setSizePolicy(QtGui.QSizePolicy.Expanding,
                                QtGui.QSizePolicy.Expanding)

        self.inspector = PipelineInspector()
        self.pipeline = None
예제 #9
0
class QVirtualCellWindow(QtGui.QFrame, QToolWindowInterface):
    """
    QVirtualCellWindow contains a caption, a virtual cell
    configuration
    
    """
    def __init__(self, parent=None):
        """ QVirtualCellWindow(parent: QWidget) -> QVirtualCellWindow
        Initialize the widget

        """
        QtGui.QFrame.__init__(self, parent)
        self.setFrameShape(QtGui.QFrame.StyledPanel)
        self.setWindowTitle('Spreadsheet Virtual Cell')
        vLayout = QtGui.QVBoxLayout(self)
        vLayout.setMargin(2)
        vLayout.setSpacing(0)
        self.setLayout(vLayout)
        
        label = QtGui.QLabel('Arrange the cell(s) below to construct'
                             ' a virtual cell')
        font = QtGui.QFont(label.font())
        label.setFont(font)
        label.setWordWrap(True)        
        vLayout.addWidget(label)

        hLayout = QtGui.QVBoxLayout()
        hLayout.setMargin(0)
        hLayout.setSpacing(0)
        vLayout.addLayout(hLayout)
        self.config = QVirtualCellConfiguration()
        self.config.setSizePolicy(QtGui.QSizePolicy.Maximum,
                                  QtGui.QSizePolicy.Maximum)
        hLayout.addWidget(self.config)
        hPadWidget = QtGui.QWidget()
        hLayout.addWidget(hPadWidget)
        hPadWidget.setSizePolicy(QtGui.QSizePolicy.Expanding,
                                 QtGui.QSizePolicy.Ignored)

        vPadWidget = QtGui.QWidget()
        vLayout.addWidget(vPadWidget)
        vPadWidget.setSizePolicy(QtGui.QSizePolicy.Expanding,
                                QtGui.QSizePolicy.Expanding)

        self.inspector = PipelineInspector()
        self.pipeline = None

    def updateVirtualCell(self, pipeline):        
        """ updateVirtualCell(pipeline: QPipeline) -> None
        Setup the virtual cells given a pipeline
        
        """
        self.pipeline = pipeline
        if self.pipeline and self.pipeline.is_valid:
            self.inspector.inspect_spreadsheet_cells(self.pipeline)
            self.inspector.inspect_ambiguous_modules(self.pipeline)
            cells = []
            for id_list in self.inspector.spreadsheet_cells:
                pipeline = self.pipeline
                id_iter = iter(id_list)
                m = pipeline.modules[id_iter.next()]
                m_id = m.id
                for m_id in id_iter:
                    pipeline = m.pipeline
                    m = pipeline.modules[m_id]
                    
                name = m.name
                if len(id_list) == 1 and \
                        m_id in self.inspector.annotated_modules:
                    cells.append((name, self.inspector.annotated_modules[m_id]))
                elif tuple(id_list) in self.inspector.annotated_modules:
                    cells.append((name, self.inspector.annotated_modules[ \
                                tuple(id_list)]))
                else:
                    cells.append((name, -1))
            self.config.configVirtualCells(cells)
        else:

            self.config.clear()

    def getConfiguration(self):
        """ getConfiguration() -> info (see below)
        Return the current configuration of the virtual cell. The
        information is:
        info = (rowCount, columnCount,
                {(type,id): (row, column)})
        """
        return self.config.getConfiguration()
                
    def setConfiguration(self, info):
        """ setConfiguration(info) -> None (see below)
        Set the configuration of the virtual cell. The
        information is:
        info = {(type, id): (row, column)}
          or
        info = (rowCount, columnCount,
                {(type, id): (row, column)})
        The second form is allowed so that the output of
        getConfiguration could be passed directly to
        setConfiguration (the dimensions aren't used).
        """
        self.config.setConfiguration(info)
예제 #10
0
def assignPipelineCellLocations(pipeline, sheetName,
                                row, col, cellIds=None,
                                minRowCount=None, minColCount=None):

    reg = get_module_registry()
    spreadsheet_cell_desc = reg.get_descriptor_by_name(spreadsheet_pkg,
                                                       'SpreadsheetCell')
    output_module_desc = reg.get_descriptor_by_name(
            'org.vistrails.vistrails.basic', 'OutputModule')

    create_module = VistrailController.create_module_static
    create_function = VistrailController.create_function_static
    create_connection = VistrailController.create_connection_static

    pipeline = copy.copy(pipeline)
    root_pipeline = pipeline
    if cellIds is None:
        inspector = PipelineInspector()
        inspector.inspect_spreadsheet_cells(pipeline)
        inspector.inspect_ambiguous_modules(pipeline)
        cellIds = inspector.spreadsheet_cells

    def fix_cell_module(pipeline, mId):
        # Delete connections to 'Location' input port
        conns_to_delete = []
        for c in pipeline.connection_list:
            if c.destinationId == mId and c.destination.name == 'Location':
                conns_to_delete.append(c.id)
        for c_id in conns_to_delete:
            pipeline.delete_connection(c_id)

        # a hack to first get the id_scope to the local pipeline scope
        # then make them negative by hacking the getNewId method
        # all of this is reset at the end of this block
        id_scope = pipeline.tmp_id
        orig_getNewId = pipeline.tmp_id.__class__.getNewId
        def getNewId(self, objType):
            return -orig_getNewId(self, objType)
        pipeline.tmp_id.__class__.getNewId = getNewId

        # Add a sheet reference with a specific name
        sheetReference = create_module(id_scope, spreadsheet_pkg,
                                       "SheetReference")
        sheetNameFunction = create_function(id_scope, sheetReference,
                                            "SheetName", [str(sheetName)])
            # ["%s %d" % (sheetPrefix, sheet)])

        sheetReference.add_function(sheetNameFunction)

        if minRowCount is not None:
            minRowFunction = create_function(id_scope, sheetReference,
                                             "MinRowCount", [str(minRowCount)])
                                                   # [str(rowCount*vRCount)])
            sheetReference.add_function(minRowFunction)
        if minColCount is not None:
            minColFunction = create_function(id_scope, sheetReference,
                                             "MinColumnCount",
                                             [str(minColCount)])
                                                   # [str(colCount*vCCount)])
            sheetReference.add_function(minColFunction)

        # Add a cell location module with a specific row and column
        cellLocation = create_module(id_scope, spreadsheet_pkg,
                                     "CellLocation")
        rowFunction = create_function(id_scope, cellLocation, "Row", [str(row)])
                                                 # [str(row*vRCount+vRow+1)])
        colFunction = create_function(id_scope, cellLocation, "Column",
                                      [str(col)])
                                                 # [str(col*vCCount+vCol+1)])

        cellLocation.add_function(rowFunction)
        cellLocation.add_function(colFunction)

        # Then connect the SheetReference to the CellLocation
        sheet_conn = create_connection(id_scope, sheetReference, "value",
                                       cellLocation, "SheetReference")

        # Then connect the CellLocation to the spreadsheet cell
        cell_module = pipeline.get_module_by_id(mId)
        cell_conn = create_connection(id_scope, cellLocation, "value",
                                      cell_module, "Location")

        pipeline.add_module(sheetReference)
        pipeline.add_module(cellLocation)
        pipeline.add_connection(sheet_conn)
        pipeline.add_connection(cell_conn)

        # replace the getNewId method
        pipeline.tmp_id.__class__.getNewId = orig_getNewId

    def fix_output_module(pipeline, mId):
        # Remove all connections to 'configuration' input port
        conns_to_delete = []
        for c in pipeline.connection_list:
            if (c.destinationId == mId and
                    c.destination.name == 'configuration'):
                conns_to_delete.append(c.id)
        for c_id in conns_to_delete:
            pipeline.delete_connection(c_id)

        m = pipeline.modules[mId]

        # Remove all functions on 'configuration' input port
        funcs_to_delete = []
        for f in m.functions:
            if f.name == 'configuration':
                funcs_to_delete.append(f.real_id)
        for f_id in funcs_to_delete:
            m.delete_function_by_real_id(f_id)

        # a hack to first get the id_scope to the local pipeline scope
        # then make them negative by hacking the getNewId method
        # all of this is reset at the end of this block
        id_scope = pipeline.tmp_id
        orig_getNewId = pipeline.tmp_id.__class__.getNewId
        def getNewId(self, objType):
            return -orig_getNewId(self, objType)
        pipeline.tmp_id.__class__.getNewId = getNewId

        config = {'row': row - 1, 'col': col - 1}
        if minRowCount is not None:
            config['sheetRowCount'] = minRowCount
        if minColCount is not None:
            config['sheetColCount'] = minColCount
        if sheetName is not None:
            config['sheetName']= sheetName
        config = {'spreadsheet': config}
        config_function = create_function(id_scope, m,
                                          'configuration', [repr(config)])
        m.add_function(config_function)

        # replace the getNewId method
        pipeline.tmp_id.__class__.getNewId = orig_getNewId

    for id_list in cellIds:
        cell_pipeline = pipeline

        # find at which depth we need to be working
        if isinstance(id_list, (int, long)):
            mId = id_list
            m = cell_pipeline.modules[mId]
        else:
            id_iter = iter(id_list)
            mId = next(id_iter)
            m = cell_pipeline.modules[mId]
            for mId in id_iter:
                cell_pipeline = m.pipeline
                m = cell_pipeline.modules[mId]

        if reg.is_descriptor_subclass(m.module_descriptor,
                                      spreadsheet_cell_desc):
            fix_cell_module(cell_pipeline, mId)
        elif reg.is_descriptor_subclass(m.module_descriptor,
                                        output_module_desc):
            fix_output_module(cell_pipeline, mId)

    return root_pipeline
예제 #11
0
class QVirtualCellWindow(QtGui.QFrame, QToolWindowInterface):
    """
    QVirtualCellWindow contains a caption, a virtual cell
    configuration
    
    """
    def __init__(self, parent=None):
        """ QVirtualCellWindow(parent: QWidget) -> QVirtualCellWindow
        Initialize the widget

        """
        QtGui.QFrame.__init__(self, parent)
        self.setFrameShape(QtGui.QFrame.StyledPanel)
        self.setWindowTitle('Spreadsheet Virtual Cell')
        vLayout = QtGui.QVBoxLayout(self)
        vLayout.setMargin(2)
        vLayout.setSpacing(0)
        self.setLayout(vLayout)

        label = QtGui.QLabel('Arrange the cell(s) below to construct'
                             ' a virtual cell')
        font = QtGui.QFont(label.font())
        label.setFont(font)
        label.setWordWrap(True)
        vLayout.addWidget(label)

        hLayout = QtGui.QVBoxLayout()
        hLayout.setMargin(0)
        hLayout.setSpacing(0)
        vLayout.addLayout(hLayout)
        self.config = QVirtualCellConfiguration()
        self.config.setSizePolicy(QtGui.QSizePolicy.Maximum,
                                  QtGui.QSizePolicy.Maximum)
        hLayout.addWidget(self.config)
        hPadWidget = QtGui.QWidget()
        hLayout.addWidget(hPadWidget)
        hPadWidget.setSizePolicy(QtGui.QSizePolicy.Expanding,
                                 QtGui.QSizePolicy.Ignored)

        vPadWidget = QtGui.QWidget()
        vLayout.addWidget(vPadWidget)
        vPadWidget.setSizePolicy(QtGui.QSizePolicy.Expanding,
                                 QtGui.QSizePolicy.Expanding)

        self.inspector = PipelineInspector()
        self.pipeline = None

    def updateVirtualCell(self, pipeline):
        """ updateVirtualCell(pipeline: QPipeline) -> None
        Setup the virtual cells given a pipeline
        
        """
        self.pipeline = pipeline
        if self.pipeline and self.pipeline.is_valid:
            self.inspector.inspect_spreadsheet_cells(self.pipeline)
            self.inspector.inspect_ambiguous_modules(self.pipeline)
            cells = []
            for id_list in self.inspector.spreadsheet_cells:
                pipeline = self.pipeline
                id_iter = iter(id_list)
                m = pipeline.modules[id_iter.next()]
                m_id = m.id
                for m_id in id_iter:
                    pipeline = m.pipeline
                    m = pipeline.modules[m_id]

                name = m.name
                if len(id_list) == 1 and \
                        m_id in self.inspector.annotated_modules:
                    cells.append(
                        (name, self.inspector.annotated_modules[m_id]))
                elif tuple(id_list) in self.inspector.annotated_modules:
                    cells.append((name, self.inspector.annotated_modules[ \
                                tuple(id_list)]))
                else:
                    cells.append((name, -1))
            self.config.configVirtualCells(cells)
        else:

            self.config.clear()

    def getConfiguration(self):
        """ getConfiguration() -> info (see below)
        Return the current configuration of the virtual cell. The
        information is:
        info = (rowCount, columnCount,
                {(type,id): (row, column)})
        """
        return self.config.getConfiguration()

    def setConfiguration(self, info):
        """ setConfiguration(info) -> None (see below)
        Set the configuration of the virtual cell. The
        information is:
        info = {(type, id): (row, column)}
          or
        info = (rowCount, columnCount,
                {(type, id): (row, column)})
        The second form is allowed so that the output of
        getConfiguration could be passed directly to
        setConfiguration (the dimensions aren't used).
        """
        self.config.setConfiguration(info)
예제 #12
0
class QAnnotatedPipelineView(QPipelineView, QToolWindowInterface):
    """
    QAnnotatedPipelineView subclass QPipelineView to perform some overlay
    marking on a pipeline view
    
    """
    def __init__(self, parent=None):
        """ QPipelineView(parent: QWidget) -> QPipelineView
        Initialize the graphics view and its properties
        
        """
        QPipelineView.__init__(self, parent)
        self.setWindowTitle('Annotated Pipeline')
        self.inspector = PipelineInspector()

    def sizeHint(self):
        """ sizeHint() -> QSize
        Prefer the view not so large
        
        """
        return QtCore.QSize(256, 256)

    def paintEvent(self, event):
        """ paintEvent(event: QPaintEvent) -> None
        Paint an overlay annotation on spreadsheet cell modules
        
        """
        QPipelineView.paintEvent(self, event)
        # super(QAnnotatedPipelineView, self).paintEvent(event)
        if self.scene():
            painter = QtGui.QPainter(self.viewport())
            for mId, annotatedId in \
                    self.inspector.annotated_modules.iteritems():
                if mId not in self.scene().modules:
                    # faulty annotated_modules entry
                    continue
                item = self.scene().modules[mId]
                br = item.sceneBoundingRect()
                rect = QtCore.QRect(self.mapFromScene(br.topLeft()),
                                    self.mapFromScene(br.bottomRight()))
                QAnnotatedPipelineView.drawId(painter, rect, annotatedId)
            painter.end()

    def updateAnnotatedIds(self, pipeline):
        """ updateAnnotatedIds(pipeline: Pipeline) -> None
        Re-inspect the pipeline to get annotated ids
        
        """
        if pipeline and self.scene():
            self.inspector.inspect_ambiguous_modules(pipeline)
            self.scene().fitToView(self)

    @staticmethod
    def drawId(painter, rect, id, align=QtCore.Qt.AlignCenter):
        """ drawId(painter: QPainter, rect: QRect, id: int,
                   align: QtCore.Qt.Align) -> None
        Draw the rounded id number on a rectangular area
        
        """
        painter.save()
        painter.setRenderHints(QtGui.QPainter.Antialiasing)
        painter.setPen(CurrentTheme.ANNOTATED_ID_BRUSH.color())
        painter.setBrush(CurrentTheme.ANNOTATED_ID_BRUSH)
        font = QtGui.QFont()
        font.setStyleStrategy(QtGui.QFont.ForceOutline)
        font.setBold(True)
        painter.setFont(font)
        fm = QtGui.QFontMetrics(font)
        size = fm.size(QtCore.Qt.TextSingleLine, str(id))
        size = max(size.width(), size.height())
        
        x = rect.left()
        if align & QtCore.Qt.AlignHCenter:
            x = rect.left() + rect.width()/2-size/2
        if align & QtCore.Qt.AlignRight:
            x = rect.left() + rect.width()-size
        y = rect.top()
        if align & QtCore.Qt.AlignVCenter:
            y = rect.top() + rect.height()/2-size/2
        if align & QtCore.Qt.AlignBottom:
            y = rect.top() + rect.height()-size
            
        newRect = QtCore.QRect(x, y, size, size)
        painter.drawEllipse(newRect)
        painter.setPen(CurrentTheme.ANNOTATED_ID_PEN)
        painter.drawText(newRect, QtCore.Qt.AlignCenter, str(id))
        painter.restore()
예제 #13
0
    def updateFromPipeline(self, pipeline, controller):
        """ updateFromPipeline(pipeline: Pipeline) -> None
        Read the list of aliases and parameters from the pipeline
        
        """
        self.clear()
        if not pipeline:
            return

        # Update the aliases
        if len(pipeline.aliases)>0:
            aliasRoot = QParameterTreeWidgetItem(None, self, ['Aliases'])
            aliasRoot.setFlags(QtCore.Qt.ItemIsEnabled)
            for (alias, info) in pipeline.aliases.iteritems():
                ptype, pId, parentType, parentId, mId = info
                parameter = pipeline.db_get_object(ptype, pId)
                function = pipeline.db_get_object(parentType, parentId)
                v = parameter.strValue
                port_spec = function.get_spec('input')
                port_spec_item = port_spec.port_spec_items[parameter.pos]
                label = ['%s = %s' % (alias, v)]
                pInfo = ParameterInfo(module_id=mId,
                                      name=function.name,
                                      pos=parameter.pos,
                                      value=v,
                                      spec=port_spec_item,
                                      is_alias=True)
                aliasItem = QParameterTreeWidgetItem((alias, [pInfo]),
                                                     aliasRoot, label)
            aliasRoot.setExpanded(True)

        vistrailVarsRoot = QParameterTreeWidgetItem(None, self,
                                      ['Vistrail Variables'])
        vistrailVarsRoot.setHidden(True)

        # Now go through all modules and functions

        inspector = PipelineInspector()
        inspector.inspect_ambiguous_modules(pipeline)
        sortedModules = sorted(pipeline.modules.iteritems(),
                               key=lambda item: item[1].name)

        reg = get_module_registry()

        for mId, module in sortedModules:
            if module.is_vistrail_var():
                vistrailVarsRoot.setHidden(False)
                vistrailVarsRoot.setExpanded(True)
                port_spec = module.get_port_spec('value', 'input')
                if not port_spec:
                    debug.critical("Not port_spec for value in module %s" % module)
                    continue
                port_spec_items = port_spec.port_spec_items

                if not controller.has_vistrail_variable_with_uuid(
                                        module.get_vistrail_var()):
                    continue
                vv = controller.get_vistrail_variable_by_uuid(
                                        module.get_vistrail_var())


                label = ['%s = %s' % (vv.name, vv.value)]
                pList = [ParameterInfo(module_id=mId,
                                       name=port_spec.name,
                                       pos=port_spec.port_spec_items[pId].pos,
                                       value="",
                                       spec=port_spec.port_spec_items[pId],
                                       is_alias=False)
                         for pId in xrange(len(port_spec.port_spec_items))]
                mItem = QParameterTreeWidgetItem((vv.name, pList),
                                                 vistrailVarsRoot,
                                                 label)
                continue
                
            function_names = {}
            # Add existing parameters
            mLabel = [module.name]
            moduleItem = None
            if len(module.functions)>0:
                for fId in xrange(len(module.functions)):
                    function = module.functions[fId]
                    function_names[function.name] = function
                    if len(function.params)==0: continue
                    if moduleItem==None:
                        if inspector.annotated_modules.has_key(mId):
                            annotatedId = inspector.annotated_modules[mId]
                            moduleItem = QParameterTreeWidgetItem(annotatedId,
                                                                  self, mLabel)
                        else:
                            moduleItem = QParameterTreeWidgetItem(None,
                                                                  self, mLabel)
                    v = ', '.join([p.strValue for p in function.params])
                    label = ['%s(%s)' % (function.name, v)]
                    
                    try:
                        port_spec = function.get_spec('input')
                    except Exception, e:
                        debug.critical("get_spec failed: %s %s %s" % \
                                       (module, function, function.sigstring))
                        continue
                    port_spec_items = port_spec.port_spec_items
                    pList = [ParameterInfo(module_id=mId,
                                           name=function.name,
                                           pos=function.params[pId].pos,
                                           value=function.params[pId].strValue,
                                           spec=port_spec_items[pId],
                                           is_alias=False)
                             for pId in xrange(len(function.params))]
                    mName = module.name
                    if moduleItem.parameter!=None:
                        mName += '(%d)' % moduleItem.parameter
                    fName = '%s :: %s' % (mName, function.name)
                    mItem = QParameterTreeWidgetItem((fName, pList),
                                                     moduleItem,
                                                     label)
            # Add available parameters
            if module.is_valid:
                for port_spec in module.destinationPorts():
                    if (port_spec.name in function_names or
                        not port_spec.is_valid or 
                        not len(port_spec.port_spec_items) or
                        not reg.is_constant(port_spec)):
                        # The function already exists or is empty
                        # or contains non-constant modules
                        continue
                    if moduleItem==None:
                        if inspector.annotated_modules.has_key(mId):
                            annotatedId = inspector.annotated_modules[mId]
                            moduleItem = QParameterTreeWidgetItem(annotatedId,
                                                                  self, 
                                                                  mLabel, 
                                                                  False)
                        else:
                            moduleItem = QParameterTreeWidgetItem(None, self,
                                                                  mLabel, False)
                    v = ', '.join([p.module for p in port_spec.port_spec_items])
                    label = ['%s(%s)' % (port_spec.name, v)]
                    pList = [ParameterInfo(module_id=mId,
                                           name=port_spec.name,
                                           pos=port_spec.port_spec_items[pId].pos,
                                           value="",
                                           spec=port_spec.port_spec_items[pId],
                                           is_alias=False)
                             for pId in xrange(len(port_spec.port_spec_items))]
                    mName = module.name
                    if moduleItem.parameter!=None:
                        mName += '(%d)' % moduleItem.parameter
                    fName = '%s :: %s' % (mName, port_spec.name)
                    mItem = QParameterTreeWidgetItem((fName, pList),
                                                     moduleItem,
                                                     label, False)
            if moduleItem:
                moduleItem.setExpanded(True)
예제 #14
0
def assignPipelineCellLocations(pipeline, sheetName, 
                                row, col, cellIds=None,
                                minRowCount=None, minColCount=None):

    reg = get_module_registry()
    spreadsheet_cell_desc = \
        reg.get_descriptor_by_name(spreadsheet_pkg, 'SpreadsheetCell')

    create_module = VistrailController.create_module_static
    create_function = VistrailController.create_function_static
    create_connection = VistrailController.create_connection_static

    pipeline = copy.copy(pipeline)
    root_pipeline = pipeline
    if cellIds is None:
        inspector = PipelineInspector()
        inspector.inspect_spreadsheet_cells(pipeline)
        inspector.inspect_ambiguous_modules(pipeline)
        cellIds = inspector.spreadsheet_cells

    for id_list in cellIds:
        # find at which depth we need to be working
        try:                
            id_iter = iter(id_list)
            m = pipeline.modules[id_iter.next()]
            for mId in id_iter:
                pipeline = m.pipeline
                m = pipeline.modules[mId]
        except TypeError:
            mId = id_list

        m = pipeline.modules[mId]
        if not reg.is_descriptor_subclass(m.module_descriptor, 
                                          spreadsheet_cell_desc):
            continue

        # Walk through all connections and remove all CellLocation
        # modules connected to this spreadsheet cell
        conns_to_delete = []
        for (cId,c) in pipeline.connections.iteritems():
            if (c.destinationId==mId and 
                pipeline.modules[c.sourceId].name=="CellLocation"):
                conns_to_delete.append(c.id)
        for c_id in conns_to_delete:
            pipeline.delete_connection(c_id)

        # a hack to first get the id_scope to the local pipeline scope
        # then make them negative by hacking the getNewId method
        # all of this is reset at the end of this block
        id_scope = pipeline.tmp_id
        orig_getNewId = pipeline.tmp_id.__class__.getNewId
        def getNewId(self, objType):
            return -orig_getNewId(self, objType)
        pipeline.tmp_id.__class__.getNewId = getNewId

        # Add a sheet reference with a specific name
        sheetReference = create_module(id_scope, spreadsheet_pkg,
                                       "SheetReference")
        sheetNameFunction = create_function(id_scope, sheetReference, 
                                            "SheetName", [str(sheetName)])
            # ["%s %d" % (sheetPrefix, sheet)])

        sheetReference.add_function(sheetNameFunction)

        if minRowCount is not None:
            minRowFunction = create_function(id_scope, sheetReference, 
                                             "MinRowCount", [str(minRowCount)])
                                                   # [str(rowCount*vRCount)])
            sheetReference.add_function(minRowFunction)
        if minColCount is not None:
            minColFunction = create_function(id_scope, sheetReference, 
                                             "MinColumnCount", 
                                             [str(minColCount)])
                                                   # [str(colCount*vCCount)])
            sheetReference.add_function(minColFunction)

        # Add a cell location module with a specific row and column
        cellLocation = create_module(id_scope, spreadsheet_pkg,
                                     "CellLocation")
        rowFunction = create_function(id_scope, cellLocation, "Row", [str(row)])
                                                 # [str(row*vRCount+vRow+1)])
        colFunction = create_function(id_scope, cellLocation, "Column", 
                                      [str(col)])
                                                 # [str(col*vCCount+vCol+1)])

        cellLocation.add_function(rowFunction)
        cellLocation.add_function(colFunction)

        # Then connect the SheetReference to the CellLocation
        sheet_conn = create_connection(id_scope, sheetReference, "self",
                                       cellLocation, "SheetReference")

        # Then connect the CellLocation to the spreadsheet cell
        cell_module = pipeline.get_module_by_id(mId)
        cell_conn = create_connection(id_scope, cellLocation, "self",
                                      cell_module, "Location")

        pipeline.add_module(sheetReference)
        pipeline.add_module(cellLocation)
        pipeline.add_connection(sheet_conn)
        pipeline.add_connection(cell_conn)
        # replace the getNewId method
        pipeline.tmp_id.__class__.getNewId = orig_getNewId

    return root_pipeline
예제 #15
0
    def updateFromPipeline(self, pipeline):
        """ updateFromPipeline(pipeline: Pipeline) -> None
        Read the list of aliases and parameters from the pipeline
        
        """
        self.clear()
        if not pipeline:
            return

        # Update the aliases
        #        if len(pipeline.aliases)>0:
        #            aliasRoot = QParameterTreeWidgetItem(None, self, ['Aliases'])
        #            aliasRoot.setFlags(QtCore.Qt.ItemIsEnabled,
        #                               )
        #            for (alias, info) in pipeline.aliases.iteritems():
        #                ptype, pId, parentType, parentId, _ = info
        #                parameter = pipeline.db_get_object(ptype, pId)
        #                v = parameter.strValue
        #                aType = parameter.type
        #                aIdentifier = parameter.identifier
        #                aNamespace = parameter.namespace
        #                label = ['%s = %s' % (alias, v)]
        #                pInfo = InstanceObject(type=aType,
        #                                      identifier=aIdentifier,
        #                                      namespace=aNamespace,
        #                                      value=v,
        #                                      id=pId,
        #                                      dbtype=ptype,
        #                                      parent_dbtype=parentType,
        #                                      parent_id=parentId,
        #                                      is_alias=True)
        #                aliasItem = QParameterTreeWidgetItem((alias, [pInfo]),
        #                                                     aliasRoot, label)
        #            aliasRoot.setExpanded(True)

        # Now go through all modules and functions
        self.aliasNames = pipeline.aliases.keys()
        inspector = PipelineInspector()
        inspector.inspect_ambiguous_modules(pipeline)
        sortedModules = sorted(pipeline.modules.iteritems(), key=lambda item: item[1].name)
        for mId, module in sortedModules:
            if len(module.functions) > 0:
                mLabel = [module.name]
                moduleItem = None
                port_dict = dict((p.name, p) for p in module.destinationPorts())
                for fId in xrange(len(module.functions)):
                    function = module.functions[fId]
                    if len(function.params) == 0:
                        continue
                    if moduleItem == None:
                        if inspector.annotated_modules.has_key(mId):
                            annotatedId = inspector.annotated_modules[mId]
                            moduleItem = QAliasParameterTreeWidgetItem(annotatedId, self, mLabel)
                        else:
                            moduleItem = QAliasParameterTreeWidgetItem(None, self, mLabel)
                    # v = ', '.join([p.strValue for p in function.params])
                    port_spec = port_dict[function.name]
                    label = ["%s" % (port_spec.union or function.name)]

                    pList = [
                        InstanceObject(
                            type=function.params[pId].type,
                            identifier=function.params[pId].identifier,
                            namespace=function.params[pId].namespace,
                            value=function.params[pId].strValue,
                            id=function.params[pId].real_id,
                            dbtype=ModuleParam.vtType,
                            parent_dbtype=function.vtType,
                            parent_id=function.real_id,
                            alias=function.params[pId].alias,
                            mId=mId,
                        )
                        for pId in xrange(len(function.params))
                    ]
                    mName = module.name
                    if moduleItem.parameter != None:
                        mName += "(%d)" % moduleItem.parameter
                    fName = "%s :: %s" % (mName, function.name)
                    mItem = QAliasParameterTreeWidgetItem((fName, pList), moduleItem, label)
                if moduleItem:
                    moduleItem.setExpanded(True)
예제 #16
0
    def updateFromPipeline(self, pipeline, controller):
        """ updateFromPipeline(pipeline: Pipeline) -> None
        Read the list of aliases and parameters from the pipeline
        
        """
        self.clear()
        if not pipeline:
            return

        # Update the aliases
        if len(pipeline.aliases) > 0:
            aliasRoot = QParameterTreeWidgetItem(None, self, ['Aliases'])
            aliasRoot.setFlags(QtCore.Qt.ItemIsEnabled)
            for (alias, info) in pipeline.aliases.iteritems():
                ptype, pId, parentType, parentId, mId = info
                parameter = pipeline.db_get_object(ptype, pId)
                function = pipeline.db_get_object(parentType, parentId)
                v = parameter.strValue
                port_spec = function.get_spec('input')
                port_spec_item = port_spec.port_spec_items[parameter.pos]
                label = ['%s = %s' % (alias, v)]
                pInfo = ParameterInfo(module_id=mId,
                                      name=function.name,
                                      pos=parameter.pos,
                                      value=v,
                                      spec=port_spec_item,
                                      is_alias=True)
                QParameterTreeWidgetItem((alias, [pInfo]), aliasRoot, label)
            aliasRoot.setExpanded(True)

        vistrailVarsRoot = QParameterTreeWidgetItem(None, self,
                                                    ['Vistrail Variables'])
        vistrailVarsRoot.setHidden(True)

        # Now go through all modules and functions

        inspector = PipelineInspector()
        inspector.inspect_ambiguous_modules(pipeline)
        sortedModules = sorted(pipeline.modules.iteritems(),
                               key=lambda item: item[1].name)

        reg = get_module_registry()

        for mId, module in sortedModules:
            if module.is_vistrail_var():
                vistrailVarsRoot.setHidden(False)
                vistrailVarsRoot.setExpanded(True)
                port_spec = module.get_port_spec('value', 'input')
                if not port_spec:
                    debug.critical("Not port_spec for value in module %s" %
                                   module)
                    continue

                if not controller.has_vistrail_variable_with_uuid(
                        module.get_vistrail_var()):
                    continue
                vv = controller.get_vistrail_variable_by_uuid(
                    module.get_vistrail_var())

                label = ['%s = %s' % (vv.name, vv.value)]
                pList = [
                    ParameterInfo(module_id=mId,
                                  name=port_spec.name,
                                  pos=port_spec.port_spec_items[pId].pos,
                                  value="",
                                  spec=port_spec.port_spec_items[pId],
                                  is_alias=False)
                    for pId in xrange(len(port_spec.port_spec_items))
                ]
                QParameterTreeWidgetItem((vv.name, pList), vistrailVarsRoot,
                                         label)
                continue

            function_names = {}
            # Add existing parameters
            mLabel = [module.name]
            moduleItem = None
            if len(module.functions) > 0:
                for fId in xrange(len(module.functions)):
                    function = module.functions[fId]
                    function_names[function.name] = function
                    if len(function.params) == 0: continue
                    if moduleItem == None:
                        if inspector.annotated_modules.has_key(mId):
                            annotatedId = inspector.annotated_modules[mId]
                            moduleItem = QParameterTreeWidgetItem(
                                annotatedId, self, mLabel)
                        else:
                            moduleItem = QParameterTreeWidgetItem(
                                None, self, mLabel)
                    v = ', '.join([p.strValue for p in function.params])
                    label = ['%s(%s)' % (function.name, v)]

                    try:
                        port_spec = function.get_spec('input')
                    except Exception:
                        debug.critical("get_spec failed: %s %s %s" % \
                                       (module, function, function.sigstring))
                        continue
                    port_spec_items = port_spec.port_spec_items
                    pList = [
                        ParameterInfo(module_id=mId,
                                      name=function.name,
                                      pos=function.params[pId].pos,
                                      value=function.params[pId].strValue,
                                      spec=port_spec_items[pId],
                                      is_alias=False)
                        for pId in xrange(len(function.params))
                    ]
                    mName = module.name
                    if moduleItem.parameter is not None:
                        mName += '(%d)' % moduleItem.parameter
                    fName = '%s :: %s' % (mName, function.name)
                    QParameterTreeWidgetItem((fName, pList), moduleItem, label)
            # Add available parameters
            if module.is_valid:
                for port_spec in module.destinationPorts():
                    if (port_spec.name in function_names
                            or not port_spec.is_valid
                            or not len(port_spec.port_spec_items)
                            or not reg.is_constant(port_spec)):
                        # The function already exists or is empty
                        # or contains non-constant modules
                        continue
                    if moduleItem == None:
                        if inspector.annotated_modules.has_key(mId):
                            annotatedId = inspector.annotated_modules[mId]
                            moduleItem = QParameterTreeWidgetItem(
                                annotatedId, self, mLabel, False)
                        else:
                            moduleItem = QParameterTreeWidgetItem(
                                None, self, mLabel, False)
                    v = ', '.join(
                        [p.module for p in port_spec.port_spec_items])
                    label = ['%s(%s)' % (port_spec.name, v)]
                    pList = [
                        ParameterInfo(module_id=mId,
                                      name=port_spec.name,
                                      pos=port_spec.port_spec_items[pId].pos,
                                      value="",
                                      spec=port_spec.port_spec_items[pId],
                                      is_alias=False)
                        for pId in xrange(len(port_spec.port_spec_items))
                    ]
                    mName = module.name
                    if moduleItem.parameter is not None:
                        mName += '(%d)' % moduleItem.parameter
                    fName = '%s :: %s' % (mName, port_spec.name)
                    QParameterTreeWidgetItem((fName, pList), moduleItem, label,
                                             False)
            if moduleItem:
                moduleItem.setExpanded(True)
        self.toggleUnsetParameters(self.showUnsetParameters)
    def updateFromPipeline(self, pipeline):
        """ updateFromPipeline(pipeline: Pipeline) -> None
        Read the list of aliases and parameters from the pipeline
        
        """
        self.clear()
        if not pipeline:
            return

        # Update the aliases


#        if len(pipeline.aliases)>0:
#            aliasRoot = QParameterTreeWidgetItem(None, self, ['Aliases'])
#            aliasRoot.setFlags(QtCore.Qt.ItemIsEnabled,
#                               )
#            for (alias, info) in pipeline.aliases.iteritems():
#                ptype, pId, parentType, parentId, _ = info
#                parameter = pipeline.db_get_object(ptype, pId)
#                v = parameter.strValue
#                aType = parameter.type
#                aIdentifier = parameter.identifier
#                aNamespace = parameter.namespace
#                label = ['%s = %s' % (alias, v)]
#                pInfo = InstanceObject(type=aType,
#                                      identifier=aIdentifier,
#                                      namespace=aNamespace,
#                                      value=v,
#                                      id=pId,
#                                      dbtype=ptype,
#                                      parent_dbtype=parentType,
#                                      parent_id=parentId,
#                                      is_alias=True)
#                aliasItem = QParameterTreeWidgetItem((alias, [pInfo]),
#                                                     aliasRoot, label)
#            aliasRoot.setExpanded(True)

# Now go through all modules and functions
        self.aliasNames = pipeline.aliases.keys()
        inspector = PipelineInspector()
        inspector.inspect_ambiguous_modules(pipeline)
        sortedModules = sorted(pipeline.modules.iteritems(),
                               key=lambda item: item[1].name)
        for mId, module in sortedModules:
            if len(module.functions) > 0:
                mLabel = [module.name]
                moduleItem = None
                port_dict = dict(
                    (p.name, p) for p in module.destinationPorts())
                for fId in xrange(len(module.functions)):
                    function = module.functions[fId]
                    if len(function.params) == 0: continue
                    if moduleItem == None:
                        if inspector.annotated_modules.has_key(mId):
                            annotatedId = inspector.annotated_modules[mId]
                            moduleItem = QAliasParameterTreeWidgetItem(
                                annotatedId, self, mLabel)
                        else:
                            moduleItem = QAliasParameterTreeWidgetItem(
                                None, self, mLabel)
                    #v = ', '.join([p.strValue for p in function.params])
                    port_spec = port_dict[function.name]
                    label = ['%s' % (port_spec.union or function.name)]

                    pList = [
                        InstanceObject(
                            type=function.params[pId].type,
                            identifier=function.params[pId].identifier,
                            namespace=function.params[pId].namespace,
                            value=function.params[pId].strValue,
                            id=function.params[pId].real_id,
                            dbtype=ModuleParam.vtType,
                            parent_dbtype=function.vtType,
                            parent_id=function.real_id,
                            alias=function.params[pId].alias,
                            mId=mId) for pId in xrange(len(function.params))
                    ]
                    mName = module.name
                    if moduleItem.parameter != None:
                        mName += '(%d)' % moduleItem.parameter
                    fName = '%s :: %s' % (mName, function.name)
                    mItem = QAliasParameterTreeWidgetItem((fName, pList),
                                                          moduleItem, label)
                if moduleItem:
                    moduleItem.setExpanded(True)
예제 #18
0
class QAnnotatedPipelineView(QPipelineView, QToolWindowInterface):
    """
    QAnnotatedPipelineView subclass QPipelineView to perform some overlay
    marking on a pipeline view
    
    """
    def __init__(self, parent=None):
        """ QPipelineView(parent: QWidget) -> QPipelineView
        Initialize the graphics view and its properties
        
        """
        QPipelineView.__init__(self, parent)
        self.setWindowTitle('Annotated Pipeline')
        self.inspector = PipelineInspector()

    def sizeHint(self):
        """ sizeHint() -> QSize
        Prefer the view not so large
        
        """
        return QtCore.QSize(256, 256)

    def paintEvent(self, event):
        """ paintEvent(event: QPaintEvent) -> None
        Paint an overlay annotation on spreadsheet cell modules
        
        """
        QPipelineView.paintEvent(self, event)
        # super(QAnnotatedPipelineView, self).paintEvent(event)
        if self.scene():
            painter = QtGui.QPainter(self.viewport())
            for mId, annotatedId in \
                    self.inspector.annotated_modules.iteritems():
                if mId not in self.scene().modules:
                    # faulty annotated_modules entry
                    continue
                item = self.scene().modules[mId]
                br = item.sceneBoundingRect()
                rect = QtCore.QRect(self.mapFromScene(br.topLeft()),
                                    self.mapFromScene(br.bottomRight()))
                QAnnotatedPipelineView.drawId(painter, rect, annotatedId)
            painter.end()

    def updateAnnotatedIds(self, pipeline):
        """ updateAnnotatedIds(pipeline: Pipeline) -> None
        Re-inspect the pipeline to get annotated ids
        
        """
        if pipeline and self.scene():
            self.inspector.inspect_ambiguous_modules(pipeline)
            self.scene().fitToAllViews(True)


    @staticmethod
    def drawId(painter, rect, id, align=QtCore.Qt.AlignCenter):
        """ drawId(painter: QPainter, rect: QRect, id: int,
                   align: QtCore.Qt.Align) -> None
        Draw the rounded id number on a rectangular area
        
        """
        painter.save()
        painter.setRenderHints(QtGui.QPainter.Antialiasing)
        painter.setPen(CurrentTheme.ANNOTATED_ID_BRUSH.color())
        painter.setBrush(CurrentTheme.ANNOTATED_ID_BRUSH)
        font = QtGui.QFont()
        font.setStyleStrategy(QtGui.QFont.ForceOutline)
        font.setBold(True)
        painter.setFont(font)
        fm = QtGui.QFontMetrics(font)
        size = fm.size(QtCore.Qt.TextSingleLine, str(id))
        size = max(size.width(), size.height())
        
        x = rect.left()
        if align & QtCore.Qt.AlignHCenter:
            x = rect.left() + rect.width()//2-size//2
        if align & QtCore.Qt.AlignRight:
            x = rect.left() + rect.width()-size
        y = rect.top()
        if align & QtCore.Qt.AlignVCenter:
            y = rect.top() + rect.height()//2-size//2
        if align & QtCore.Qt.AlignBottom:
            y = rect.top() + rect.height()-size
            
        newRect = QtCore.QRect(x, y, size, size)
        painter.drawEllipse(newRect)
        painter.setPen(CurrentTheme.ANNOTATED_ID_PEN)
        painter.drawText(newRect, QtCore.Qt.AlignCenter, str(id))
        painter.restore()