class PieView

Public Class Methods

new(parent = nil) click to toggle source
Calls superclass method
# File examples/itemviews/chart/pieview.rb, line 32
def initialize(parent = nil)
    super(parent)
    horizontalScrollBar.range = 0..0
    verticalScrollBar.range = 0..0

    @margin = 8
    @totalSize = 300
    @pieSize = @totalSize - 2*@margin
    @validItems = 0
    @totalValue = 0.0
end

Public Instance Methods

dataChanged(topLeft, bottomRight) click to toggle source
Calls superclass method
# File examples/itemviews/chart/pieview.rb, line 44
def dataChanged(topLeft, bottomRight)
    super(topLeft, bottomRight)

    @validItems = 0
    @totalValue = 0.0

    (0...model().rowCount(rootIndex())).each do |row|

        index = model().index(row, 1, rootIndex())
        value = model().data(index).toDouble

        if value > 0.0
            @totalValue += value
            @validItems += 1
        end
    end
    viewport().update()
end
edit(index, trigger, event) click to toggle source
Calls superclass method
# File examples/itemviews/chart/pieview.rb, line 63
def edit(index, trigger, event)
    if index.column() == 0
        return super(index, trigger, event)
    else
        return false
    end
end
horizontalOffset() click to toggle source
# File examples/itemviews/chart/pieview.rb, line 225
def horizontalOffset()
    return horizontalScrollBar().value()
end
indexAt(point) click to toggle source

Returns the item that covers the coordinate given in the view.

# File examples/itemviews/chart/pieview.rb, line 73
def indexAt(point)
    if @validItems == 0
        return Qt::ModelIndex.new
    end

    # Transform the view coordinates into contents widget coordinates.
    wx = point.x() + horizontalScrollBar().value()
    wy = point.y() + verticalScrollBar().value()

    if wx < @totalSize
        cx = wx - @totalSize/2
        cy = @totalSize/2 - wy # positive cy for items above the center

        # Determine the distance from the center point of the pie chart.
        d = ((cx ** 2) + (cy ** 2)) ** 0.5

        if d == 0 || d > @pieSize/2
            return Qt::ModelIndex.new
        end

        # Determine the angle of the point.
        angle = (180 / Math::PI) * Math.acos(cx/d)
        if cy < 0
            angle = 360 - angle
        end

        # Find the relevant slice of the pie.
        startAngle = 0.0

        for row in 0...model.rowCount(rootIndex)

            index = model.index(row, 1, rootIndex())
            value = model.data(index).to_f

            if value > 0.0
                sliceAngle = 360*value/@totalValue

                if angle >= startAngle && angle < (startAngle + sliceAngle)
                    return model().index(row, 1, rootIndex())
                end

                startAngle += sliceAngle
            end
        end
    else
        itemHeight = Qt::FontMetrics.new(viewOptions().font).height()
        listItem = ((wy - @margin) / itemHeight).to_i
        validRow = 0

        for row in 0...model.rowCount(rootIndex) do

            index = model().index(row, 1, rootIndex())
            if model().data(index).to_f > 0.0

                if listItem == validRow
                    return model().index(row, 0, rootIndex())
                end

                # Update the list index that corresponds to the next valid row.
                validRow += 1
            end
        end
    end

    return Qt::ModelIndex.new
end
isIndexHidden(index) click to toggle source
# File examples/itemviews/chart/pieview.rb, line 140
def isIndexHidden(index)
    return false
end
itemRect(index) click to toggle source

Returns the rectangle of the item at position a index in the model. The rectangle is in contents coordinates.

# File examples/itemviews/chart/pieview.rb, line 147
def itemRect(index)
    if !index.isValid()
        return Qt::Rect.new
    end

    # Check whether the index's row is in the list of rows represented
    # by slices.
    valueIndex = Qt::ModelIndex.new

    if index.column() != 1
        valueIndex = model().index(index.row(), 1, rootIndex())
    else
        valueIndex = index
    end

    if model().data(valueIndex).toDouble > 0.0

        listItem = 0
        (index.row()-1).downto(0) do |row|
            if model().data(model().index(row, 1, rootIndex())).toDouble > 0.0
                listItem += 1
            end
        end

        case index.column
        when 0
            itemHeight = Qt::FontMetrics.new(viewOptions().font).height()

            return Qt::Rect.new(@totalSize,
                         (@margin + listItem*itemHeight).to_i,
                         @totalSize - @margin, itemHeight.to_i)
        when 1
            return viewport().rect()
        end

    end
    return Qt::Rect.new
end
itemRegion(index) click to toggle source
# File examples/itemviews/chart/pieview.rb, line 186
def itemRegion(index)
    if !index.isValid()
        return Qt::Region.new
    end

    if index.column() != 1
        return Qt::Region.new(itemRect(index))
    end

    if model().data(index).to_f <= 0.0
        return Qt::Region.new
    end

    startAngle = 0.0
    (0...model.rowCount(rootIndex())).each do |row|

        sliceIndex = model.index(row, 1, rootIndex)
        value = model.data(sliceIndex).to_f

        if value > 0.0
            angle = 360*value/@totalValue

            if sliceIndex == index
                slicePath = Qt::PainterPath.new
                slicePath.moveTo(@totalSize/2, @totalSize/2)
                slicePath.arcTo(@margin, @margin, @margin+@pieSize, @margin+@pieSize,
                                startAngle, angle)
                slicePath.closeSubpath()

                return Qt::Region.new(slicePath.toFillPolygon().toPolygon())
            end

            startAngle += angle
        end
    end

    return Qt::Region.new
