示例#1
0
  def __layoutActions(self):
    if self._layout == None:
      self._layout = dict()
      actions = self.actions()
      count = len(actions)
      angleStep = 2.0*math.pi/float(count)
      angle = 0
      fontMetrics = QtGui.QFontMetrics(self.font())
      radius = 120
      bounds = QRect()
      for a in actions:
        r = fontMetrics.boundingRect(a.text()).adjusted(-8, -8, 8, 8)
        r = r.translated(radius*math.cos(angle), radius*math.sin(angle))
        r = r.translated(-r.width()/2, -r.height()/2)
        r = r.translated(self.width()/2, self.height()/2)
        self._layout[a] = r
        bounds |= r
        angle += angleStep

      bounds = bounds.adjusted(-self._lineWidth, -self._lineWidth, self._lineWidth, self._lineWidth)
      for a in self._layout.keys():
        r = self._layout[a]
        r.translate(-bounds.x(), -bounds.y())

      self.resize(bounds.width(), bounds.height())
    def __layoutActions(self):
        if self._layout == None:
            self._layout = dict()
            actions = self.actions()
            count = len(actions)
            angleStep = 2.0 * math.pi / float(count)
            angle = 0
            fontMetrics = QtGui.QFontMetrics(self.font())
            radius = 120
            bounds = QRect()
            for a in actions:
                r = fontMetrics.boundingRect(a.text()).adjusted(-8, -8, 8, 8)
                r = r.translated(radius * math.cos(angle),
                                 radius * math.sin(angle))
                r = r.translated(-r.width() / 2, -r.height() / 2)
                r = r.translated(self.width() / 2, self.height() / 2)
                self._layout[a] = r
                bounds |= r
                angle += angleStep

            bounds = bounds.adjusted(-self._lineWidth, -self._lineWidth,
                                     self._lineWidth, self._lineWidth)
            for a in self._layout.keys():
                r = self._layout[a]
                r.translate(-bounds.x(), -bounds.y())

            self.resize(bounds.width(), bounds.height())
示例#3
0
文件: bars_chart.py 项目: wiz21b/koi
    def _draw_peak_values(self, painter, labels):
        #mainlog.debug('_draw_peak_values : {}'.format(labels))
        text_pen = QPen()
        text_pen.setCapStyle(Qt.RoundCap)
        text_pen.setColor(Qt.GlobalColor.white) # alpha=255=fully opaque
        text_pen.setWidth(1)
        fm = painter.fontMetrics()

        rects = []

        painter.setPen(text_pen)

        # The sort allow to draw the peak values which are lower first.
        # We do that to visually connect a peak value to its bar in a
        # (hopefully) better way

        for i in sorted( range(len(labels)), key=lambda i:self._item_coordinates(i)[1]):
            x, y_top, y_below = self._item_coordinates(i)

            label = labels[i]

            w = fm.boundingRect(label).width()
            h = fm.boundingRect(label).height()

            r = QRect(self.x_centers[i] - int(w/2), self.y_base-y_top - 5 - h, w, h)

            i = 0
            while i < len(rects):
                old_r = rects[i]
                if r.intersect(old_r):
                    i = 0
                    # Move r atop old_r
                    r.translate(0, -(r.bottom() - old_r.y()) - 2)
                else:
                    i += 1
            rects.append(r)

            self._draw_box_under_text(painter, r.x(), r.y() + h,label)
            painter.drawText( r.x(), r.y() + h,label)
