Ejemplo n.º 1
0
def iLabel(node, *args, **kargs):

    #code for making specialized faces for intermediates mostly cribbed from the ete2 website example (though not interactive):
    # http://pythonhosted.org/ete2/tutorial/tutorial_drawing.html#creating-your-custom-interactive-item-faces

    my_label = node.name

    ellipse = QGraphicsEllipseItem(
        0, 0, fontSize * 2, fontSize * 2
    )  #I think the first two are coords of center; second pair is major/minor axis
    ellipse.setPen(QPen(QColor('black')))
    ellipse.setBrush(QBrush(QColor('white')))

    text = QGraphicsSimpleTextItem(my_label)
    text.setParentItem(ellipse)
    text.setBrush(QBrush(QColor("black")))
    font = QFont("Arial", fontSize * .9, weight=80)
    font.setLetterSpacing(1, 2)  #add 2 pixels between letters for legibility
    text.setFont(font)

    #Center text according to masterItem size
    tw = text.boundingRect().width()
    th = text.boundingRect().height()
    center = ellipse.boundingRect().center()
    text.setPos(
        center.x() + 1 - tw / 2,
        center.y() - th / 2
    )  #since the last letter has an extra 2 pixels after it from the spacing command, adjust center to compensate

    return ellipse
Ejemplo n.º 2
0
 def update_items(self):
     #self.item = QGraphicsRectItem(0,0,self._total_w, self.row_h)
     seq_width = 0
     nopen = QPen(QtCore.Qt.NoPen)
     font = QFont("Courier", self.fsize)
     rect_cls = self.InteractiveLetterItem if self.interact else QGraphicsRectItem
     for i, letter in enumerate(self.seq):
         width = self.col_w
         for m in self.special_col:
             if m[0] < i <= m[1]:
                 width = self.alt_col_w
                 break
         #load interactive item if called correspondingly
         rectItem = rect_cls(0, 0, width, self.row_h, parent=self.item)
         rectItem.setX(seq_width)  # to give correct X to children item
         rectItem.setBrush(self.bg_col[letter])
         rectItem.setPen(nopen)
         if self.interact:
             if self.codon:
                 rectItem.codon = '%s, %d: %s' % (
                     self.seq[i], i, self.codon[i * 3:i * 3 + 3])
             else:
                 rectItem.codon = '%s, %d' % (self.seq[i], i)
         # write letter if enough space
         if width >= self.fsize:
             text = QGraphicsSimpleTextItem(letter, parent=rectItem)
             text.setFont(font)
             text.setBrush(self.fg_col[letter])
             # Center text according to rectItem size
             tw = text.boundingRect().width()
             th = text.boundingRect().height()
             text.setPos((width - tw) / 2, (self.row_h - th) / 2)
         seq_width += width
     self.width = seq_width
Ejemplo n.º 3
0
def iLabel(node, *args, **kargs):

	#code for making specialized faces for intermediates mostly cribbed from the ete2 website example (though not interactive):
	# http://pythonhosted.org/ete2/tutorial/tutorial_drawing.html#creating-your-custom-interactive-item-faces

	my_label = node.name

	ellipse = QGraphicsEllipseItem(0,0,fontSize*2,fontSize*2) #I think the first two are coords of center; second pair is major/minor axis
	ellipse.setPen(QPen(QColor( 'black' )))
	ellipse.setBrush(QBrush(QColor( 'white' )))

	text = QGraphicsSimpleTextItem(my_label)
	text.setParentItem(ellipse)
	text.setBrush(QBrush(QColor("black")))
	font = QFont("Arial",fontSize*.9,weight=80)
	font.setLetterSpacing(1, 2) #add 2 pixels between letters for legibility
	text.setFont(font)

	#Center text according to masterItem size
	tw = text.boundingRect().width()
	th = text.boundingRect().height()
	center = ellipse.boundingRect().center()
	text.setPos(center.x()+1-tw/2, center.y()-th/2) #since the last letter has an extra 2 pixels after it from the spacing command, adjust center to compensate
    
	return ellipse