end
mouseReleaseEvent(event) click to toggle source
Calls superclass method
# File examples/itemviews/chart/pieview.rb, line 229
def mouseReleaseEvent(event)
    super(event)
    @selectionRect = Qt::Rect.new
    viewport().update()
end
moveCursor(cursorAction, modifiers) click to toggle source
# File examples/itemviews/chart/pieview.rb, line 235
def moveCursor(cursorAction, modifiers)
    current = currentIndex()

    case cursorAction
    when MoveLeft, MoveUp
        if current.row > 0
            current = model().index(current.row() - 1, current.column,
                                        rootIndex())
        else
            current = model().index(0, current.column, rootIndex())
        end
    when MoveRight, MoveDown
        if current.row < rows(current) - 1
            current = model().index(current.row + 1, current.column,
                                        rootIndex())
        else
            current = model().index(rows(current) - 1, current.column,
                                        rootIndex())
        end
    end

    viewport().update()
    return current
end
paintEvent(event) click to toggle source
# File examples/itemviews/chart/pieview.rb, line 260
def paintEvent(event)
    selections = selectionModel()
    option = viewOptions()
    state = option.state
 
    background = option.palette.base()
    foreground = Qt::Pen.new(option.palette.color(Qt::Palette::Foreground))
    textPen = Qt::Pen.new(option.palette.color(Qt::Palette::Text))
    highlightedPen = Qt::Pen.new(option.palette.color(Qt::Palette::HighlightedText))

    painter = Qt::Painter.new(viewport())
    painter.renderHint = Qt::Painter::Antialiasing

    painter.fillRect(event.rect(), background)
    painter.pen = foreground

    # Viewport rectangles
    pieRect = Qt::Rect.new(@margin, @margin, @pieSize, @pieSize)
    keyPoint = Qt::Point.new(@totalSize - horizontalScrollBar().value(),
                             @margin - verticalScrollBar().value())

    if @validItems > 0
        painter.save()
        painter.translate(pieRect.x() - horizontalScrollBar().value(),
                          pieRect.y() - verticalScrollBar().value())
        painter.drawEllipse(0, 0, @pieSize, @pieSize)
        startAngle = 0.0

        for row in 0...model.rowCount(rootIndex) do
            index = model.index(row, 1, rootIndex())
            value = model.data(index).toDouble

            if value > 0.0
                angle = 360*value/@totalValue

                colorIndex = model().index(row, 0, rootIndex())
                color = Qt::Color.new(model().data(colorIndex,
                                Qt::DecorationRole).toString)

                if currentIndex() == index
                    painter.brush = Qt::Brush.new(color, Qt::Dense4Pattern)
                elsif selections.isSelected(index)
                    painter.brush = Qt::Brush.new(color, Qt::Dense3Pattern)
                else
                    painter.brush = Qt::Brush.new(color)
                end

                painter.drawPie(0, 0, @pieSize, @pieSize, (startAngle*16).to_i,
                                (angle*16).to_i)

                startAngle += angle
            end
        end
        painter.restore()

        keyNumber = 0

        for row in 0...model.rowCount(rootIndex()) do

            index = model.index(row, 1, rootIndex())
            value = model.data(index).toDouble

            if value > 0.0
                labelIndex = model.index(row, 0, rootIndex())

                option = viewOptions()
                option.rect = visualRect(labelIndex)
                if selections.isSelected(labelIndex)
                    option.state |= Qt::Style::State_Selected.to_i
                end
                if currentIndex() == labelIndex
                    option.state |= Qt::Style::State_HasFocus.to_i
                end
                itemDelegate().paint(painter, option, labelIndex)

                keyNumber += 1
            end
        end
    end

    if !@selectionRect.nil?
        band = Qt::StyleOptionRubberBand.new
        band.shape = Qt::RubberBand::Rectangle
        band.rect = @selectionRect
        painter.save()
        style().drawControl(Qt::Style::CE_RubberBand, band, painter)
        painter.restore()
    end

    painter.end
end
resizeEvent(event) click to toggle source
# File examples/itemviews/chart/pieview.rb, line 352
def resizeEvent(event)
    updateGeometries()
end
rows(index) click to toggle source
# File examples/itemviews/chart/pieview.rb, line 356
def rows(index)
    return model().rowCount(model().parent(index))
end
rowsAboutToBeRemoved(parent, start_row, end_row) click to toggle source
Calls superclass method
# File examples/itemviews/chart/pieview.rb, line 375
def rowsAboutToBeRemoved(parent, start_row, end_row)
    for row in start_row..end_row do

        index = model.index(row, 1, rootIndex())
        value = model.data(index).toDouble
        if value > 0.0
            @totalValue -= value
            @validItems -= 1
        end
    end

    super(parent, start_row, end_row)
