~ubuntu-branches/ubuntu/oneiric/koffice/oneiric-updates

« back to all changes in this revision

Viewing changes to kchart/kdchart/src/KDChartPercentLyingBarDiagram_p.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Alessandro Ghersi
  • Date: 2010-10-27 17:52:57 UTC
  • mfrom: (0.12.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20101027175257-s04zqqk5bs8ckm9o
Tags: 1:2.2.83-0ubuntu1
* Merge with Debian git remaining changes:
 - Add build-deps on librcps-dev, opengtl-dev, libqtgtl-dev, freetds-dev,
   create-resources, libspnav-dev
 - Remove needless build-dep on libwv2-dev
 - koffice-libs recommends create-resources
 - krita recommends pstoedit
 - Keep our patches
* New upstream release 2.3 beta 3
  - Remove debian/patches fixed by upstream
  - Update install files

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- Mode: C++ -*-
2
 
   KDChart - a multi-platform charting engine
3
 
   */
4
 
 
5
 
/****************************************************************************
6
 
 ** Copyright (C) 2005-2007 Klarälvdalens Datakonsult AB.  All rights reserved.
7
 
 **
8
 
 ** This file is part of the KD Chart library.
9
 
 **
10
 
 ** This file may be used under the terms of the GNU General Public
11
 
 ** License versions 2.0 or 3.0 as published by the Free Software
12
 
 ** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3
13
 
 ** included in the packaging of this file.  Alternatively you may (at
14
 
 ** your option) use any later version of the GNU General Public
15
 
 ** License if such license has been publicly approved by
16
 
 ** Klarälvdalens Datakonsult AB (or its successors, if any).
17
 
 ** 
18
 
 ** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
19
 
 ** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
20
 
 ** A PARTICULAR PURPOSE. Klarälvdalens Datakonsult AB reserves all rights
21
 
 ** not expressly granted herein.
22
 
 ** 
23
 
 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
24
 
 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
25
 
 **
26
 
 **********************************************************************/
27
 
 
28
 
#include "KDChartPercentLyingBarDiagram_p.h"
29
 
 
30
 
#include <QModelIndex>
31
 
 
32
 
#include "KDChartBarDiagram.h"
33
 
#include "KDChartTextAttributes.h"
34
 
#include "KDChartAttributesModel.h"
35
 
#include "KDChartAbstractCartesianDiagram.h"
36
 
 
37
 
using namespace KDChart;
38
 
 
39
 
PercentLyingBarDiagram::PercentLyingBarDiagram( BarDiagram* d )
40
 
    : BarDiagramType( d )
41
 
{
42
 
}
43
 
 
44
 
BarDiagram::BarType PercentLyingBarDiagram::type() const
45
 
{
46
 
    return BarDiagram::Percent;
47
 
}
48
 
 
49
 
const QPair<QPointF, QPointF> PercentLyingBarDiagram::calculateDataBoundaries() const
50
 
{
51
 
    //const int rowCount = compressor().modelDataRows();
52
 
    //const int colCount = compressor().modelDataColumns();
53
 
 
54
 
    const double xMin = 0;
55
 
    const double xMax = diagram()->model() ? diagram()->model()->rowCount( diagram()->rootIndex() ) : 0;
56
 
    double yMin = 0.0, yMax = 100.0;
57
 
    /*for( int col = 0; col < colCount; ++col )
58
 
    {
59
 
        for( int row = 0; row < rowCount; ++row )
60
 
        {
61
 
            // Ordinate should begin at 0 the max value being the 100% pos
62
 
            const QModelIndex idx = diagram()->model()->index( row, col, diagram()->rootIndex() );
63
 
            // only positive values are handled
64
 
            double value = diagram()->model()->data( idx ).toDouble();
65
 
            if ( value > 0 )
66
 
                yMax = qMax( yMax, value );
67
 
        }
68
 
    }*/
69
 
    // special cases
70
 
    if (  yMax == yMin ) {
71
 
        if ( yMin == 0.0 )
72
 
            yMax = 0.1; //we need at least a range
73
 
        else
74
 
            yMax = 0.0; // they are the same but negative
75
 
    }
76
 
    const QPointF bottomLeft( QPointF( yMin, xMin ) );
77
 
    const QPointF topRight( QPointF( yMax, xMax ) );
78
 
 
79
 
    //qDebug() << "BarDiagram::calculateDataBoundaries () returns ( " << bottomLeft << topRight <<")";
80
 
    return QPair< QPointF, QPointF >( bottomLeft,  topRight );
81
 
}
82
 
 
83
 
void PercentLyingBarDiagram::paint( PaintContext* ctx )
84
 
{
85
 
    reverseMapper().clear();
86
 
 
87
 
    const QPair<QPointF,QPointF> boundaries = diagram()->dataBoundaries(); // cached
88
 
 
89
 
    const QPointF boundLeft = ctx->coordinatePlane()->translate( boundaries.first ) ;
90
 
    const QPointF boundRight = ctx->coordinatePlane()->translate( boundaries.second );
91
 
 
92
 
    const int rowCount = compressor().modelDataRows();
93
 
    const int colCount = compressor().modelDataColumns();
94
 
 
95
 
    BarAttributes ba = diagram()->barAttributes( diagram()->model()->index( 0, 0, diagram()->rootIndex() ) );
96
 
    double barWidth = 0;
97
 
    double maxDepth = 0;
98
 
    double width = boundLeft.y() - boundRight.y();
99
 
    QPointF testVector = boundRight - boundLeft;
100
 
    double groupWidth = width/ (rowCount + 2);
101
 
    double spaceBetweenBars = 0;
102
 
    double spaceBetweenGroups = 0;
103
 
 
104
 
    if ( ba.useFixedBarWidth() ) {
105
 
        barWidth = ba.fixedBarWidth();
106
 
        groupWidth += barWidth;
107
 
 
108
 
        // Pending Michel set a min and max value for the groupWidth
109
 
        // related to the area.width
110
 
        if ( groupWidth < 0 )
111
 
            groupWidth = 0;
112
 
 
113
 
        if ( groupWidth  * rowCount > width )
114
 
            groupWidth = width / rowCount;
115
 
    }
116
 
 
117
 
    // maxLimit: allow the space between bars to be larger until area.width()
118
 
    // is covered by the groups.
119
 
    double maxLimit = rowCount * (groupWidth + ((colCount-1) * ba.fixedDataValueGap()) );
120
 
 
121
 
 
122
 
    //Pending Michel: FixMe
123
 
    if ( ba.useFixedDataValueGap() ) {
124
 
        if ( width > maxLimit )
125
 
            spaceBetweenBars += ba.fixedDataValueGap();
126
 
        else
127
 
            spaceBetweenBars = ((ctx->rectangle().width()/rowCount) - groupWidth)/(colCount-1);
128
 
    }
129
 
 
130
 
    if ( ba.useFixedValueBlockGap() )
131
 
        spaceBetweenGroups += ba.fixedValueBlockGap();
132
 
 
133
 
    calculateValueAndGapWidths( rowCount, colCount,groupWidth,
134
 
                                barWidth, spaceBetweenBars, spaceBetweenGroups );
135
 
    
136
 
    DataValueTextInfoList list;
137
 
    const double maxValue = 100.0; // always 100 %
138
 
    double sumValues = 0;
139
 
    QVector <double > sumValuesVector;
140
 
 
141
 
    //calculate sum of values for each column and store
142
 
    for( int row = 0; row < rowCount; ++row )
143
 
    {
144
 
        for( int col = 0; col < colCount; ++col )
145
 
        {
146
 
            const CartesianDiagramDataCompressor::CachePosition position( row, col );
147
 
            const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
148
 
            //if ( point.value > 0 )
149
 
            sumValues += qMax( point.value, -point.value );
150
 
            if ( col == colCount - 1 ) {
151
 
                sumValuesVector <<  sumValues ;
152
 
                sumValues = 0;
153
 
            }
154
 
        }
155
 
    }
156
 
 
157
 
    // calculate stacked percent value
158
 
    for( int curRow = rowCount - 1; curRow >= 0; --curRow )
159
 
    {
160
 
        double offset = spaceBetweenGroups;
161
 
        if( ba.useFixedBarWidth() )
162
 
            offset -= ba.fixedBarWidth();
163
 
        
164
 
        if( offset < 0 )
165
 
            offset = 0;
166
 
 
167
 
        for( int col = 0; col < colCount ; ++col )
168
 
        {
169
 
                double threeDOffset = 0.0;
170
 
            const CartesianDiagramDataCompressor::CachePosition position( curRow, col );
171
 
            const CartesianDiagramDataCompressor::DataPoint p = compressor().data( position );
172
 
            QModelIndex sourceIndex = attributesModel()->mapToSource( p.index );
173
 
            ThreeDBarAttributes threeDAttrs = diagram()->threeDBarAttributes( sourceIndex );
174
 
 
175
 
            if ( threeDAttrs.isEnabled() ){
176
 
                if ( barWidth > 0 ) {
177
 
                    barWidth =  (width - ((offset+(threeDAttrs.depth()))*rowCount))/ rowCount;
178
 
                        threeDOffset = threeDAttrs.depth();
179
 
                }
180
 
                if ( barWidth <= 0 ) {
181
 
                    barWidth = 0.1;
182
 
                    threeDOffset = (width - (offset*rowCount))/ rowCount;
183
 
                }
184
 
            }else{
185
 
                barWidth = (width - (offset*rowCount))/ rowCount;
186
 
            }
187
 
 
188
 
            const double value = qMax( p.value, -p.value );
189
 
            double stackedValues = 0.0;
190
 
            double key = 0.0;
191
 
            
192
 
            // calculate stacked percent value
193
 
            // we only take in account positives values for now.
194
 
            for( int k = col; k >= 0 ; --k )
195
 
            {
196
 
                const CartesianDiagramDataCompressor::CachePosition position( curRow, k );
197
 
                const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
198
 
                stackedValues += qMax( point.value, -point.value );
199
 
                key = point.key;
200
 
            }
201
 
 
202
 
            QPointF point, previousPoint;
203
 
            if(  sumValuesVector.at( curRow ) != 0 && value > 0 ) {
204
 
                QPointF dataPoint( ( stackedValues / sumValuesVector.at( curRow ) * maxValue ), rowCount - key );
205
 
                point = ctx->coordinatePlane()->translate( dataPoint );
206
 
                point.ry() += offset / 2 + threeDOffset;
207
 
 
208
 
                previousPoint = ctx->coordinatePlane()->translate( QPointF( ( ( stackedValues - value) / sumValuesVector.at( curRow ) * maxValue ), rowCount - key ) );
209
 
            }
210
 
            
211
 
            const double barHeight = point.x() - previousPoint.x();
212
 
            
213
 
            point.setX ( point.x() - barHeight );
214
 
 
215
 
            const QRectF rect( point, QSizeF( barHeight, barWidth ) );
216
 
            appendDataValueTextInfoToList( diagram(), list, sourceIndex, PositionPoints( rect ),
217
 
                                              Position::NorthEast, Position::SouthWest,
218
 
                                              value );
219
 
            paintBars( ctx, sourceIndex, rect, maxDepth );
220
 
        }
221
 
    }
222
 
    paintDataValueTextsAndMarkers(  diagram(),  ctx,  list,  false );
223
 
}