Ejemplo n.º 4
0
 def update_items(self):
     #self.item = QGraphicsRectItem(0,0,self._total_w, self.row_h)
     seq_width = 0
     nopen = QPen(QtCore.Qt.NoPen)
     font = QFont("Courier", self.fsize)
     rect_cls = self.InteractiveLetterItem if self.interact else QGraphicsRectItem
     for i, letter in enumerate(self.seq):
         width = self.col_w
         for m in self.special_col:
             if m[0] < i <= m[1]:
                 width = self.alt_col_w
                 break
         #load interactive item if called correspondingly
         rectItem = rect_cls(0, 0, width, self.row_h, parent=self.item)
         rectItem.setX(seq_width) # to give correct X to children item
         rectItem.setBrush(self.bg_col[letter])
         rectItem.setPen(nopen)
         if self.interact:
             if self.codon:
                 rectItem.codon = '%s, %d: %s' % (self.seq[i], i,
                                                  self.codon[i*3:i*3+3])
             else:
                 rectItem.codon = '%s, %d' % (self.seq[i], i)
         # write letter if enough space
         if width >= self.fsize:
             text = QGraphicsSimpleTextItem(letter, parent=rectItem)
             text.setFont(font)
             text.setBrush(self.fg_col[letter])
             # Center text according to rectItem size
             tw = text.boundingRect().width()
             th = text.boundingRect().height()
             text.setPos((width - tw)/2, (self.row_h - th)/2)
         seq_width += width
     self.width = seq_width
Ejemplo n.º 5
0
    def update_items(self):
        rect_cls = QGraphicsRectItem
        self.item = rect_cls(0, 0, self.width, self.row_h)
        seq_width = 0
        nopen = QPen(Qt.NoPen)
        font = QFont("Courier", self.fsize)
        for i, letter in enumerate(self.seq):
            width = self.col_w
            for reg in self.special_col:
                if reg[0] < i <= reg[1]:
                    width = self.alt_col_w
                    break
            rectitem = rect_cls(0, 0, width, self.row_h, parent=self.item)
            rectitem.setX(seq_width)  # to give correct X to children item
            rectitem.setBrush(self.bg_col[letter])
            rectitem.setPen(nopen)

            # write letter if enough space
            if width >= self.fsize:
                text = QGraphicsSimpleTextItem(letter, parent=rectitem)
                text.setFont(font)
                text.setBrush(self.fg_col[letter])
                # Center text according to rectitem size
                txtw = text.boundingRect().width()
                txth = text.boundingRect().height()
                text.setPos((width - txtw) / 2, (self.row_h - txth) / 2)
            seq_width += width
        self.width = seq_width
Ejemplo n.º 6
0
    def update_items(self):
        self.item = QGraphicsRectItem(
            0, 0, self.width, self.row_h * self.coeff_h)
        seq_width = 0
        nopen = QPen(Qt.NoPen)
        self.item.setPen(nopen)
        font = QFont(self.ftype, self.fsize)
        if self.fstyle == "italic":
            font.setStyle(QFont.StyleItalic)
        elif self.fstyle == "oblique":
            font.setStyle(QFont.StyleOblique)
        rect_cls = QGraphicsRectItem
        for i, val in enumerate(self.liste):
            width = self.col_w
            height = self.row_h * len(str(val)) + 1
            rectitem = rect_cls(0, 0, width, height, parent=self.item)
            rectitem.setX(seq_width)  # to give correct X to children item
            rectitem.setBrush(QBrush(QColor(self.bgcolor)))
            rectitem.setPen(nopen)

            # write letter if enough space in height
            if height >= self.fsize:
                text = QGraphicsSimpleTextItem(str(val), parent=rectitem)
                text.setFont(font)
                text.setBrush(QBrush(QColor(self.fgcolor)))
                # Center text according to rectitem size
                # txtw = text.boundingRect().width()
                txth = text.boundingRect().height()
                text.setRotation(self.rot)
                text.setX(txth)
            seq_width += width
        self.width = seq_width