end
rowsInserted(parent, start_row, end_row) click to toggle source
Calls superclass method
# File examples/itemviews/chart/pieview.rb, line 360
def rowsInserted(parent, start_row, end_row)
    for row in start_row..end_row do

        index = model.index(row, 1, rootIndex)
        value = model.data(index).toDouble

        if value > 0.0
            @totalValue += value
            @validItems += 1
        end
    end

    super(parent, start_row, end_row)
end
scrollContentsBy(dx, dy) click to toggle source
# File examples/itemviews/chart/pieview.rb, line 389
def scrollContentsBy(dx, dy)
    viewport().scroll(dx, dy)
end
scrollTo(index, hint) click to toggle source
# File examples/itemviews/chart/pieview.rb, line 393
def scrollTo(index, hint)
    area = viewport.rect
    rect = visualRect(index)

    if rect.left < area.left
        horizontalScrollBar.setValue(
            horizontalScrollBar.value + rect.left - area.left)
    elsif rect.right > area.right
        horizontalScrollBar.setValue(
            horizontalScrollBar.value +
                [rect.right - area.right, rect.left - area.left].min)
    end

    if rect.top < area.top()
        verticalScrollBar.setValue(
            verticalScrollBar.value + rect.top - area.top)
    elsif rect.bottom > area.bottom()
        verticalScrollBar.setValue(
            verticalScrollBar.value +
                [rect.bottom - area.bottom, rect.top - area.top].min)
    end
end
setSelection(rect, command) click to toggle source

Find the indices corresponding to the extent of the selection.

# File examples/itemviews/chart/pieview.rb, line 417
def setSelection(rect, command)
    # Use content widget coordinates because we will use the itemRegion()
    # function to check for intersections.

    contentsRect = rect.translated(horizontalScrollBar.value,
                                         verticalScrollBar.value)

    rows = model.rowCount(rootIndex)
    columns = model.columnCount(rootIndex)
    indexes = []

    for row in 0...rows do
        for column in 0...columns do
            index = model.index(row, column, rootIndex)
            region = itemRegion(index)
            if !region.intersect(Qt::Region.new(contentsRect)).empty?
                indexes.push(index)
            end
        end
    end

    if indexes.size > 0
        firstRow = indexes[0].row
        lastRow = indexes[0].row
        firstColumn = indexes[0].column
        lastColumn = indexes[0].column

        for i in 1...indexes.size do
            firstRow = [firstRow, indexes[i].row].min
            lastRow = [lastRow, indexes[i].row].max
            firstColumn = [firstColumn, indexes[i].column].min
            lastColumn = [lastColumn, indexes[i].column].max
        end

         selection = Qt::ItemSelection.new(
            model.index(firstRow, firstColumn, rootIndex()),
            model.index(lastRow, lastColumn, rootIndex()))
        selectionModel.select(selection, command)
    else
        noIndex = Qt::ModelIndex.new
        selection = Qt::ItemSelection.new(noIndex, noIndex)
        selectionModel.select(selection, command)
    end

    @selectionRect = rect
end
updateGeometries() click to toggle source
# File examples/itemviews/chart/pieview.rb, line 464
def updateGeometries
    horizontalScrollBar.pageStep = viewport.width
    horizontalScrollBar.range = 0..[0, 2*@totalSize - viewport.width].max
    verticalScrollBar.pageStep = viewport.height
    verticalScrollBar.range = 0..[0, @totalSize - viewport.height].max
end
verticalOffset() click to toggle source
# File examples/itemviews/chart/pieview.rb, line 471
def verticalOffset
    return verticalScrollBar.value
end
visualRect(index) click to toggle source

Returns the position of the item in viewport coordinates.

# File examples/itemviews/chart/pieview.rb, line 477
def visualRect(index)
    rect = itemRect(index)
    if rect.valid?
        return Qt::Rect.new(rect.left - horizontalScrollBar.value,
                     rect.top - verticalScrollBar.value,
                     rect.width, rect.height)
    else
        return rect
    end
end
visualRegionForSelection(selection) click to toggle source

Returns a region corresponding to the selection in viewport coordinates.

# File examples/itemviews/chart/pieview.rb, line 490
def visualRegionForSelection(selection)
    ranges = selection.length

    if ranges == 0
        return Qt::Region.new(Qt::Rect.new)
    end

    # Note that we use the top and bottom functions of the selection range
    # since the data is stored in rows.

    firstRow = selection.at(0).top
    lastRow = selection.at(0).top

    for i in 0...ranges do
        firstRow = [firstRow, selection.at(i).top].min
        lastRow = [lastRow, selection.at(i).bottom].max
    end

    firstItem = model().index([firstRow, lastRow].min, 0, rootIndex())
    lastItem = model().index([firstRow, lastRow].max, 0, rootIndex())

    firstRect = visualRect(firstItem)
    lastRect = visualRect(lastItem)

    return Qt::Region.new(firstRect.unite(lastRect))
end