示例#4
0
class PackedRect:
    """ Given p and a starting rect, draw
        a subrectangle that takes <= p% of the
        area of the starting rect. Repeat for p1,p2...
        as long as there continues to be room in the parent rect"""  
    
    def __init__(self, parentRect, percentageItems):
        self.parentRect = self.leftoverRect = QRect()
        self.percItems = sorted(percentageItems, key=lambda pItem: pItem.getLocalPercentage(), reverse = True)
        self.parentRect = QRect(parentRect)
        self.reset()
        self.percs = []
        
    def __iter__(self):
        return self
        
    def next(self):
        perc = 0
        if self.currPercItem < len(self.percItems) and not self.isEmpty():
            while perc == 0:
                if self.currPercItem < len(self.percItems):
                    percItem = self.percItems[self.currPercItem]
                    perc = percItem.getLocalPercentage()
                else:
                    raise StopIteration()
                self.currPercItem += 1
            
            return (percItem, self.nextRect(perc))
        else:
            raise StopIteration()
        
        
    def reset(self):
        import copy
        self.lastFlipPercentage = 100
        self.currPercItem = 0
        self.leftoverRect = QRect(self.parentRect)
        
    def __updateDirectionToPreferSquareness(self, neededArea):
        """ Pick a direction that will give a more square 
            result for the next rectangle, but strongly
            bias toward horizontal. Its important for there
            to be consistency in this algorithm and not 
            have it depend on any weird side effects """
        biasTowardHoriz = 1.5
        (width, height) = (self.leftoverRect.width(),self.leftoverRect.height())
        (width, height) = self.__calculaceGivingUpWidth(neededArea, width, height)
        widthDiff = abs(width-height) 
        (width, height) = (self.leftoverRect.width(),self.leftoverRect.height())
        (width, height) = self.__calculateGivingUpHeight(neededArea, width, height)
        heightDiff = abs(width-height)
        if widthDiff < (heightDiff * biasTowardHoriz):
            return Direction.Horizontal
        else:
            return Direction.Vertical
        
            
    def isEmpty(self):
        return self.leftoverRect.isEmpty()
    
    def __isNeededAreaMoreThanLeftover(self, neededArea):
        leftoverArea = self.leftoverRect.width() * self.leftoverRect.height()
        return (neededArea + 0.01) > leftoverArea

        
            
    @validRectReturned
    def __giveUpAllRemainingArea(self):
        """ Return all remaining leftover space and empty
            the leftover rect"""
        assert not self.leftoverRect.isEmpty()
        remaining = QRect(self.leftoverRect)
        self.leftoverRect.setWidth(-1)
        self.leftoverRect.setHeight(-1)
        assert self.leftoverRect.isEmpty()
        return remaining
    
    def __calculateGivingUpHeight(self, neededArea, width, height):
        height = neededArea / width
        height = ceil(height)
        return (width, height)
        
    def __calculaceGivingUpWidth(self, neededArea, width, height):
        width = neededArea / height
        width = ceil(width)
        return (width, height)
        
    
    def __giveUpLeftoverHeight(self, neededArea, width, height):
        """ Sacrifice some height from the leftover rect for the needed area"""
        (width, height) = self.__calculateGivingUpHeight(neededArea, width, height)
        self.leftoverRect.setY(self.leftoverRect.y() + height)
        return (width, height)
        
    def __giveUpLeftoverWidth(self, neededArea, width, height):
        """ Sacrifice some width from the leftover rect for the needed area"""
        (width, height) = self.__calculaceGivingUpWidth(neededArea, width, height)
        self.leftoverRect.setX(self.leftoverRect.x() + width)
        return (width, height)
    
    @validRectReturned    
    def __giveUpSomeLeftoverSpace(self, neededArea):
        """ Sacrifice some leftover space to represent the neededARea"""
        thisDir = self.__updateDirectionToPreferSquareness(neededArea)
        giveUpFns = [self.__giveUpLeftoverWidth, self.__giveUpLeftoverHeight] 
        fn = giveUpFns[thisDir]
        newRect = QRect()
        newRect.setTopLeft(self.leftoverRect.topLeft())
        (width, height) = (self.leftoverRect.width(), self.leftoverRect.height())
        
        (width, height) = fn(neededArea, width, height)
      
        if not self.leftoverRect.isValid() and not self.leftoverRect.isEmpty():
            print "Failure with the following input"
            print "W/H %i/%i" % (width, height)
            print "ParentRect %s" % repr(self.parentRect)
            print "Leftover %s" % repr(self.leftoverRect)
            print "Percentages %s" % repr(self.percs)

            assert False
        
        newRect.setHeight(height)
        newRect.setWidth(width)
        return newRect

        
    @validRectReturned
    def nextRect(self, percentage):
        """ Get the next rect from leftoverRect, update
            leftoverRect with whats leftover """
        self.percs.append(percentage)
        if self.isEmpty():
            raise ValueError("This guy is empty pR: %s perc: %s" % (self.parentRect, self.percs))
        neededArea = (self.parentRect.width() * self.parentRect.height()) * (percentage/100.0)
        if self.__isNeededAreaMoreThanLeftover(neededArea):
            return self.__giveUpAllRemainingArea()
        
        return self.__giveUpSomeLeftoverSpace(neededArea)
    
    def __repr__(self):
        return "PackedRect(%s)" % repr(self.parentRect) 

    def __str__(self):
        return self.__repr__() + " Leftover(%s)" % repr(self.leftoverRect)