Ejemplo n.º 7
0
 def display_answer(self, question, answers, correct_answer, description, selected_index, correct):
     x, y = self.display_question(question, answers, selected_index, correct) #TODO pass what to check and if right or wrong
     y += 50
     item =  QGraphicsSimpleTextItem("Correct Answer: %s" % correct_answer)
     item.setBrush(self.TEXT_COLOR)
     font = QFont(self.BOLDISH)
     font.setUnderline(True)
     item.setFont(font) 
     item.setX(x)
     item.setY(y)
     self.qtscene.addItem(item)
     self.references.append(item)
     
     y += 60
     item =  QGraphicsSimpleTextItem(make_pretty(description, 55))
     item.setBrush(self.TEXT_COLOR)
     item.setFont(self.NORMALISH) 
     item.setX(x)
     item.setY(y)
     self.qtscene.addItem(item)
     self.references.append(item)
     
     item = QPushButton('Next')
     item.clicked.connect(self.on_next)
     item.setFont(self.BOLDISH) 
     item.move(x+700, y)
     self.qtscene.addWidget(item)
     self.references.append(item)
Ejemplo n.º 8
0
    def update_items(self):
        try:
            max_codons = math.ceil(
                max([len(x) for x in self.readict.values()]) / 2.0) * 2
        except:
            max_codons = 1
        if self.maxcodon:
            max_codons = max(max_codons, self.maxcodon)

        max_h = max_codons * (self.h + self.spacer)
        rect_cls = QGraphicsRectItem
        self.item = rect_cls()
        nopen = QPen(QColor('#EEEEEE'))
        nobrush = QBrush(Qt.NoBrush)
        width = self.mgl
        font = QFont(self.ffamily, self.fsize)
        for aa in self.aa_list:
            codons = self.readict.get(aa, [])
            tot_codons = len(codons)
            hpos = (self.h + self.spacer) * (max_codons - tot_codons) / 2.0

            for cod in codons:
                rectitem = rect_cls(0, 0, self.w, self.h, parent=self.item)
                rectitem.setX(width)
                rectitem.setY(hpos)
                rectitem.setBrush(self.bgcolor[aa])
                rectitem.setPen(nopen)
                hpos += (self.h + self.spacer)
                # write letter if enough space
                if self.w >= self.fsize:
                    text = QGraphicsSimpleTextItem(cod, parent=rectitem)
                    text.setFont(font)
                    text.setBrush(self.fgcolor[aa])
                    # Center text according to rectitem size
                    txtw = text.boundingRect().width()
                    txth = text.boundingRect().height()
                    text.setPos((self.w - txtw) / 2, (self.h - txth) / 2)

            # this only happen if codon reassignment not found for aa
            # we do not need a spacer if it's an internal node (I hope)
            if hpos == 0 and self.is_leaf:
                rectitem = rect_cls(0, 0, self.w, self.h, parent=self.item)
                rectitem.setX(width)
                rectitem.setY(hpos)
                rectitem.setBrush(nobrush)
                rectitem.setPen(nopen)

            width += self.w + self.spacer

        self.width = width
        self.item.setPen(nopen)
        self.item.setRect(0, 0, self.width, max_h)
Ejemplo n.º 9
0
 def add_text(self):
     if (self.labels):
         center = self.item.boundingRect().center()
         text = QGraphicsSimpleTextItem(str(self.labels))
         text.setFont(QFont("Arial", self.label_size))
         text.setParentItem(self.item)
         text.setBrush(QBrush(QColor('#ddd')))
         tw = text.boundingRect().width() / 2.
         th = text.boundingRect().height() / 2.
         x = -tw + center.x()
         y = -th + center.y()
         # Center text according to masterItem size
         text.setPos(x, y)
Ejemplo n.º 10
0
    def update_items(self):
        rect_cls = QGraphicsRectItem
        nobrush = QBrush(Qt.NoBrush)
        nopen = QPen(QColor('#FFFFFF'))
        grad = Qt.NoBrush
        self.item = rect_cls()

        for codon in self.codons.keys():
            rectitem = rect_cls(self.width, self.margin,
                                self.w, self.h, parent=self.item)
            total_rea = len(self.aa_list[codon])
            if total_rea > 0:

                grad = QLinearGradient(QPointF(0, 0.5), QPointF(1, 0.5))
                grad.setCoordinateMode(QLinearGradient.ObjectBoundingMode)
                pointpos = 1.0 / total_rea
                starting = -0.001
                for reqcol, aa in enumerate(self.aa_list[codon]):
                    curcol = self.bgcolor[aa]
                    # use the same color twice to mark start and end
                    grad.setColorAt(starting + 0.001, curcol)
                    starting += pointpos
                    grad.setColorAt(starting, curcol)

                    # grad.setColorAt(starting, QColor(curcol))
            # put small rec in big rec
            # Comment award of the year !
            brush = QBrush(QColor('#CCCCCC'))
            pen = QPen(QColor('#BBBBBB'))
            if self.codons[codon]:
                brush = QBrush(grad)
                pen = QPen(QColor('#000000'))

            rectitem.setBrush(brush)
            rectitem.setPen(pen)
            # Center text according to rectitem size
            text = QGraphicsSimpleTextItem(self.codons[codon], parent=rectitem)
            text.setFont(self.font)
            text.setBrush(self.fgcolor)
            center = rectitem.boundingRect().center()
            txtw = text.boundingRect().width()
            txth = text.boundingRect().height()
            text.setPos(center.x() - txtw / 2, center.y() - txth / 2)

            self.width += self.w + self.margin

        # now plot the big rect (with margin)
        self.item.setPen(nopen)
        self.item.setBrush(nobrush)
        self.item.setRect(0, 0, self.width, self.h + (2 * self.margin))
Ejemplo n.º 11
0
def iLabel(node, *args, **kargs):

	#code for making specialized faces for intermediates mostly cribbed from the ete2 website example (though not interactive):
	# http://pythonhosted.org/ete2/tutorial/tutorial_drawing.html#creating-your-custom-interactive-item-faces

	my_label = args[0][0] #or maybe just node.name?

	ellipse = QGraphicsEllipseItem(0,0,fontSize*2,fontSize*2) #I think the first two are coords of center; second pair is major/minor axis
	ellipse.setBrush(QBrush(QColor( 'black' )))

	text = QGraphicsSimpleTextItem(my_label)
	text.setParentItem(ellipse)
	text.setBrush(QBrush(QColor("white")))
	text.setFont(QFont("Arial",fontSize*.75))

	#Center text according to masterItem size
	tw = text.boundingRect().width()
	th = text.boundingRect().height()
	center = ellipse.boundingRect().center()
	text.setPos(center.x()-tw/2, center.y()-th/2)
    
	return ellipse
Ejemplo n.º 12
0
def iLabel(node, *args, **kargs):

    #code for making specialized faces for intermediates mostly cribbed from the ete2 website example (though not interactive):
    # http://pythonhosted.org/ete2/tutorial/tutorial_drawing.html#creating-your-custom-interactive-item-faces

    my_label = args[0][0]  #or maybe just node.name?

    ellipse = QGraphicsEllipseItem(
        0, 0, fontSize * 2, fontSize * 2
    )  #I think the first two are coords of center; second pair is major/minor axis
    ellipse.setBrush(QBrush(QColor('black')))

    text = QGraphicsSimpleTextItem(my_label)
    text.setParentItem(ellipse)
    text.setBrush(QBrush(QColor("white")))
    text.setFont(QFont("Arial", fontSize * .75))

    #Center text according to masterItem size
    tw = text.boundingRect().width()
    th = text.boundingRect().height()
    center = ellipse.boundingRect().center()
    text.setPos(center.x() - tw / 2, center.y() - th / 2)

    return ellipse
Ejemplo n.º 13
0
 def display_question(self, question, answers, selected_index = None, correct = None):
     self._init_scene()
     x = 50
     y = 25
     item =  QGraphicsSimpleTextItem(question)
     item.setBrush(self.TEXT_COLOR)
     item.setFont(self.BOLDISH) 
     item.setX(x)
     item.setY(y)
     self.qtscene.addItem(item)
     self.references.append(item)
     y += 75
     
     for index, answer in enumerate(answers):
         index += 1
         item =  QGraphicsSimpleTextItem("%s) %s" % (index, answer))
         item.setBrush(self.TEXT_COLOR)
         item.setFont(self.NORMALISH) 
         item.setX(x)
         item.setY(y)
         item.setAcceptHoverEvents(True)
         self.qtscene.addItem(item)
         self.references.append(item)
         #TODO: do not register click but do show check or not
         if not selected_index:
             item.hoverEnterEvent = partial(self.on_hover_answer, item) 
             item.hoverLeaveEvent = partial(self.on_unhover_answer, item) 
             item.mousePressEvent = partial(self.on_click_answer, index) 
         elif selected_index == index:
             if correct:
                 item =  QGraphicsSimpleTextItem(u"\u2713")
                 item.setBrush(QBrush(QColor(0,150,0)))
                 item.setX(0)
             else:
                 item =  QGraphicsSimpleTextItem("X")
                 item.setBrush(QBrush(QColor(255,0,0)))
                 item.setX(3)
             item.setFont(self.BOLDISH)
             item.setY(y)
             self.qtscene.addItem(item)
             self.references.append(item)
             
         y += 50
     return x, y
Ejemplo n.º 14
0
class PreCrossoverHandle(QGraphicsItem):
    scafpen = QPen(styles.pch_scaf_stroke, styles.PATH_STRAND_STROKE_WIDTH)
    scafpen.setCapStyle(Qt.FlatCap)  # or Qt.RoundCap
    scafpen.setJoinStyle(Qt.RoundJoin)
    stappen = QPen(styles.pch_stap_stroke, styles.PATH_STRAND_STROKE_WIDTH)
    stappen.setCapStyle(Qt.FlatCap)  # or Qt.RoundCap
    stappen.setJoinStyle(Qt.RoundJoin)
    disabpen = QPen(styles.pch_disab_stroke, styles.PATH_STRAND_STROKE_WIDTH)
    disabpen.setCapStyle(Qt.FlatCap)
    disabpen.setJoinStyle(Qt.RoundJoin)
    disabbrush = QBrush(styles.pch_disab_stroke)  # For the helix number label
    enabbrush = QBrush(Qt.SolidPattern)  # Also for the helix number label
    baseWidth = styles.PATH_BASE_WIDTH
    rect = QRectF(0, 0, styles.PATH_BASE_WIDTH, styles.PATH_BASE_WIDTH)
    toHelixNumFont = QFont("Times", 10, QFont.Bold)
    
    def __init__(self, parentPH, fromStrand, fromIdx, toVH, toIdx, orientedLeft):
        super(PreCrossoverHandle, self).__init__(parentPH)
        self.fromVH = parentPH.vhelix()
        self.fromStrand = fromStrand
        self.fromIdx = fromIdx
        self.toVH = toVH
        self.toIdx = toIdx
        self.orientedLeft = orientedLeft
        
        self.fromVH.basesModified.connect(self.updateVisibilityAndEnabledness)
        self.toVH.basesModified.connect(self.updateVisibilityAndEnabledness)
        
        self.label = QGraphicsSimpleTextItem(str(toVH.number()), parent=self)
        self.label.setFont(self.toHelixNumFont)
        
        x = self.baseWidth * self.fromIdx
        y = (-1.25 if self.onTopStrand() else 2.25) * self.baseWidth
        self.setPos(x, y)
        halfLabelW = self.label.boundingRect().width() / 2
        labelX = self.baseWidth/2 - halfLabelW
        labelY = (-.10 if self.onTopStrand() else .48) * self.baseWidth
        self.label.setPos(labelX, labelY)
        self.updateVisibilityAndEnabledness()
    
    def onTopStrand(self):
        return self.fromVH.evenParity() and self.fromStrand==StrandType.Scaffold or\
               not self.fromVH.evenParity() and self.fromStrand==StrandType.Staple
            
    def couldFormNewCrossover(self):
        return self.fromVH.possibleNewCrossoverAt(self.fromStrand, self.fromIdx, self.toVH, self.toIdx)
    
    def crossoverExists(self):
        return self.fromVH.hasCrossoverAt(self.fromStrand, self.fromIdx)
    
    def is3pEndOfCrossover(self):
        return self.orientedLeft and self.onTopStrand() or\
               not self.orientedLeft and not self.onTopStrand
    
    def updateVisibilityAndEnabledness(self):
        shouldBeVisible = not self.crossoverExists()
        self.setVisible(shouldBeVisible)
        self.label.setVisible(shouldBeVisible)
        if self.couldFormNewCrossover():
            self.label.setBrush(self.enabbrush)
        else:
            self.label.setBrush(self.disabbrush)
        self.update()
    
    def paint(self, painter, option, widget=None):
        #Look Up Table
        pathLUT = (_ppathRD, _ppathRU, _ppathLD, _ppathLU)
        path = pathLUT[2*int(self.orientedLeft) + int(self.onTopStrand())]
        pen = self.disabpen
        if self.couldFormNewCrossover():
            if self.fromStrand == StrandType.Scaffold:
                pen = self.scafpen
            else:
                pen = self.stappen
        painter.setPen(pen)
        painter.drawPath(path)
    
    def boundingRect(self):
        return self.rect
    
    def mousePressEvent(self, event):
        if event.button() != Qt.LeftButton:
            return QGraphicsItem.mousePressEvent(self, event)
        if not self.couldFormNewCrossover():
            return
        # Determine upstream base
        fromHelix, toHelix = self.fromVH, self.toVH
        fromIdx, toIdx = self.fromIdx, self.toIdx
        if not self.is3pEndOfCrossover():
            fromHelix, toHelix = toHelix, fromHelix
            fromIdx, toIdx = toIdx, fromIdx
        # Create XoverHandlePair and store references
        # fromHelix.installXoverFrom3To5(StrandType.Scaffold, \
        #                                 fromIndex, toHelix, toIndex)
        fromHelix.installXoverFrom3To5(self.fromStrand, \
                                        fromIdx, toHelix, toIdx)
Ejemplo n.º 15
0
class ActiveSliceHandle(QGraphicsItem):
    """docstring for ActiveSliceHandle"""
    _baseWidth = styles.PATH_BASE_WIDTH
    _brush = QBrush(styles.orangefill)
    _labelbrush = QBrush(styles.orangestroke)
    _pen = QPen(styles.orangestroke, styles.SLICE_HANDLE_STROKE_WIDTH)
    _myfont = QFont("Times", 12, QFont.Bold)

    def __init__(self, pathHelixGroup):
        super(ActiveSliceHandle, self).__init__(pathHelixGroup)
        self._pathHelixGroup = None
        self._activeSlice = 0
        self._dragMode = False
        self._label = QGraphicsSimpleTextItem("", parent=self)
        self._label.setPos(0, -18)
        self._label.setFont(self._myfont)
        self._label.setBrush(self._labelbrush)
        self._label.hide()
        self.setPathHelixGroup(pathHelixGroup)
        self.setFlag(QGraphicsItem.ItemIsMovable)
        self.setAcceptHoverEvents(True)
        self.setZValue(styles.ZACTIVESLICEHANDLE)

    def controller(self):
        return self._pathHelixGroup.controller()

    def part(self):
        return self._pathHelixGroup.part()

    def pathHelixGroup(self):
        return self._pathHelixGroup

    def setPathHelixGroup(self, newPHG):
        if self._pathHelixGroup:
            self._pathHelixGroup.geometryChanged.disconnect(\
                                                   self.prepareGeometryChange)
            self._pathHelixGroup.displayedVHsChanged.disconnect(self._hideIfEmptySelection)
        if self._pathHelixGroup and self._pathHelixGroup.part():
            self._pathHelixGroup.part().activeSliceWillChange.disconnect(\
                                                      self._updateActiveSlice)
        self._pathHelixGroup = newPHG
        newPHG.geometryChanged.connect(self.prepareGeometryChange)
        newPHG.part().activeSliceWillChange.connect(self._updateActiveSlice)
        newPHG.displayedVHsChanged.connect(self._hideIfEmptySelection)
        self._hideIfEmptySelection()
        self._updateActiveSlice(newPHG.part().activeSlice())

    def activeSlice(self):
        return self.part().activeSlice()

    def setActiveSlice(self, baseIndex):
        self.part().setActiveSlice(baseIndex)
    
    def _hideIfEmptySelection(self):
        self.setVisible(len(self.pathHelixGroup().displayedVHs())>0)
    
    def _updateActiveSlice(self, baseIndex):
        """The slot that receives active slice changed notifications from
        the part and changes the receiver to reflect the part"""
        bi = int(baseIndex)
        if bi < 0 or bi >= self.part().dimensions()[2]:
            raise IndexError
        self.setPos(bi * self._baseWidth, -styles.PATH_HELIX_PADDING)
        self._activeSlice = bi
        if self._label:
            self._label.setText("%d" % bi)
            self._label.setX((self._baseWidth -\
                              self._label.boundingRect().width()) / 2)

    def boundingRect(self):
        return QRectF(0, 0, self._baseWidth,\
                      self.pathHelixGroup().boundingRect().height())

    def paint(self, painter, option, widget=None):
        if self.boundingRect().height() > 0:
            painter.setBrush(self._brush)
            painter.setPen(self._pen)
            painter.drawRect(self.boundingRect())
            self._label.show()
        else:
            self._label.hide()

    def resetBounds(self, maxBase):
        """Call after resizing virtualhelix canvas."""
        self.maxBase = maxBase
        self.maxX = (maxBase - 1) * self._baseWidth

    def hoverEnterEvent(self, event):
        if self.controller().isSelectToolActive():
            self.setCursor(Qt.OpenHandCursor)
        QGraphicsItem.hoverEnterEvent(self, event)
    # end def

    # def hoverMoveEvent(self, event):
    #     if not self.controller().isSelectToolActive():
    #         # pass None, but if needed pass self for having a special
    #         # behavior for the slice helix
    #         self.controller().toolHoverMove(None, event, flag=True)
    #     QGraphicsItem.hoverMoveEvent(self, event)
    # end def

    def hoverLeaveEvent(self, event):
        self.setCursor(Qt.ArrowCursor)
        QGraphicsItem.hoverLeaveEvent(self, event)
    # end def

    def mouseMoveEvent(self, event):
        """Snaps handle into place when dragging."""
        if not self.controller().isSelectToolActive() or not self._dragMode:
            return
        x = event.scenePos().x()
        dx = int((x - self.pressX)/self._baseWidth)
        self.setActiveSlice(self.pressBaseIdx+dx)

    def mousePressEvent(self, event):
        if event.button() != Qt.LeftButton:
            event.ignore()
            QGraphicsItem.mousePressEvent(self, event)
            return
        if not self.controller().isSelectToolActive():
            return
        self.scene().views()[0].addToPressList(self)
        self._dragMode = True
        self.pressX = event.scenePos().x()
        self.pressBaseIdx = self.activeSlice()

    def customMouseRelease(self, eventPosition):
        """Snaps to grid after mouse released. Updates vhelix data according
        to what movement took place."""
        self._dragMode = False

    def moveToLastSlice(self):
        """Moves to the last slice position."""
        self.setActiveSlice(self.part().numBases() - 1)

    def moveToFirstSlice(self):
        """Moves to the last slice position."""
        self.setActiveSlice(0)